Django REST Framework serializer - access existing foreign key

为君一笑 提交于 2019-12-12 19:40:03

问题


I am using Django Rest Framework in my app, and I need to create new model instances which contain foreign keys. These refer to existing objects in another table, so I don't want new instances of these foreign objects to be created. Also I cannot access these objects via their primary keys, as that information is not submitted (I need to filter on certain fields which are included in the POST request).

How do I do this? This question seems to address the same issue, though it's not clear to me that the accepted answer actually solves the problem. Suppose I have two models, Category and Item, with a ForeignKey field in the latter specifying the category:

class Category(models.Model):
    name = models.TextField()
    format = models.TextField()
    page = models.IntegerField(default=1)
    order = models.IntegerField(default=1)

class Item(models.Model):
    username = models.TextField()
    title = models.TextField()
    category = models.ForeignKey('Category', null=True)
    data = JSONField(null=True, blank=True)

The body of the POST request consists of a JSON payload, with the category defined as an object specifying the format, page and order fields:

POST /api/items
{
  "username" : "test",
  "title" : "foo",
  "category" : {
    "format" : "A",
    "page" : 2,
    "order" : 1
  },
  "data" : [1,2,3,4,5]
}

Then I suppose I might define my Item serializer as follows, overriding create so that it retrieves the right Category instance by filtering on the appropriate fields, and setting it into the returned Item instance:

class ItemSerializer(serializers.ModelSerializer):
    category = CategorySerializer()
    data = serializers.ListField()

    class Meta:
        model = Item
        fields = ('username', 'title', 'category', 'data')

    def create(self, validated_data):
        category_dict = validated_data.pop('category')
        item = Item.objects.create(**validated_data)
        format = category_dict.format
        page = category_dict.page
        order = category_dict.order
        item.category = Category.objects.get(format=format, page=page, order=order)
        return item

Is this the right way to do it?


回答1:


It will be like

try:
    category = Category.objects.get(format=format, page=page, order=order)
except Category.DoesNotExist:
    # either make it None or create new category, depends on your requirement
    category = None
    # or create new category
except Category.MultipleObjectsReturned:
    category = category.first() # it depends on your requirement
item.category = category



回答2:


At least there is one error,you should use get to get only one category as you item's category instead of use filter to get queryset.

class ItemSerializer(serializers.ModelSerializer):
    category = CategorySerializer()
    data = serializers.ListField()

    class Meta:
        model = Item
        fields = ('username', 'title', 'category', 'data')

    def create(self, validated_data):
        category_dict = validated_data.pop('category')
        item = Item.objects.create(**validated_data)
        format = category_dict.format
        page = category_dict.page
        order = category_dict.order
        try:
            item.category = Category.objects.get(format=format, page=page, order=order)
        except  Category.DoesNotExist:
            pass
        except  Category.MultipleObjectsReturned:
            pass
        return item


来源:https://stackoverflow.com/questions/47974094/django-rest-framework-serializer-access-existing-foreign-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!