【问题标题】:Django REST Framework serializer - access existing foreign keyDjango REST Framework 序列化程序 - 访问现有的外键
【发布时间】:2018-06-07 00:44:47
【问题描述】:

我在我的应用程序中使用Django Rest Framework,我需要创建包含外键的新模型实例。这些引用另一个表中的现有对象,因此我不希望创建这些外部对象的新实例。此外,我无法通过它们的主键访问这些对象,因为该信息未提交(我需要过滤 POST 请求中包含的某些字段)。

我该怎么做? This 问题似乎解决了同样的问题,尽管我不清楚接受的答案是否真的解决了问题。假设我有两个模型,CategoryItem,后者中有一个 ForeignKey 字段指定类别:

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)

POST 请求的主体由 JSON 有效负载组成,类别定义为指定格式、页面和订单字段的对象:

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

然后我想我可以如下定义我的Item 序列化程序,覆盖create 以便它通过过滤适当的字段来检索正确的Category 实例,并将其设置为返回的Item 实例:

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

这是正确的做法吗?

【问题讨论】:

  • 是的,这是正确的做法。您还需要提供姓名。因此,如果一个类别不存在这些详细信息,您也可以创建新类别。如果您确定您提供了正确的类别并且已经可用,那么它就是正确的方法。
  • 刚刚回复了pk另一篇帖子stackoverflow.com/questions/42014287/…

标签: python django django-rest-framework foreign-keys


【解决方案1】:

会是这样的

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

【讨论】:

  • filter() 不会引发异常。可能你的意思是get() ??
【解决方案2】:

至少有一个错误,你应该使用get只获取一个类别作为你项目的类别,而不是使用filter获取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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-21
    • 2019-01-19
    • 1970-01-01
    • 2016-04-10
    • 2021-04-09
    相关资源
    最近更新 更多