python - 如何在 django 中使用外键创建新模型
问题描述
class Schedule(models.Model):
name = models.CharField(max_length=50)
class ScheduleDefinition(models.Model):
schedule = models.ForeignKey(Schedule, on_delete=models.DO_NOTHING)
config = JSONField(default=dict, blank=True)
这些是我的模型。我正在尝试创建一个新ScheduleDefinition
的(Schedule
已经存在并且我知道要用于我的外键的 ID)。我有一个要使用的预定义计划 ID,但它不起作用..
发布此正文:
{
"schedule_id": 1,
"config": {
"CCC": "ccc"
}
}
我得到的错误:
null value in column "schedule_id" violates not-null constraint
我究竟做错了什么?当我创建新ScheduleDefinition
模型时,Schedule
之前已经创建了模型。Schedule
当我创造新的时,我永远不会创造新ScheduleDefinition
的。
序列化器:
class ScheduleSerializer(serializers.ModelSerializer):
class Meta:
model = Schedule
fields = ['id', 'name']
class ScheduleDefinitionSerializer(serializers.ModelSerializer):
schedule = ScheduleSerializer(read_only=True, many=False)
class Meta:
model = ScheduleDefinition
fields = ['schedule', 'config']
看法:
from rest_framework import generics
from .models import Schedule, ScheduleDefinition
from .serializers import ScheduleSerializer, ScheduleDefinitionSerializer
class ScheduleList(generics.ListAPIView):
queryset = Schedule.objects.all()
serializer_class = ScheduleSerializer
class ScheduleDefinitionList(generics.ListCreateAPIView):
queryset = ScheduleDefinition.objects.all()
serializer_class = ScheduleDefinitionSerializer
class ScheduleDefinitionDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = ScheduleDefinition.objects.all()
serializer_class = ScheduleDefinitionSerializer
查看错误:
File "/app/server/schedules/serializers.py", line 13, in ScheduleDefinitionSerializer
schedule_id = serializers.PrimaryKeyRelatedField(source="schedule")
File "/usr/local/lib/python3.7/dist-packages/rest_framework/relations.py", line 247, in __init__
super().__init__(**kwargs)
File "/usr/local/lib/python3.7/dist-packages/rest_framework/relations.py", line 108, in __init__
'Relational field must provide a `queryset` argument, '
AssertionError: Relational field must provide a `queryset` argument, override `get_queryset`, or set read_only=`True`.
解决方案
您已根据需要指定了 Schedule(非空),但实际上并未向其发布任何信息。目前,您的序列化程序需要以下形式的信息:
{
"schedule": {
"name": "Foo"
},
"config": {...}
}
schedule_id
发布时被丢弃。此外,您已指定这schedule
是一个只读字段,这意味着即使您发布了时间表,它仍然会被丢弃。
如果您想发布到外键,您需要通过手动编写可写嵌套序列化程序的创建/更新逻辑来专门处理它(这可能有点麻烦),或者使用不同的(可写)外键字段序列化器并以另一种方式序列化您的其他只读数据。
例如,以下设置应该与您当前尝试发布的数据一起工作(未经测试):
class ScheduleDefinitionSerializer(serializers.ModelSerializer):
schedule = serializers.PrimaryKeyRelatedField(
queryset=Schedule.objects.all()
)
schedule_name = serializers.CharField(read_only=True, source="schedule.name")
class Meta:
model = ScheduleDefinition
fields = ['schedule', 'schedule_name', 'config']
schedule_name
有了这个,您的帖子应该可以工作,并且您仍然可以通过列表/详细信息视图中的字段对相应的日程安排名称进行只读访问。
编辑
我早期版本的代码与原始所需的 POST 数据不兼容。以下应该可以在不更改 POST 的情况下工作
class ScheduleDefinitionSerializer(serializers.ModelSerializer):
schedule = ScheduleSerializer(many=False, read_only=True)
schedule_id = serializers.PrimaryKeyRelatedField(
source="schedule",
queryset=Schedule.objects.all()
)
class Meta:
model = ScheduleDefinition
fields = ['schedule', 'schedule_id', 'config']
推荐阅读
- javascript - HTML/Javscript - 接受 10 以外的其他基数的数字输入
- python - 如何在 tkinter.messagebox.showinfo() 小部件中取消用于显示消息的字体?
- python - 将 psycopg2 光标传递给 tweepy on_status() 方法
- html - 为什么这个 Bootstrap 4 Navbar 不能创建等宽的菜单项?
- docker - gRPC 流式处理过程返回“方法未实现”。在 Azure 容器实例中运行时
- r - R Shiny - 自定义选项不适用于tippy::with_tippy()
- xodus - 如何使用 Xodus DNQ 检查组合唯一性
- ios - 从 SwiftUI 上的部分列表中删除项目
- single-sign-on - SAML 属性经常实现 eduPerson 规范?有没有更通用的规范?
- anaconda - 内核开发版本与centos7上的内核不同