I have the following code working perfectly. I can create a Post
object from DRF panel by selecting an image and a user. However I want DRF to populate the user field by the currently logged in user.
models.py
class Post(TimeStamped):
user = models.ForeignKey(User)
photo = models.ImageField(upload_to='upload/')
hidden = models.BooleanField(default=False)
upvotes = models.PositiveIntegerField(default=0)
downvotes = models.PositiveIntegerField(default=0)
comments = models.PositiveIntegerField(default=0)
serializers.py
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ['id', 'user', 'photo']
views.py
class PhotoListAPIView(generics.ListCreateAPIView):
queryset = Post.objects.filter(hidden=False)
serializer_class = PostSerializer
authentication_classes = (SessionAuthentication, BasicAuthentication)
permission_classes = (IsAuthenticated,)
How can I do this?
It depends on your use case. If you want it to be "write-only", meaning DRF automatically populates the field on write and doesn't return the on read, the most straight-forward implementation according to the docs would be with a HiddenField:
If you want want it to be readable, you could use a PrimaryKeyRelatedField while being careful that your serializer pre-populates the field on write - otherwise a User could set the
user
field pointing to some other random User.Finally, note that if you're using the more verbose
APIView
instead ofgenerics.ListCreateAPIView
, you have to overwritecreate
instead ofperform_create
like so:Try this:
@DaveBensonPhillips's answer might work in your particular case for some time, but it is not very generic since it breaks OOP inheritance chain.
ListCreateAPIView
inherits fromCreateModelMixin
which saves the serializer already. You should always strive to get the full chain of overridden methods executed unless you have a very good reason not to. This way your code stays DRY and robust against changes:You can use CurrentUserDefault:
See http://www.django-rest-framework.org/api-guide/validators/#currentuserdefault
Off the top of my head, you can just override the
perform_create()
method:Give that a shot and let me know if it works
You will have to override the default behavior of how
generics.ListCreateAPIView
creates an object.The
.get_serializer_class()
is not necessary as you can specify which fields are read-only from your serializer, but based on the projects I have worked on, I usually end up with 'asymmetric' serializers, i.e. different serializers depending on the intended operation.