简体   繁体   中英

Django Rest Framework - Interrelated serializers

Given the following models for which two have a ManyToMany relationship with the first, how can I construct a serializer for all three models?

This is where the importance of ordering in Python is turning to be an issue.

class Trail(models.Model):
    '''
    Main model for this application.  Contains all information for a particular trail
    '''
    trail_name = models.CharField(max_length=150)
    active = models.BooleanField(default=True)
    date_uploaded = models.DateTimeField(default=now())
    owner = models.ForeignKey(Account, default=1)


    class Meta:
        ordering = ('trail_name', )

class Activity(models.Model):
    '''
    A many to many join table to map an activity name to a trail.  A trail can have many
    activities
    '''
    name = models.CharField(max_length=40, unique=True)
    trails = models.ManyToManyField(Trail)

    class Meta:
        ordering = ('name', )


class Surface(models.Model):
    '''
    A many to many join table to map a surface type to many trails.  A trail can have many
    surface types.
    '''
    type = models.CharField(max_length=50, db_column='surface_type', unique=True)
    trails = models.ManyToManyField(Trail)

    class Meta:
        ordering = ('type', )

I have the following serializers in serializers.py :

class TrailSerializer(serializers.ModelSerializer):
    owner = AccountSerializer()
    activities = ActivitySerializer()

    class Meta:
        model = Trail
        fields = ('trail_name', 'active', 'date_uploaded', 'owner', 'activities', )


class ActivitySerializer(serializers.ModelSerializer):
    trails = TrailSerializer()

    class Meta:
        model = Activity
        fields = ('trails', 'name', )


class SurfaceSerializer(serializers.ModelSerializer):
    trails = TrailSerializer()

    class Meta:
        model = Surface
        fields = ('trails', 'type', )

My question is, short of creating another file to contain ActivitySerializer and SurfaceSerializer , how can I ensure that TrailSerializer works as expected in order to include Activity and Surface references during serialization?

Use Marshmallow (serialization library inspired in part by DRF serializers). It solves this problem, by allowing nested schemas to be reference as strings. See Marshmallow: Two Way Nesting

class AuthorSchema(Schema):
    # Make sure to use the 'only' or 'exclude' params to avoid infinite recursion
    books = fields.Nested('BookSchema', many=True, exclude=('author', ))
    class Meta:
        fields = ('id', 'name', 'books')

class BookSchema(Schema):
    author = fields.Nested(AuthorSchema, only=('id', 'name'))
    class Meta:
        fields = ('id', 'title', 'author')

You can use directly or use via django-rest-marshmellow by Tom Christie , which allows use of Marshmallow, while maintaining the same API as REST framework's Serializer class.

I'm not aware of a way to achieve the same result using just DRFs serializers.

See also: Why Marshmallow?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM