- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试创建一个 api,用户可以在其中创建程序并向其添加规则。规则必须按优先顺序执行。我正在使用 Django rest 框架来实现这一点,并且我试图在不使用 ModelSerializer 的情况下使用 Serializer 来实现这一点。使用序列化器提供您的解决方案。序列化器类
一个程序可以有很多规则,一个规则可以在多个程序中。所以,我正在使用 many_to_many 关系,我还希望用户更改程序中规则的顺序,为了实现这一点,我使用了一个名为 Priority 的直通表,我在其中使用优先级字段跟踪规则和程序之间的关系
模型.py
class Program(models.Model):
name = models.CharField(max_length=32)
description = models.TextField(blank=True)
rules = models.ManyToManyField(Rule, through='Priority')
class Rule(models.Model):
name = models.CharField(max_length=20)
description = models.TextField(blank=True)
rule = models.CharField(max_length=256)
class Priority(models.Model):
program = models.ForeignKey(Program, on_delete=models.CASCADE)
rule = models.ForeignKey(Rule, on_delete=models.CASCADE)
priority = models.PositiveIntegerField()
def save(self, *args, **kwargs):
super(Priority, self).save(*args, **kwargs)
序列化器.py
class RuleSerializer(serializers.Serializer):
name = serializers.CharField(max_length=20)
description = serializers.CharField(allow_blank=True)
rule = serializers.CharField(max_length=256)
def create(self, validated_data):
return Rule.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.name = validated_data.get('name', instance.name)
instance.description = validated_data.get('description', instance.description)
instance.rule = validated_data.get('rule', instance.rule)
instance.save()
return instance
class PrioritySerializer(serializers.Serializer):
rule_id = serializers.IntegerField(source='rule.id')
rule_name = serializers.CharField(source='rule.name')
rule_rule = serializers.CharField(source='rule.rule')
priority = serializers.IntegerField()
class ProgramSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=32)
description = serializers.CharField(style={'base_template': 'textarea.html'})
rules = PrioritySerializer(source='priority_set', many=True)
def create(self, validated_data):
rules_data = validated_data.pop('rules')
program_obj = Program.objects.create(**validated_data)
priority = 0
for rule in rules_data:
rule_obj = Rule.objects.get(pk=rule.rule_id)
priority += 1
Priority.objects.create(program=program_obj, rule=rule_obj, priority=priority)
return program_obj
views.py
class ProgramList(APIView):
"""
List all programs, or create a new program.
"""
def get(self, request, format=None):
programs = Program.objects.all()
serializers = ProgramSerializer(programs, many=True)
return Response(serializers.data)
def post(self, request, format=None):
serializer = ProgramSerializer(data=request.data, partial=True)
print(serializer.initial_data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
当我向 http://localhost:8000/api/programs/ 发出获取请求时,我得到了这个响应
[
{
"id": 1,
"name": "some",
"description": "hahah",
"rules": [
{
"rule_id": 3,
"rule_name": "DAIEA",
"rule_rule": "date,and,invoice,equal,amount",
"priority": 1
},
{
"rule_id": 2,
"rule_name": "DAIEA",
"rule_rule": "date,and,invoice,equal,amount",
"priority": 2
},
{
"rule_id": 1,
"rule_name": "DAI=A",
"rule_rule": "date,and,invoice,equal,amount",
"priority": 3
}
]
},
{
"id": 2,
"name": "DAI=AS",
"description": "Date and Invoice equal Amount Sumif",
"rules": []
},
]
我在规则字段下获得了规则列表,但是当我使用此 request.data 发出发布请求以在 rule.id 的帮助下创建一个包含规则的新程序时,
发布数据:
{
"name": "DAI=AS",
"description": "Date and Invoice equal Amount Sumif",
"rules": [
{
"rule_id": 1
},
{
"rule_id": 2
}
]
}
在序列化过程之后,validated_data 包含 priority_set 字段而不是 rules 字段,如下所示
{
'name': 'DAI=AS',
'description': 'Date and Invoice equal Amount Sumif',
'priority_set': [
OrderedDict([('rule', {'id': 1})]),
OrderedDict([('rule', {'id': 2})])
]
}
我不希望序列化程序将规则更改为 priority_set
此外,我在 priority_set 中获取 OrderedDict 列表,而不是我需要规则对象字典
这就是我在序列化过程之后想要的,
{
"name": "DAI=AS",
"description": "Date and Invoice equal Amount Sumif",
"rules": [
{
"rule_id": 1
},
{
"rule_id": 2
}
]
}
提前致谢
最佳答案
解决方案一:
验证数据中的字段使用源属性重命名。您可以在序列化程序的 create
方法中使用重命名的属性。
对于嵌套的序列化程序,验证数据似乎包含 OrderedDict
。你可以把它转换成普通的Dict
,并且可以得到规则id。
class ProgramSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=32)
description = serializers.CharField(style={'base_template': 'textarea.html'})
rules = PrioritySerializer(source='priority_set', many=True)
def create(self, validated_data):
rules_data = validated_data.pop('priority_set')
program_obj = Program.objects.create(**validated_data)
priority = 0
for rule in rules_data:
rule_obj = Rule.objects.get(pk=dict(rule)["rule"]["id"])
priority += 1
Priority.objects.create(program=program_obj, rule=rule_obj, priority=priority)
return program_obj
解决方案 2:
您可以将源名称为 priority_set
的 rules
设置为 read_only
并可以从请求数据中提取它。
class ProgramSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=32)
description = serializers.CharField(style={'base_template': 'textarea.html'})
rules = PrioritySerializer(source='priority_set', many=True, read_only=True)
def create(self, validated_data):
rules_data = self.context["request"].data["rules"]
program_obj = Program.objects.create(**validated_data)
priority = 0
for rule in rules_data:
rule_obj = Rule.objects.get(pk=rule["rule_id"])
priority += 1
Priority.objects.create(program=program_obj, rule=rule_obj, priority=priority)
return program_obj
您需要将请求上下文传递给序列化器
serializer = ProgramSerializer(data=request.data, partial=True, context={"request": request})
解决方案 3:
在Priority
模型的program
外键中添加related_name
program = models.ForeignKey(Program, related_name="rule", on_delete=models.CASCADE)
将 ProgramSerializer
中的 rules
字段重命名为其他名称,例如规则
,并删除源。
class ProgramSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(max_length=32)
description = serializers.CharField(style={'base_template': 'textarea.html'})
rule = PrioritySerializer(many=True)
def create(self, validated_data):
rules_data = validated_data.pop('rule')
program_obj = Program.objects.create(**validated_data)
priority = 0
for rule in rules_data:
rule_obj = Rule.objects.get(pk=dict(rule)["rule"]["id"])
priority += 1
Priority.objects.create(program=program_obj, rule=rule_obj, priority=priority)
return program_obj
现在您将能够使用 rule
键发布和检索数据。您可以根据需要重命名它。
关于python - Serializers.validated_data 字段已更改为 DRF 中的源值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69297409/
背景 我有一个定义了多个自定义操作的 ModelViewSet。我在 urls.py 中使用默认路由器注册 URL。现在,我的 View 使用默认创建的路由,如 ^images/$ , ^images
DRF 中的 request.data 和 DRF 中的 serializers.data 有什么区别。 当我在 DRF 中编写基于函数的 View 时,我会像使用它们一样 - eli
我用Django REST框架准备了API。我正在使用docker运行我的API,一切在我的机器上都运行得很好。因此,我只需运行docker-compose up,就可以在浏览器中使用Swagger测
我用Django REST框架准备了API。我正在使用docker运行我的API,一切在我的机器上都运行得很好。因此,我只需运行docker-compose up,就可以在浏览器中使用Swagger测
快速上手JWT签发token和认证,有这一篇就够了,DRF自带的和自定义的都帮你总结好了,拿去用~ DRF JWT认证(二) 上篇中对JWT有了基本的认知,这篇来略谈JWT的使用 签发:一般我们登录成
什么接口文档都不用手写了?自动挡? DRF 自动生成接口文档 我们知道前后端分离,前端一般按后端写好的接口去开发,那么就需要我们明细后端接口数据等,需要写接口文档,前端按照接口文档去开发 接口文档如何
为什么要使用JWT认证?构成和原理又是什么?怎么还有Base64的事?我都写了👆 DRF JWT认证(一) JWT认证 Json web token (JWT), 是为了在网络应用环境间传递声明而执
DRF 中如何使用过滤,排序,分页,以及报错了如何处理?10分钟get了~ DRF 过滤排序分页异常处理 过滤 涉及到查询数据的接口才需要过滤功能 DRF过滤使用种类: 内置过滤类 第三方 自定义 内
前后端分离开发怎么给接口做认证权限频率三大认证?点进来5分钟get! DRF-认证权限频率 前后端混合开发,可以通过HttpResponse对象来设置cookie进而校验登录,现在前后端分离开发,用不
你问我使用DRF视图组件快速写接口?九九归一剑诀早就准备好了,没有副作用! DRF 视图组件 DRF框架提供了很多通用的视图基类与扩展类,上篇使用的APIView是比较偏Base的,视图的使用更加简化
1、路由Routers 在 Rest Framework 中提供了两个 router , 可以帮助我们快速的实现路由的自动生成。 必须是继承 ModelViewSet 的视图类才能自动生成路由
1. 前言 大家好,我是安果! 接下来,将通过几篇文章将对 DRF 模型序列化进行展开说明,详情谈谈模型序列化的作用、步骤及进阶用法 2. 模型序列化的作用?  
我第一次尝试进入 Django 原子事务。我想知道是否有可能像这样使用它: class TaskViewSet(MultiSerializerViewSet): @transaction.at
我有一个 drf 序列化程序,其中有一个我想重命名的字段: class UserBulkUploadSerializer(serializers.Serializer): ... is
我使用了 drf 并且还使用了 serializer 来检查用户输入。 这是我的serializer.py class BoardSerializer(serializers.Serializer):
我正在尝试序列化一个 CreateUserSerializer(ModelSerializer)我的代码如下。我的问题是它只会创建一个 User 而不是 UserProfile。 模型.py clas
我如何发布这个 JSON { "campaign": 27, "campaignName": "Prueba promo", "promotionType": 999, "items"
我正在构建一个 todo 应用程序,可以在 todo 上发布评论。 为此,我制作了一个可写的双嵌套序列化程序。它有效,但我编写的更新方法难以理解,因此我试图使其更具可读性。是否有更好的(或标准的)方法
有没有办法为特定的 View 类指定所需的自定义 header ?在我正在使用的 API 上,一些信息是使用 header 传递的,如果缺少 header ,我需要返回 BAD_REQUEST 或类似
我正在使用 DRF 并且我正在尝试创建一个对象,该对象具有多个外键以及需要在此过程中创建的相关对象。 这是我的模型的简化版本: class Race(models.Model): name =
我是一名优秀的程序员,十分优秀!