如何从Django获取内部联接中的某些字段?

时间:2018-07-28 20:15:48

标签: django django-models django-rest-framework

我正在尝试从Django数据库中获取一些字段。

我的模特:

class Category(models.Model):
    name = models.CharField(max_length=200)

    def __str__(self):
        return self.name

class Product(models.Model):
    product_Description = models.CharField(max_length=255)
    product_Comments = models.CharField(max_length=255)
    size = models.CharField(max_length=10, null=True)
    product_Status = models.BooleanField(default=True)
    category = models.ForeignKey(Category,  on_delete=models.CASCADE, null=True)
    date_Created = models.DateTimeField(default=datetime.now, blank=True)
    date_Modified = models.DateTimeField(default=datetime.now, blank=True)

    def __str__(self):
        return self.product_Description

我的序列化器:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ('id', 'product_Description', 'product_Comments', 'product_Status', 'category', 'date_Created',
                  'date_Modified')

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ('id', 'name')
class InventorySerializers(serializers.ModelSerializer):
    model_b = CategorySerializer(source="category")
    class Meta:
        model = Product
        fields = ('id', 'product_Description', 'product_Comments', 'product_Status', 'category', 'date_Created',
                  'date_Modified', 'model_b')

和我的view.py:

class inventoryList(generics.ListCreateAPIView):
    queryset = Product.objects.select_related('category')

    print(str(queryset.query))
    serializer_class = InventorySerializers
    def get_object(self):
        queryset = self.queryset()
        obj = get_object_or_404(queryset)
        return obj

这是JSON结果:

[
    {
        "id": 9,
        "product_Description": "Corbata roja gruesa",
        "product_Comments": "Corbate para ocasiones especiales",
        "product_Status": true,
        "category": 1,
        "date_Created": "2018-07-24T19:53:13Z",
        "date_Modified": "2018-07-24T19:53:13Z",
        "model_b": {
            "id": 1,
            "name": "Corbata"
        }
    }
]

但是我需要它,

[
  {
    "id": 1,
    "name": "Corbata",
    "items": {
        "id": 9,
        "product_Description": "Corbata roja gruesa",
        "product_Comments": "Corbate para ocasiones especiales",
        "product_Status": true,
        "category": 1,
        "date_Created": "2018-07-24T19:53:13Z",
        "date_Modified": "2018-07-24T19:53:13Z"
    }
  }
]

我试图像这样更改序列化器:

class InventorySerializers(serializers.ModelSerializer):
    model_b = ProductSerializer(many=True)
    class Meta:
        model = Category
        fields = ('id', 'name', 'model_b')


class inventoryList(generics.ListCreateAPIView):
    queryset = Category.objects.select_related()
    print(str(queryset.query))
    serializer_class = InventorySerializers
    def get_object(self):
        queryset = self.queryset()
        obj = get_object_or_404(queryset)
        return obj

但在这种情况下,查询打印

SELECT "reservation_category"."id", "reservation_category"."name" FROM "reservation_category"

在这种情况下,不是在我的两个表之间进行联接

在这种情况下,查询如何从“ reservation_category”和联接中使用表“ reservation_product”进行查询,如下所示:

SELECT "reservation_product"."id", "reservation_product"."product_Description", "reservation_product"."product_Comments", "reservation_product"."size", "reservation_product"."product_Status", "reservation_product"."category_id", "reservation_product"."date_Created", "reservation_product"."date_Modified", "reservation_category"."id", "reservation_category"."name" 
FROM "reservation_category" 
LEFT OUTER JOIN "reservation_product" ON ("reservation_category"."id"  = "reservation_product"."category_id")

1 个答案:

答案 0 :(得分:1)

首先...在样式上...您在CamelCase和snake_case之间有一个有趣的混合体...所以我会选择一个...通常在Python中是snake_case。 (我的答案只是使用您输入的内容,我所有添加的内容都是snake_case)。

关于这个问题……这不是联接的问题……这是正确配置序列化程序的问题。

我假设您的意思是这样:

[
    {
        "id": 1,
        "name": "Corbata",
        "items": [
            {
                "id": 9,
                "product_Description": "Corbata roja gruesa",
                "product_Comments": "Corbate para ocasiones especiales",
                "product_Status": true,
                "category": 1,
                "date_Created": "2018-07-24T19:53:13Z",
                "date_Modified": "2018-07-24T19:53:13Z"
            }
        ]
    }
]

如果那是您想要的...。我将执行以下操作:

模型(这里的变化是我在related_name上添加了ForeignKey,这使您可以使用更好的名称(产品)遍历向后关系...我还删除了{{1} }从category的角度来看,这是多余的。进一步...不是将字段称为Product,而是将其保留为items,因为它更具描述性...但显然您可以做对您有意义的事情。

products

序列化器(请注意,类别序列化器现在将具有“产品”列表)

class Category(models.Model):

    name = models.CharField(max_length=200)

    def __str__(self):
        return self.name

class Product(models.Model):

    product_Description = models.CharField(max_length=255)
    product_Comments = models.CharField(max_length=255)
    size = models.CharField(max_length=10, null=True)
    product_Status = models.BooleanField(default=True)
    category = models.ForeignKey(Category,  on_delete=models.CASCADE, null=True, related_name='products')
    date_Created = models.DateTimeField(default=datetime.now, blank=True)
    date_Modified = models.DateTimeField(default=datetime.now, blank=True)

    def __str__(self):
        return self.product_Description

视图(由于这里是一对多的关系,因此我将查询集更改为从类别开始,因为这是这里的根对象。我也使用class ProductSerializer(serializers.ModelSerializer): class Meta: model = Product fields = ( 'id', 'product_Description', 'product_Comments', 'product_Status', 'category', 'date_Created', 'date_Modified' ) class CategorySerializer(serializers.ModelSerializer): class Meta: model = Category fields = ('id', 'name', 'products') products = ProductSerializer(many=True) 而不是prefetch_related) / p>

select_related

几件事要注意... 1.我没有测试此代码...因此,视图可能需要进行一些调整(我不确定class inventoryList(generics.ListCreateAPIView): queryset = Category.objects.prefetch_related('products') print(str(queryset.query)) serializer_class = CategorySerializer def get_object(self): queryset = self.queryset() obj = get_object_or_404(queryset) return obj 在这里是否有意义)。 2.我认为这有点不好的API设计。我不喜欢嵌套事物列表,因为它会降低分页能力。如果最终有很多类别,然后每个类别中都有很多产品,则此调用可能会变得非常昂贵且难以管理。

希望这会有所帮助。