0

So here is my files - Models.py

class Model1(models.Model):
    user = models.ForeignKey(User)
    other_fields = models.CharField(max_length=40)

Serializers.py

class MySerializer(ModelSerializer):
    class Meta:
        model = Model1
        fields = '__all__'


Here  json request
{"user_id":1, "other_fields":"details"}

and in views.py

serializer = MySerializer(data=request.data)
serializer.data

**Throws keyerror "user"**

When i try to change request parameter "user_id" to "user" it works for me . But I can't change request json. Is there any way to handle this issue in serializer?

I can set all the fields inplace of '_all_' but it is not a good solution due to large number of fields .

I also tried with -

 class MySerializer(ModelSerializer):
    user = serializers.CharField(source='user_id')
    class Meta:
        model = Model1
        fields = '__all__'

but it was not worked for me.

9
  • Why not try to use exclude param in your Meta class, pass it a tuple of not required fields. Commented Sep 4, 2018 at 13:52
  • quick question, is your database normalized? Commented Sep 4, 2018 at 13:53
  • Are you trying to get all the field on the User model as well ? Commented Sep 4, 2018 at 13:59
  • Usually, __all__ will include all model fields + fields included explicitly in serializer Commented Sep 4, 2018 at 14:10
  • @e4c5, Yes my database is noramized Commented Sep 4, 2018 at 14:15

3 Answers 3

1

try this:

class MySerializer(ModelSerializer):
    user_id = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), source='user', write_only=True)
    class Meta:
        model = Model1
        fields = '__all__'
Sign up to request clarification or add additional context in comments.

Comments

1

I assume you are using viewset class for your views. then this will work

Override the __init__ method as,

class MySerializer(ModelSerializer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if 'view' in self.context and self.context['view'].action in ['create', 'update', 'partial_update']:
            self.fields['user_id'] = self.fields.pop('user')

    class Meta:
        model = Model1
        fields = '__all__'



The ['create', 'update', 'partial_update'] are the actions of viewset class which are representing HTTP POST, HTTP PUT and HTTP PATCH respectively.

Comments

1

Try using PrimaryKeyRelatedField

class MySerializer(ModelSerializer):

    def to_internal_value(self, data):
        data = data.copy() # incase request data is immutable
        data['user'] = data['user_id']
        return super().to_internal_value(data)

    user = serializers.PrimaryKeyRelatedField(queryset=User.objects.all())

    class Meta:
        model = Model1
        fields = '__all__'

This should allow for payload:

 {"user_id": 1, "other_fields": "details"}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.