Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: Serialize a model with a many-to-many relationship with a through argument

The model defines an Article and an Author classes. They are linked together with a many-to-many relationship. This relationship is defined through an custom intermediary table:

# models.py
class Article(models.Model):
    title = models.CharField(max_length=500)
    authors = models.ManyToManyField(Author, through='AuthorOrder')

class Author(models.Model):
    name = models.CharField(max_length=255)

class AuthorOrder(models.Model):
    author = models.ForeignKey(Author)
    article = models.ForeignKey(Article)
    writing_order = models.IntegerField()

The serialization should return a JSON like this:

#articles_json
{"fields":
     {
         "title": "A title",
         "authors": [
             {
                 "name":"Author 1",
                 "writing_order": 1
             },
             {
                 "name":"Author 2",
                 "writing_order": 2
             }
         }
     }
}

I've identified two solutions.

  • This one suggests to serialize the AuthorOrder field separately.
  • The second one is to use the Django Rest Framework.

I tried the twos but without success. Do you know another way to do it?

like image 409
pzijd Avatar asked Feb 01 '17 10:02

pzijd


People also ask

How do you serialize a Manytomany field?

To serialize many to many field with Python Django rest framework, we can add a serializer with many set to True . to create the PostSerializer with the tag field assigned to the TagSerializer instance. We set many to true to let us serialize many to many fields.

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.

How do I serialize Queryset?

To serialize a queryset or list of objects instead of a single object instance, you should pass the many=True flag when instantiating the serializer. You can then pass a queryset or list of objects to be serialized.


1 Answers

Thanks to your feedback, I focused on Django REST framework and it works. Here are the custom serializers I've written:

# serializers.py
from rest_framework import serializers
from app.models import Article, AuthorsOrder


class AuthorsOrderSerializer(serializer.ModelSerializer):
    author_name = serializers.ReadOnlyField(source='author.name')

    class Meta:
        model = AuthorsOrder
        fields = ('writing_order', 'author_name')


class ArticleSerializer(serializer.ModelSerializer):
    authors = AuthorsOrderSerializer(source='authorsorder_set', many=True)

    class Meta:
        model = Article
        fields = ('title', 'authors')

Sources:

  1. Include intermediary (through model) in responses in Django Rest Framework
  2. https://bitbucket.org/snippets/adautoserpa/MeLa/django-rest-framework-manytomany-through
like image 158
pzijd Avatar answered Oct 09 '22 19:10

pzijd