Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use perform_create to set a field automatically in Django Rest Framework?

I am trying to create a REST Api for my application.

urls.py in the application directory looks like this:

urlpatterns = [
    url(
        r'^professors/(?P<pk>[0-9]+)/reviews/$',
        views.ProfessorReviewList.as_view(),
        name = 'user-review-list',
    )
]

serializers.py

class ProfessorSerializer(serializers.HyperlinkedModelSerializer):
    reviews = serializers.HyperlinkedIdentityField(view_name='professor-review-list')
    class Meta:
        model = Professor
        fields = (
            'url', 'name', 'name_code', 'university',
            'department', 'total_rating_points',
            'number_of_reviews', 'rating', 'reviews',
        )

class ReviewSerializer(serializers.HyperlinkedModelSerializer):
    author = serializers.ReadOnlyField(source='author.username')

    class Meta:
        model = Review
        fields = (
            'url', 'author', 'professor',
            'created', 'updated', 'rating', 'text'
        )

And finally, my views.py looks like this:

class ProfessorReviewList(generics.ListCreateAPIView):
    queryset = Review.objects.all()
    serializer_class = ReviewSerializer
    def get_queryset(self):
        queryset = super(ProfessorReviewList, self).get_queryset()
        return queryset.filter(professor__pk=self.kwargs.get('pk'))

    permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                          IsAuthorOrReadOnly,)

    def perform_create(self, serializer):
        # The request user is set as author automatically.
        serializer.save(author=self.request.user)

What I am trying to do is get a list of all the reviews for one particular professor when I go to the URL. I also want to allow users to add a new review at this end-point if they want to. Everything works nicely, but I want a system where the user does not have to choose the professor when creating a review.

Lets say I go to /professors/1/reviews/, a list of all the reviews for the professor with pk=1 is obtained. Now, if the user adds a new review, the professor is automatically set to the professor with pk=1. The user does not get to choose. At /professors/2/reviews/, the professor field for the review is automatically set to the professor with pk=2 and so on and so on.

How can I do this? Thanks for any help.

like image 529
darkhorse Avatar asked Feb 09 '16 03:02

darkhorse


People also ask

What is Perform_create in Django?

perform_create. perform create method is used to add extra information when creating a new object. perform_create() method will not execute if you override create() method.

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.

What is ModelViewSet in Django REST framework?

ModelViewSet. The ModelViewSet class inherits from GenericAPIView and includes implementations for various actions, by mixing in the behavior of the various mixin classes. The actions provided by the ModelViewSet class are .list() , .retrieve() , .create() , .update() , .partial_update() , and .destroy() .

How do I use Mixins in Django REST framework?

Writing mixins for Django Class Based Viewsmixins override dispatch if they need to check if user if logged in, has permission. This is one of the first methods called and view determines which request method (get, post etc) is used. mixins override get_context_data() to add new data to context.


1 Answers

You should simply add the professor as you did with the author:

serializer.save(
    author=self.request.user,
    professor_id=self.kwargs.get('pk'),
)

Note that in order to avoid to pull the professor from the DB, I set the FK explicitly instead.

like image 142
Linovia Avatar answered Nov 02 '22 23:11

Linovia