阅读相关模型中的特定字段

时间:2018-08-14 20:23:00

标签: django django-rest-framework django-serializer

我已经完成了这种简单的关系设置并可以正常工作,但是现在我需要对其进行修改,并且遇到了问题。它是“获取与当前用户相关的产品名称”,而现在是“获取与当前用户相关的产品名称,开始日期和结束日期。”

对于前者,我通过以下方式得到它:

# models.py
class Products(models.Model):
    id = models.AutoField(primary_key=True)
    code = models.CharField(unique=True, max_length=16)
    name = models.CharField(max_length=255, blank=True, null=True)
    short_name = models.CharField(max_length=128)
    start_date= models.DateField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)  
    users = models.ManyToManyField(User, through='UserToProduct')
    stage = models.CharField(max_length=32, blank=True, null=True)

    def __str__(self):
        return self.name

    class Meta:
        db_table = 'Products'

class UserToProduct(models.Model):
    user = models.ForeignKey(User, related_name='user_product', db_column='user_id', null=True, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, related_name='product', db_column='product_id', null=True, on_delete=models.CASCADE)
    stamp = models.DateTimeField(blank=True, null=True) 

    def __str__(self):
        return u'%s' % self.product

    class Meta:
        db_table = 'User_to_Product'
        unique_together = ('user', 'product')
        ordering = ['-product']

以及以下序列化器:

# serializers.py
class ProductListSerializer(serializers.ModelSerializer):
    product = serializers.CharField()
    product_id = serializers.IntegerField()

    class Meta:
        model = Products
        fields = [
            'product_id',
            'product'
        ]

class GetHomeSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    product_list = ProductListSerializer(required=False, many=True)

    def validate(self, data):
        if data:
            data['product_list'] = UserToProduct.objects.filter(user=data['id']).prefetch_related('product').filter(product__stage='active')
            return data

现在,我正在尝试将查询修改为以下内容:

class ProductListSerializer(serializers.ModelSerializer):
    product = serializers.CharField()
    product_id = serializers.IntegerField()
    start_date = serializers.DateField()

    class Meta:
        model = UserToProduct
        fields = [
            'product_id',
            'product',
            'start_date'
        ]

... #stuff in between

data['product_list'] = UserToProduct.objects.filter(user=data['id']).prefetch_related('product').filter(product__stage='active').values('product_id', 'product', 'product__start_date')

并将该字段添加到ProductListSerializer。我收到错误消息:

KeyError: "Got KeyError when attempting to get a value for field `start_date` on serializer `ProductListSerializer`.\nThe serializer field might be named incorrectly and not match any attribute or key on the `dict` instance.\nOriginal exception text was: 'start_date'."

还尝试了以下操作:

class ProductListSerializer(serializers.ModelSerializer):
    id= serializers.IntegerField()
    name = serializers.CharField()
    start_date = serializers.DateField()

    class Meta:
        model = Products
        fields = [
            'id',
            'name',
            'start_date'
        ]

... #stuff in between

data['product_list'] = UserToProduct.objects.filter(user=data['id']).prefetch_related('product').filter(product__stage='active').values('product__id', 'product__name', 'product__start_date')

这将导致相同的错误,其中id是有错误的字段。

尝试将values()替换为.select_related(products__product),结果是:

Choices are: user, product

尝试.select_related(product)并说:

Original exception text was: 'UserToProduct' object has no attribute 'name'. 

这里有什么?

1 个答案:

答案 0 :(得分:1)

使用source参数将嵌套关系指定为

class ProductListSerializer(serializers.ModelSerializer):
    product = serializers.CharField()
    product_id = serializers.IntegerField()
    start_date = serializers.DateField(source='product.start_date') # chage is here <<<<<

    class Meta:
        model = UserToProduct
        fields = [
            'product_id',
            'product',
            'start_date'
        ]


而且,您的 validate() 方法不好,不是应该的。如果未满足某些特定条件,则validate方法应raise ValidationError。{br />
示例:

class SampleSerializer(serializers.Serializer):
    name = serializers.CharField()
    age = serializers.IntegerField()

    def validate(self, attrs):
        if attrs['age']:  # if age is there
            if attrs['age'] < 18:  # validation check for 
                raise serializers.ValidationError("You are under 18. Not allowed")
        return attrs

    def validate_age(self, age):
        if age < 18:  # validation check for 
            raise serializers.ValidationError("You are under 18. Not allowed")
        return age