1

I have this json code:

{
  "word" : "world",
  "days" : ["tuesday", "thursday"]
}

And DRF gives me this error:

'days': [{'non_field_errors': ['Invalid data. Expected a dictionary, but got string.']}, 

This is my days serializer:

class DaysSerializer(serializers.ModelSerializer):
    class Meta:
        model = Days
        fields = ('day')

And this my top level serializer:

class WordsSerializer(serializers.ModelSerializer):
    days = DaysSerializer(many=True)
    class Meta:
          model = Words
          fields = ('word', 'days')

The Days model is:

class Days(models.Model):
    DAYS = (
        ("sunday", "Sunday"),
        ("monday", "Monday"),
        ("tuesday", "Tuesday"),
        ("wednesday", "Wednesday"),
        ("thursday", "Thursday"),
        ("friday", "Friday"),
        ("saturday", "Saturday"))

    day = models.TextField(choices=DAYS)

I want to emphasize that the input:

"days" : ["tuesday", "thursday"]

are the values not the keys in the Days table.

I read that I need to use bulk serializers. Is that the route that is recommended today? Or there is a simpler way?

If I need to use the bulk serializer library, I don't understand from their example how I could use that library for my purposes? Namely to (bulk) save the many to many entries (the Days) with one of the records (the Word).

P.S.

By the way, the relation between days and Words is M2M with no through field. Just plain M2M

P.S (2)

The way that I image this should work is DRF will look in the Days table and try to find the Day where the day column equals tuesday and make a M2M.

If it's not there, DRF needs to create the record and then make the M2M.

Same thing for thursday.

1
  • You have an issue, change fields = ('day') to fields = ('day',) Commented Oct 23, 2017 at 0:49

2 Answers 2

1

If I understand correctly you trying to pass 'days' as list of primary keys, if that the case try to change your serializer to this form:

class WordsSerializer(serializers.ModelSerializer):
days=serializers.PrimaryKeyRelatedField(queryset=Days.objects.all(),many=True)
class Meta:
      model = Words
      fields = ('word', 'days')

The error that you received raised because DRF expecting to get list of objects by default when you using your own model serializer to serialize fields. You can read more about it in DRF docs.

Sign up to request clarification or add additional context in comments.

4 Comments

To tell you the truth, the days are the values. The table days has two column 'int pk' and 'int day'. The [1, 3, 5] represents the entries (1, 1), 2, 3), (3, 5). I'd like DRF to look in the table Days and either find those values (1, 3, 5) or create them and make the M2Ms. Your suggestion is probably 100% valid. I just want to understand how would this work if I'm receiving values from the client and not the keys.
I see, Now it's more clear. in that case you have few options.
I have changed the question to better reflect what I meant. Thank you kindly for your important and helpful answer. I'll use your answer in my program but also want to find out what I can do in the scenario I described. I'll probably need it in the future. And others too probably. Seems like a common situation to be in.
So here your options: First one is to track Days resource and to have it synced on your client side, then you can know if its a new object or one that exists. Second option is to create custom field for days by inheriting from serializers.Field and overriding to_internal (where you put your logic before saving data to the DB) and to_representation methods, here link to the docs: django-rest-framework.org/api-guide/fields/#custom-fields. Third option is to override to_internal method in WordsSerializer and to implement your logic there.
1

There are multiple ways you can represent relational field in DRF serializers. For your specific case SlugRelatedField suits better.

class WordsSerializer(serializers.ModelSerializer):
    days = serializers.SlugRelatedField(many=True, slug_field='day`)

    class Meta:
        model = Words
        fields = ('word', 'days')

But remember

When using SlugRelatedField as a read-write field, you will normally want to ensure that the slug field corresponds to a model field with unique=True.

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.