MODELS.py
class MyPicture(models.Model):
picture = models.ImageField(upload_to=join_path('pictures'))
SERIALIZERS.PY
class MyPictureSerializer(serializers.ModelSerializer):
picture = serializers.ImageField(required=True, use_url=True)
class Meta:
model = MyPicture
fields = ['id', 'picture']
VIEWS.PY
class MyPictureAPI(APIView):
parser_classes = (FormParser, FileUploadParser)
def post(self, request):
print(request.FILES)
serializer = MyPictureSerializer(data=request.FILES)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
if I print(request.FILES) ,
it is {'file': <InMemoryUploadedFile: cloud_vazifa_01.png (multipart/form-data; boundary=--------------------------563292059865884360215980)>}
here key is 'file' but i have saved it to model and serializer as 'picture'
so serilizer is invalid
help me to save picture to models
enter image description here
I think you need to use the FileField, not ImageField.
class MyPictureSerializer(serializers.ModelSerializer):
picture = serializers.FileField(
max_length = 10000000,
allow_empty_file = False
use_url = False,
)
class Meta:
model = MyPicture
fields = ['id', 'picture']
def create(self, validated_data):
image = validated_data.pop('picture')
return MyPicture.objects.create(picture = image)
In MyPictureAPI,
class MyPictureAPI(APIView):
def post(self, request):
serializer = MyPictureSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
Related
I am new to DRF. I am very interested in application of generic views. I want to rewrite the following code with generic DRF view RetrieveAPIView:
views.py
class ProductDetail(APIView):
def get_object(self, category_slug, product_slug):
try:
return Product.objects.filter(category__slug=category_slug).get(slug=product_slug)
except Product.DoesNotExist:
raise Http404
def get(self, request, category_slug, product_slug, format=None):
product = self.get_object(category_slug, product_slug)
serializer = ProductSerializer(product)
return Response(serializer.data)
urls.py
urlpatterns = [
path('products/<slug:category_slug>/<slug:product_slug>/',
ProductDetail.as_view())
]
models.py
class Category(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField()
class Meta:
ordering = ('name',)
def __str__(self):
return self.name
def get_absolute_url(self):
return f'/{self.slug}/'
class Product(models.Model):
category = models.ForeignKey(
Category, related_name='products', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
slug = models.SlugField()
description = models.TextField(blank=True, null=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
image = models.ImageField(upload_to='uploads/', blank=True, null=True)
thumbnail = models.ImageField(upload_to='uploads/', blank=True, null=True)
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-date_added',)
def __str__(self):
return self.name
def get_absolute_url(self):
return f'{self.category.slug}/{self.slug}/'
How can I use RetrieveAPIView instead of above APIView?
I tried to add a custom mixin, did not help:
class MultipleFieldLookupMixin:
def get_object(self):
queryset = self.get_queryset() # Get the base queryset
queryset = self.filter_queryset(queryset) # Apply any filter backends
multi_filter = {field: self.kwargs[field] for field in self.lookup_fields}
obj = get_object_or_404(queryset, **multi_filter) # Lookup the object
self.check_object_permissions(self.request, obj)
return obj
class ProductDetail(MultipleFieldLookupMixin, RetrieveAPIView):
queryset = Product.objects.filter(category__slug=category_slug).get(slug=product_slug)
serializer = ProductSerializer
lookup_fields = ['category_slug', 'product_slug']
Does not work.
I have troubles with my code in deleting a specific loan_id(primary key). My post method works good but my delete method doesn´t. Here's my code:
views.py:
class SolicitudPrestamoViewSet(viewsets.mixins.CreateModelMixin,viewsets.mixins.DestroyModelMixin,viewsets.GenericViewSet):
permission_classes = [IsAdminUser]
serializer_class = SucursalSerializer
queryset = Prestamo.objects.all()
lookup_field = 'loan_id'
def get(self, request, format=None,):
serializer = SucursalSerializer()
return Response(serializer.data)
def delete(self, request, loan_id, format=None):
object = self.get_object(loan_id)
object.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
models.py:
class Prestamo(models.Model):
loan_id = models.AutoField(primary_key=True)
loan_type = models.CharField(max_length=20,
choices = [('PERSONAL', 'PERSONAL'), ('HIPOTECARIO', 'HIPOTECARIO'), ('PRENDARIO', 'PRENDARIO')])
loan_date = models.DateField()
loan_total = models.IntegerField()
customer_id = models.IntegerField()
class Meta:
db_table = 'prestamo'
In viewset you should use destroy method to handle DELETE requests:
class SolicitudPrestamoViewSet(viewsets.mixins.CreateModelMixin,viewsets.mixins.DestroyModelMixin,viewsets.GenericViewSet):
permission_classes = [IsAdminUser]
serializer_class = SucursalSerializer
queryset = Prestamo.objects.all()
lookup_field = 'loan_id'
def destroy(self, request, loan_id):
object = self.get_object(loan_id)
object.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
I have a model Classroom which has a field code that is generated automatically
from django.utils.crypto import get_random_string
class Classroom(models.Model):
CODE_LEN = 16
teacher = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
name = models.CharField(max_length=250)
subject = models.CharField(max_length=50)
code = models.CharField(max_length=CODE_LEN, unique=True)
def save(self, *args, **kwargs):
while True:
self.code = get_random_string(length=16)
if not Classroom.objects.filter(code=self.code).exists():
break
super().save(*args, **kwargs)
The serializer for Classroom is -
class ClassroomSerializer(serializers.ModelSerializer):
class Meta:
model = Classroom
fields = ('teacher', 'name', 'subject', 'code')
This is the view for creating new Classroom -
class ListCreateClassroom(APIView):
def get(self, request):
classrooms = Classroom.objects.all()
serializer = ClassroomSerializer(classrooms, many=True)
return Response(serializer.data)
def post(self, request):
token = request.headers.get('Authorization').split()[1]
token_obj = AccessToken.objects.get(token=token)
teacher = token_obj.user.pk
request.data.update({"teacher": teacher})
serializer = ClassroomSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
When I send an api request to add new classroom, the request doesn't contain the code field because of which serializer.is_valid() throws error.
One way to solve it would be to create a code in the view and add it to the request.
But, is there a better way?
Simply set the code field in the serializer to read_only=True:
class ClassroomSerializer(serializers.ModelSerializer):
code = serializers.CharField(read_only=True)
class Meta:
model = Classroom
fields = ('teacher', 'name', 'subject', 'code')
* i have * router.register(r'reseller/', views.UserViewSet)
and router.register(r'one/', views.OneLViewSet)
I want to make nested url like 'reseller/ or {pk}/one/
But i'm failed.
I tried adding DynamicRelationField to User Model but not worked.
my user_model
phone = models.CharField(_('phone number'), max_length=30, blank=True)
address = models.CharField(_('reseller address'), max_length=220, blank=True)
OneL model
id = models.AutoField(_('lottery id'), unique=False, primary_key=True, auto_created=True,)
lno = models.CharField(_('1000ks lottery'), max_length=8, unique=True)
name = models.CharField(_('customer name'), max_length=100, )
reseller = models.ForeignKey('lotto_app.User', on_delete=models.CASCADE)
user_serializer
class UserSerializer(serializers.DynamicModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email', 'phone', 'address', )
oneL serializer
class OneLSerializer(serializers.DynamicModelSerializer):
reseller = fields.DynamicField(source='reseller.username', read_only=True)
class Meta:
model = OneL
fields = (
'id', 'lno', 'name', 'reseller', 'phone', 'address', 'nth', 'is_winner', 'prize_details', 'created_at',
'updated_at')
user dynamicviewset
class UserViewSet(DynamicModelViewSet):
permission_classes = (IsAdmin, IsAuthenticated)
model = User
queryset = User.objects.all()
serializer_class = UserSerializer
OneLviewSet
class OneLViewSet(DynamicModelViewSet):
permission_classes = (IsAuthenticated, IsOwner)
model = OneL
queryset = OneL.objects.all()
serializer_class = OneLSerializer
def create(self, request, *args, **kwargs):
serializer = OneLSerializer(data=request.data)
if serializer.is_valid():
serializer.save(reseller=request.user)
return Response(serializer.data)
def list(self, request, *args, **kwargs):
queryset = OneL.objects.filter(reseller=request.user)
serializer = OneLSerializer(queryset, many=True)
return Response(serializer.data)
I want to change this.url
router.register(r'reseller', views.UserViewSet)
router.register(r'one', views.OneLViewSet)
urlpatterns = [
path('api/saledatas/', include(router.urls))
]
TO THIS
router.register(r'reseller', views.UserViewSet)
router.register(r'reseller/{pk}/one', views.OneLViewSet) #or <int:pk>
urlpatterns = [
path('api/saledatas/', include(router.urls))
]
After change
error-- "Request URL: http://localhost:8000/api/saledatas/reseller/1/one/" Not Found!
And How to make http://localhost:8000/api/saledatas/reseller/1/one/ to be work.
create action in Userviewset
#action(detail=True, methods=["get"])
def one(self, request):
''' to get instance just do get_object() it'll give reseller instance '''
user = self.get_object()
ones = user.onel_set.all()
''' now you can work on one '''
i extending a user model and creating a serializer that can register a user but i think i have a problem with the Register serializer
i have tried changing the input but i cant tell where the problem is
class Register(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
address = models.CharField(max_length=70)
phone = models.IntegerField()
register_as = models.CharField(max_length=20)
# register serializer
class RegisterSerializer(serializers.ModelSerializer):
model = Register
fields = ('id', 'username', 'email', 'address', 'phone', 'register_as', 'password')
extra_kwargs = {'password': {'write_only':True}}
def create(self, validated_data):
user = User.objects.create_user(validated_data['username'], validated_data['email'], validated_data['password'])
return user
#register API
class RegisterAPI(generics.GenericAPIView):
serializer_class = RegisterSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()
return Response({
'user': UserSerializer(user,
context=self.get_serializer_context()).data,
'token': AuthToken.objects.create(user)[1]
})
i expect it to return the fields in the user model plus the ones i added in the model