AttributeError Exception: Serializer has no attribute request in DRF - python

I have written following code in serializer where I am validating data:
class MySerializer(serializers.ModelSerializer):
class Meta:
model = models.MyClass
fields = "__all__"
def validate(self, data):
role = data["role"]
roles = models.Role.objects.filter(
-->(exception) organization=self.request.user.organization
)
if role not in roles:
raise serializers.ValidationError("Invlid role selected")
return data
But I am getting following exception:
'MySerializer' object has no attribute 'request'.
And it is coming in the mentioned line.
I want to access current user in validate function. How can I do that?

If the request is provided in the context, which a ModelViewSet for example does, you can access this with:
class MySerializer(serializers.ModelSerializer):
class Meta:
model = models.MyClass
fields = '__all__'
def validate(self, data):
role = data['role']
request = self.context['request']
roles = models.Role.objects.filter(
organization__user=request.user
).distinct()
if role not in roles:
raise serializers.ValidationError('Invalid role selected')
return data

Related

Custom Validate function is not being called inside perform_create function in DRF

This is my code.
class MyViewSet(ModelViewSet):
serializer_class = MySerializer
queryset = MyClass.objects.all()
def get_serializer_class(self):
if request.user.is_superuser:
return self.serializer_class
else:
return OtherSerializer
def perform_create(self, serializer):
if request.user.is_superuser:
if serializer.is_valid():
serializer.save(organization=self.request.user.organization)
else:
employee = Employee.objects.get(user=self.request.user)
serializer.save(employee=employee, organization=self.request.user.organization)
This is my Serializer:
class MySerializer(serializers.ModelSerializer):
class Meta:
model = models.MyClass
def validate(self, data):
employee = data.get('employee')
members = Team.objects.get(id=team.id.members.all())
if employee not in members:
raise serializers.ValidationError('Invalid')
return data
The issue is, My custom validate function is not being called when I call it inside perform_create() in my ViewSet.
What might be the issue?
validate member function should be defined in the scope of the serializer class not inside class Meta. So you need to left-indent the function validate:
class MySerializer(serializers.ModelSerializer):
class Meta:
model = models.MyClass
def validate(self, data):
employee = data.get('employee')
members = Team.objects.get(id=team.id.members.all())
if employee not in members:
raise serializers.ValidationError('Invalid')
return data

AttributeError: 'Serializer' object has no attribute 'Meta' in django rest framework

I am using serializers.Serializer instead of ModelSerializer which doesn't require Meta class but it keep saying object has no attribute Meta. Iam not sure what is the issue but when I run the localserver, the main page gives error saying api fetch error and in the terminal it says AttributeError: 'Serializer' object has no attribute 'Meta'.
My view:
class ClassView(viewsets.ModelViewSet):
queryset = Class.objects.all().order_by('-created_at')
serializer_class = ClassSerializer
serializer_action_classes = {
'get_all_students_of_a_class': ClassDetailSerializer,
}
# .annotate(total_students=Count('students_in_class'))
def get_serializer_class(self):
"""
returns a serializer class based on the action
that has been defined.
"""
try:
return self.serializer_action_classes[self.action]
except (KeyError, AttributeError):
return super(ClassView, self).get_serializer_class()
def get_all_students_of_a_class(self,request,pk=None):
"""
returns a class details with all the students signed up for the
class along with the subject.
"""
id = pk
if self.is_teacher(id):
online_classes = get_object_or_404(Class, id=id)
students = Student.objects.filter(online_class__id=id)
subject_details = Subject.objects.get(online_class__id=id)
total_students_in_class = online_classes.total_students_in_class
created_at = online_classes.created_at
updated_at = online_classes.updated_at
data = {
"teacher": self.get_teacher_instance(),
'total_students_in_class': total_students_in_class,
"students_in_class": students,
"subject": subject_details,
'created_at': created_at,
'last_updated_at': updated_at,
}
serializer_class = self.get_serializer_class()
serializer = serializer_class(data)
return Response(serializer.data, status=status.HTTP_200_OK)
My serializer:
class ClassDetailSerializer(serializers.Serializer):
teacher = serializers.StringRelatedField()
subject = SubjectLevelSerializer()
total_students_in_class = serializers.ReadOnlyField()
students_in_class = serializers.StringRelatedField(many=True)
created_at = serializers.DateTimeField(read_only=True)
last_updated_at = serializers.DateTimeField(read_only=True)
My url:
path("class/<int:pk>/",teacher.ClassView.as_view({"get": "get_all_students_of_a_class","delete":"destroy"}),
),
However it works and I can perform action if I go to localhost/admin and other api calls from localhost.
Add a Meta class with model = YourModel
class ExampleDetailSerializer(serializers.Serializer):
employee = serializers.StringRelatedField()
person = PersonSerializer()
class Meta:
model = Example # model name
fields = ('__all__')
Try to use "ViewSet" instead of "ModelViewSet". And while using ViewSet make sure to define list, create, etc. function by your own.

data in serializer is always empty

I have following serializer:
class AdminSerializer(serializers.Serializer):
def validate(self, data):
user = data.get("user_pk")
total_licenses = data.get("total_licenses")
#here i do some validation with the vars
But my data is always empty. This is part of my view
serializer_class = self.get_serializer_class()
serializer = serializer_class(
data=self.request.data,
)
serializer.is_valid(raise_exception=True)
This is my unit test request:
response = self.client.patch(
url,
data={"user_pk": self.user.pk, "total_licenses": 3},
)
Why is my 'data' always empty?
You have to explicitly specify fields in your serializer:
class AdminSerializer(serializers.Serializer):
user_pk = serializers.IntegerField()
total_licenses = serializers.IntegerField()
def validate(self, data):
...
You need to call serializer.save() before you can access .data attribute on a serializer. Otherwise, you can access .validated_data attribute on your serializer

Original exception text was: 'QuerySet' object has no attribute 'client'

I got AttributeError when attempting to get a value for field client on serializer ClientSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the QuerySet instance.
models.py
class Box(models.Model):
box = models.IntegerField()
controller = models.ForeignKey(Controller, related_name='boxes', on_delete=models.CASCADE)
def __str__(self):
return str(self.box)
class Client(models.Model):
client = models.CharField(max_length=30)
cpf = models.IntegerField()
box = models.OneToOneField(
Box,
on_delete=models.CASCADE,
primary_key=True
)
def __str__(self):
return self.client
serializers.py
class ClientSerializer(serializers.ModelSerializer):
class Meta:
model = Client
fields = [
"id",
"client",
"cpf",
"box",
]
class BoxSerializer(serializers.ModelSerializer):
class Meta:
model = Box
fields = [
"id",
"box",
"controller"
]
views.py
class ClientViewSet(viewsets.ModelViewSet):
serializer_class = ClientSerializer
queryset = Client.objects.all()
def list(self, request, store_pk=None, locker_pk=None, controller_pk=None, box_pk=None):
queryset = Client.objects.filter(box=box_pk, box__controller=controller_pk, box__controller__locker=locker_pk, box__controller__locker__store=store_pk)
serializer = ClientSerializer(queryset, context={'request': request})
return Response(serializer.data)
def retrieve(self, request, store_pk=None, locker_pk=None, controller_pk=None, box_pk=None):
queryset = Client.objects.filter(box=box_pk, box__controller=controller_pk, box__controller__locker=locker_pk, box__controller__locker__store=store_pk)
client = get_object_or_404(queryset)
serializer = ClientSerializer(client, context={'request': request})
return Response(serializer.data)
I'm trying to get the object client on lockers/1/controllers/1/boxes/1/client/
which is OneToOneField relations with boxes and It's in a nested router
I already tried use decorator #action but yet didn't work.
Anyone know why it's not finding the correct object attribute ?
For a list method you should use many=True parameter when you're creating a new serializer instance:
serializer = ClientSerializer(queryset, context={'request': request}, many=True)
In case of retrieve only one object should be received. Instead of
client = get_object_or_404(queryset)
you should call first(), last() (or most basically and clearly - .get(pk=pk)) on queryset to retrieve only one item from QuerySet. Then you should just execute:
# client is one of elements of your queryset
serializer = ClientSerializer(client, context={'request': request})

DRF Serializer validation by database column

I have a custom serializer like this--
class customSerializers(serializers.Serializer):
token = serializers.CharField(max_length=12)
And I have a model like this
class UserToken(models.Model):
user = models.ForeignKey(User)
token = models.CharField(max_length=12)
Now I want to validate my customSerializers token field. The token value has to exists in the UserToken model and belongs to the current user.
** I Don't want to use model serializer.
You should pass user to serializer, then implement validation on the field:
class CustomSerializer(serializers.Serializer):
token = serializers.CharField(max_length=12)
def validate_token(self, value):
user_id = self.context.get('user_id')
return UserToken.objects.filter(user__id=user_id, token=value).exists()
in your view:
serializer = CustomSerializer(... , context={'user_id': request.user.id})
if serializer.is_valid():
...

Categories