代码之家  ›  专栏  ›  技术社区  ›  ChrisM

Django REST Framework序列化程序-访问现有外键

  •  3
  • ChrisM  · 技术社区  · 8 年前

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

    我该怎么做? This 这个问题似乎解决了同样的问题,尽管我不清楚公认的答案是否真的解决了这个问题。假设我有两个模型, Category Item ,带有 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)
    

    的主体 发布 请求由一个JSON负载组成,其类别定义为一个指定格式、页面和顺序字段的对象:

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

    那么我想我可以定义我的 项目 序列化程序,如下所示,重写 create 以便检索到正确的 类别 实例,并将其设置到返回的 项目 实例:

    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
    

    这样做对吗?

    2 回复  |  直到 8 年前
        1
  •  3
  •   Umar Asghar    7 年前

    这就像

    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
  •  2
  •   Ykh    8 年前

    至少有一个错误,您应该使用 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