具有一对多唯一值的Django Rest框架嵌套序列化器

问题描述

我有一个状态模型和一个用于为每种状态存储几种语言的模型:

class Status(models.Model):
    code = models.IntegerField()

class StatusValueLang(models.Model):
    status = models.ForeignKey(Status,related_name="langs",on_delete=models.CASCADE)
    lang = models.CharField(max_length=3)       
    value = models.CharField(max_length=255)

我有一个模型使用状态

class Order(models.Model):
    number = models.CharField(max_length=10)
    status = models.ForeignKey(Status,on_delete=models.PROTECT)

然后,我要序列化此查询集(获取状态名称为英文的订单):

orders = Order.objects.filter(status__langs__lang='en')

使用序列化器。序列化器:

class StatusValueLangSerializer(serializers.Serializer):
    value = serializers.CharField(max_length=255)

class StatusSerializer(serializers.Serializer):
    langs = StatusValueLangSerializer(many=True)

class OrderSerializer(serializers.Serializer):
    number = models.CharField(max_length=10)
    status = StatusSerializer()

它有效,但是由于行'langs = StatusValueLangSerializer(many = True)'中的'Many = True',尽管我使用了过滤器(status__langs__lang ='en'),StatusSerializer 仍返回所有行(语言) 如何设置序列化器以获得此结果:

[
    {
        "number": "123","status": {
            "langs": [
                {
                    "value" : "Approved" <-- Just one,filtered row. 
                }
            ]
        }
    }
]

或者可能更好:

[
    {
        "number": "123","status": {
            "value": "Approved"
        }
    }
]

解决方法

与串行器无关。它与查询本身有关。如果您要在Order模型上进行查询,则将返回Order个对象的QuerySet。

假设有一个名为foo的订单对象。这个foo有一个状态,其状态有很多lang。那么您希望查询得到什么条件?

您在问题中提到的查询:Order.objects.filter(status__langs__lang='en')说给我所有Order,它们的状态至少包含一个lang='en'。订单序列化程序包含状态序列化程序,状态序列化程序包含其所有lang。

为了要在序列化对象中显示一种特定的语言,应自定义序列化程序。像这样:

>>> class NewOrderSerializer(serializers.Serializer):
...     number = serializers.CharField(max_length=10)
...
>>> desired_lang = 'en'
>>> desired_lang_value = StatusValueLang.objects.get(lang='en').value
>>> orders = Order.objects.filter(status__langs__lang=desired_lang)
>>> seriliazed_orders = NewOrderSerializer(orders,many=True)
>>> for order in seriliazed_orders:
...     order['status'] = {'value': desired_lang}
...
>>> print(json.dumps(s,indent=4,sort_keys=True))
[
    {
        "number": "10001","status": {
            "value": desired_lang_value
        }
    }
]
>>>

但这不是一个好方法;这只是一种简单的方法。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...