Adding field that isn't in model to serializer in Django REST framework

前端 未结 4 2211
孤独总比滥情好
孤独总比滥情好 2020-12-28 21:24

I have a model Comment that when created may or may not create a new user. For this reason, my API requires a password field when creating a new comment. Here is my Comment

相关标签:
4条回答
  • 2020-12-28 21:55

    If anyone is curious, the solution is to override the restore_object method and add the extra instance variable to the comment object after it has been instantiated:

    def restore_object(self, attrs, instance=None):
            if instance is not None:
                instance.email = attrs.get('email', instance.email)
                instance.author = attrs.get('author', instance.author)
                instance.url = attrs.get('url', instance.url)
                instance.content = attrs.get('content', instance.content)
                instance.ip = attrs.get('ip', instance.ip)
                instance.post_title = attrs.get('post_title', instance.post_title)
                instance.post_url = attrs.get('post_url', instance.post_url)
                return instance
    
            commenter_pw = attrs.get('commenter_pw')
            del attrs['commenter_pw']
    
            comment = Comment(**attrs)
            comment.commenter_password = commenter_pw
    
            return comment
    
    0 讨论(0)
  • 2020-12-28 22:11

    Thanks for your own answer, it helped me a lot :)

    But I think this is a bit more generic, since I still want to call the method on the super serializer class

    def restore_object(self, attrs, instance=None):
        '''
        we have to ensure that the temporary_password is attached to the model
        even though it is no field
        '''
        commenter_pw = attrs.pop('comment_pw', None)
        obj = super(
            CommentCreateSerializer, self
        ).restore_object(attrs, instance=instance)
        if commenter_pw:
            obj.commenter_pw = commenter_pw
        return obj
    
    0 讨论(0)
  • 2020-12-28 22:17

    What you can do is to overwrite the pre_save or create function and take out the commenter_pw from the data fields that are sent (not sure, but you can probably take it out form request.POST or after you have serialized it), so the framework should not rise the error.

    Plus, if you have additional logic you can implement it there before saving it (such as the one for checking if the user have to be created or what).

    0 讨论(0)
  • 2020-12-28 22:22

    Previous answers didn't work on DRF3.0, the restore_object() method is now deprecated.

    The solution I have used is awful but I have not found a better one. I have put a dummy getter/setter for this field on the model, this allows to use this field as any other on the model.

    Remember to set the field as write_only on serializer definition.

    class Comment(models.Model):
        @property
        def commenter_pw():
            return None
    
        @commenter_pw.setter
        def commenter_pw(self, value):
            pass
    
    class CommentCreateSerializer(serializers.ModelSerializer):
        commenter_pw = serializers.CharField(max_length=32, write_only=True, required=False)
    
        class Meta:
            model = Comment
            fields = ('email', 'author', 'url', 'content', 'ip', 'post_title', 'post_url', 'commenter_pw')
    
    0 讨论(0)
提交回复
热议问题