Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework - Check/manipulate data (by some logic) before saving to database

I am new to Django Rest Framework. I have a serializer like this:

class ReviewSerializer(serializers.ModelSerializer):
    class Meta:
        model = Review
        fields = (
            'user',
            'course',
            'major',
            'title',
            'text',
            'placements',
            'faculty',
            'infrastructure',
            'students',
            'extra_curricular',
            'passing_year',
        )

models.py

class Review(models.Model):
    user = models.ForeignKey(to=User, related_name='reviews')
    course = models.ForeignKey(to=Course, related_name='reviews')
    major = models.ForeignKey(to=Major, related_name='reviews', blank=True, null=True)
    title = models.TextField(db_index=True)
    text = models.TextField(db_index=True)
    placements = models.FloatField(default=0.0)
    faculty = models.FloatField(default=0.0)
    infrastructure = models.FloatField(default=0.0)
    students = models.FloatField(default=0.0)
    extra_curricular = models.FloatField(default=0.0)
    passing_year = models.PositiveSmallIntegerField(default=2014)
    created_on = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now=True)

And the views.py

class ReviewViewSet(viewsets.ModelViewSet):
    """
    College API
    """
    queryset = Review.objects.all()
    serializer_class = ReviewSerializer
    paginate_by = 5

Now,whenever I post something to the API it directly gets saved to the database if the validation passes successfully. What I need is, I want to check and apply some conditions on the data using some business logic before it saves the data to the database. So that if the condition is true only then the data gets saved, or else it returns a error message to the client.

like image 228
Iqbal Avatar asked Dec 05 '14 10:12

Iqbal


People also ask

What is the difference between ModelSerializer and HyperlinkedModelSerializer?

The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys. By default the serializer will include a url field instead of a primary key field.

How does Django validate data in serializer?

Validation in Django REST framework serializers is handled a little differently to how validation works in Django's ModelForm class. With ModelForm the validation is performed partially on the form, and partially on the model instance. With REST framework the validation is performed entirely on the serializer class.

What is the purpose of serialization in Django REST framework?

Serializers in Django REST Framework are responsible for converting objects into data types understandable by javascript and front-end frameworks. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.

How do you pass extra context data to Serializers in Django REST framework?

In function based views we can pass extra context to serializer with "context" parameter with a dictionary. To access the extra context data inside the serializer we can simply access it with "self. context". From example, to get "exclude_email_list" we just used code 'exclude_email_list = self.


1 Answers

I assume you are using the new version 3.0. Then you need to put your validation logic into your serializer ReviewSerializer (See http://www.django-rest-framework.org/topics/3.0-announcement/#serializers).

So if you want to create a validation of the fields you should overload the def validate_<fieldname>(self, value). For example if you want Review.placements be >= 0.0, you may write

class ReviewSerializer(serializers.ModelSerializer):
[...]
    def validate_placements(self, value):
         if value >= 0.0:
              return value
         raise serializers.ValidationError('placements should be non-negative.')
[...]

If you need more advanced validation, e.g. to validate two dependent fields, then you need to override the def validate(self, attrs).

For example to have created_on <= updated_on

class ReviewSerializer(serializers.ModelSerializer):
[...]
    def validate(self, attrs):
        if attrs['created_on'] <= attrs['update_on']:
            return attrs
        raise ValidationError('Date of creation should be before update date.')
[...]

If you now add some objects over REST-API, the validation will be called automatically. You don't have to override the methods of ModelViewSet.

In the link above and in www.django-rest-framework.org/api-guide/serializers/#validation are more hints.

like image 136
user3142459 Avatar answered Sep 29 '22 19:09

user3142459