添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information. Learn more class Item(models.Model): name = models.CharField(max_length=100) category = models.ForeignKey(Category, related_name='items') def __unicode__(self): return self.name

To create a serializer for the categories I'd do:

class CategorySerializer(serializers.ModelSerializer):
    items = serializers.RelatedField(many=True)
    class Meta:
        model = Category

... and this would provide me with:

[{'items': [u'Item 1', u'Item 2', u'Item 3'], u'id': 1, 'name': u'Cat 1'},
 {'items': [u'Item 4', u'Item 5', u'Item 6'], u'id': 2, 'name': u'Cat 2'},
 {'items': [u'Item 7', u'Item 8', u'Item 9'], u'id': 3, 'name': u'Cat 3'}]

How would I go about getting the reverse from an Item serializer, ie:

[{u'id': 1, 'name': 'Item 1', 'category_name': u'Cat 1'},
{u'id': 2, 'name': 'Item 2', 'category_name': u'Cat 1'},
{u'id': 3, 'name': 'Item 3', 'category_name': u'Cat 1'},
{u'id': 4, 'name': 'Item 4', 'category_name': u'Cat 2'},
{u'id': 5, 'name': 'Item 5', 'category_name': u'Cat 2'},
{u'id': 6, 'name': 'Item 6', 'category_name': u'Cat 2'},
{u'id': 7, 'name': 'Item 7', 'category_name': u'Cat 3'},
{u'id': 8, 'name': 'Item 8', 'category_name': u'Cat 3'},
{u'id': 9, 'name': 'Item 9', 'category_name': u'Cat 3'}]

I've read through the docs on reverse relationships for the rest framework but that appears to be the same result as the non-reverse fields. Am I missing something obvious?

Just use a related field without setting many=True.

Note that also because you want the output named category_name, but the actual field is category, you need to use the source argument on the serializer field.

The following should give you the output you need...

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.RelatedField(source='category', read_only=True)
    class Meta:
        model = Item
        fields = ('id', 'name', 'category_name')
                if you want to retrieve all the fields of category model make the category serializer and have it in code like category_name = CategorySerliazer()
– Faizan Ali
                Dec 1 '14 at 11:31
                I tried to do this but i'm getting a error  Relational field must provide a 'queryset' argument, or set read_only='True' 
– ePascoal
                Jul 23 '15 at 9:03
                or providing a queryset attribute if you want to support create/update, something like: category_name = serializers.RelatedField(source='category', queryset=Category.objects.all())    I suppose.
– stelios
                Oct 13 '16 at 18:17
                If you get AssertionError:... use this answer stackoverflow.com/a/44530606/5403449
– Josh
                Apr 29 '19 at 13:00

In the DRF version 3.6.3 this worked for me

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.CharField(source='category.name')
    class Meta:
        model = Item
        fields = ('id', 'name', 'category_name')

More info can be found here: Serializer Fields core arguments

  • create a property in your Item model that returns the category name and
  • expose it as a ReadOnlyField.
  • Your model would look like this.

    class Item(models.Model):
        name = models.CharField(max_length=100)
        category = models.ForeignKey(Category, related_name='items')
        def __unicode__(self):
            return self.name
        @property
        def category_name(self):
            return self.category.name
    

    Your serializer would look like this. Note that the serializer will automatically get the value of the category_name model property by naming the field with the same name.

    class ItemSerializer(serializers.ModelSerializer):
        category_name = serializers.ReadOnlyField()
        class Meta:
            model = Item
    
    class ItemSerializer(serializers.ModelSerializer):
        category_name = serializers.ReadOnlyField(source='category.name')
        class Meta:
            model = Item
            fields = "__all__"
    

    Worked on 08/08/2018 and on DRF version 3.8.2:

    class ItemSerializer(serializers.ModelSerializer):
        category_name = serializers.ReadOnlyField(source='category.name')
        class Meta:
            model = Item
            read_only_fields = ('id', 'category_name')
            fields = ('id', 'category_name', 'name',)
    

    Using the Meta read_only_fields we can declare exactly which fields should be read_only. Then we need to declare the foreign field on the Meta fields (better be explicit as the mantra goes: zen of python).

    Simple solution source='category.name' where category is foreign key and .name it's attribute.

    from rest_framework.serializers import ModelSerializer, ReadOnlyField
    from my_app.models import Item
    class ItemSerializer(ModelSerializer):
        category_name = ReadOnlyField(source='category.name')
        class Meta:
            model = Item
            fields = __all__