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')
Related
I'm new in DRF: ¿Can I create a filter in a function in Django Rest Framework, not created it in a Class, for use in a view? I'm trying a filter for search by: document and document_type.
Ty
My code:
#model
class Account(models.Model):
'''Modelo para la gestión de cuentas'''
document_type = models.CharField('Tipo documento', null=True, max_length=20, choices=DOCUMENT_TYPE)
document = models.CharField('Documento',null=True, max_length=18)
first_name = models.CharField('Nombres / razón social',null=True, max_length=100)
last_name = models.CharField('Apellidos', null=True, max_length=100)
phone = models.CharField('Teléfono fijo', max_length=7, null=True, blank=True)
cellphone = models.CharField('Celular', max_length=10, null=True, blank=True)
email = models.EmailField('Correo', max_length=100, null=True, blank=True )
address = models.CharField('Dirección', max_length=70, null=True, blank=True)
gender = models.CharField('Genero',null=True, max_length=1, choices=GENDER_TYPE)
affiliate_type = models.CharField('Tipo de afiliado',null=True, max_length=12, choices=AFFILIATE_TYPE)```
#view
```class AccountList(APIView):
"""
List all accounts, or create a new account....
"""
def get(self, request, format=None):
account = Account.objects.all()
serializer = AccountSerializer(account, many=True)
filter_class = AccountFilter
filter_backends = [filters.SearchFilter]
return Response({'data':serializer.data},status=status.HTTP_200_OK)
def post(self, request, format=None):
serializer = AccountSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response({'Message':'Registro creado exitosamente'}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)```
#filter
class AccountFilter(django_filters.rest_framework.FilterSet):
class Meta:
model = Account
fields = {
'document': ['exact'],
'document_type': ['exact']
}
ordering_fields = ('document')
You can use self.filter_queryset(queryset) to filter queryset using filter class.
class AccountList(APIView):
def get(self, request, format=None):
self.filter_class = AccountFilter
self.filter_backends = [filters.SearchFilter]
account_qs = Account.objects.all()
account = self.filter_queryset(account_qs)
serializer = AccountSerializer(account, many=True)
return Response({'data':serializer.data},status=status.HTTP_200_OK)
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)
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)
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
This is probably a very simple question, but I cant seem to solve it.
I have a ModelSerializer like so:
class UserSerializer(serializers.ModelSerializer):
# http -v POST http://127.0.0.1:8000/user/user-list/ email="f#b.de" password="123"
def create(self, validated_data):
user = UserModel.objects.create(
email=validated_data['email']
)
user.set_password(validated_data['password'])
user.is_active = False
user.save()
return user
class Meta:
model = UserModel
fields = (
'email',
'password',
'is_active',
'company',
'name',
)
read_only_fields = ('is_active',)
extra_kwargs = {
'password': {'write_only': True},
}
The corresponding view looks like this:
class UserDetail(APIView):
permission_classes = (permissions.IsAuthenticated,)
def get(self, request):
try:
user = request.user
serializer = UserMailSerializer(user)
print(serializer.data)
return Response(serializer.data, status=status.HTTP_200_OK)
except UserModel.DoesNotExist:
return Response(serializer.data, status=status.HTTP_401_UNAUTHORIZED)
When I sent a GET request the serializer.data will only return the 'email' address (I am using a custom User Model with the email as primary identification).
I want to return all the fields that are not specified as write_only. How Do I achieve this?
You are using UserMailSerializer serializer class in your views, which may be the wrong one. Use UserSerializer serializer instead
class UserDetail(APIView):
permission_classes = (permissions.IsAuthenticated,)
def get(self, request):
try:
user = request.user
serializer = UserSerializer(user) # change is here <<<<<
print(serializer.data)
return Response(serializer.data, status=status.HTTP_200_OK)
except UserModel.DoesNotExist:
return Response(serializer.data, status=status.HTTP_401_UNAUTHORIZED)