如何使用 DRF 序列化程序创建包含必需的 OneToOneField 的 Django 模型实例
How to Create a Django Model Instance That Contains a Required OneToOneField with DRF Serializers
问题
假设我有一个包含 OneToOneField
的模型,如下所示:
models.py
class Event(models.Model)
# some basic fields...
class EventDetail(models.Model):
event = models.OneToOneField(Event, on_delete=models.CASCADE,
related_name='event_detail')
# other basic fields, all with default values...
什么是实现 POST 请求的正确方法,该请求旨在在数据库中创建一个新的 Event
,如果它是,则自动创建一个链接到它的默认 EventDetail None 在请求 header 中,使用 Django Rest Framework 的序列化程序?
我的尝试
test.py
class EventTestCase(APITestCase):
def test_post(self):
# Need to provide an id, or else an error occurs about the OneToOneField
event = Event(id=1)
serializer = serializers.EventSerializer(event)
res = self.api_client.post('/event/', serializer.data)
views.py
def post(self, request, format=None):
serializer = EventSerializer(
data=request.data)
# ***This always returns false!***
if serializer.is_valid():
try:
instance = serializer.save()
except ValueError:
return Response(status=status.HTTP_400_BAD_REQUEST)
serializers.py
class EventSerializer(serializers.ModelSerializer):
serialization_title = "Event"
event_detail = EventDetailSerializer()
class Meta:
model = Event
exclude = ('id',)
error_status_codes = {
HTTP_400_BAD_REQUEST: 'Bad Request'
}
class EventDetailSerializer(serializers.ModelSerializer):
serialization_title = "Event Detail"
class Meta:
model = models.EventDetail
exclude = ('id',)
error_status_codes = {
HTTP_400_BAD_REQUEST: 'Bad Request'
}
如上面的评论所述,serializer.is_valid()
总是 returns 错误,错误为:
{'event_detail': [u'This field may not be null.']}
我知道这是在抱怨,因为需要创建 EventDetail
和 Event
才能添加 OneToOne 关系,但是当 OneToOneField 时如何使用序列化器处理这个问题是必需的,但客户没有提供?
感谢您的帮助。
免责声明:我使用的是 Django 1.11
您可以使用 read_only=True
或 required=False
声明 EventDetailSerializer
,然后以不同的方式处理 EventDetail
的创建,例如:您可以有一个 post_save
侦听 Event
class 的信号 - 一旦创建了新的 Event
对象,您就可以创建初始的 EventDetail
对象,或者执行此操作在 post
定义的 serializer.save()
之后创建,甚至在 EventSerializer
.
的 create
方法上创建
编辑:关于如何使用 EventDetailSerializer
执行创建并覆盖 EventSerializer
.
的 create
方法的示例
def create(self, validated_data):
detail = self.initial_data.get('event_detail')
instance = super().create(validated_data)
if detail:
serializer = EventDetailSerializer(data=detail)
serializer.is_valid(raise_exception=True)
serializer.save(event=instance)
return instance
问题
假设我有一个包含 OneToOneField
的模型,如下所示:
models.py
class Event(models.Model)
# some basic fields...
class EventDetail(models.Model):
event = models.OneToOneField(Event, on_delete=models.CASCADE,
related_name='event_detail')
# other basic fields, all with default values...
什么是实现 POST 请求的正确方法,该请求旨在在数据库中创建一个新的 Event
,如果它是,则自动创建一个链接到它的默认 EventDetail None 在请求 header 中,使用 Django Rest Framework 的序列化程序?
我的尝试
test.py
class EventTestCase(APITestCase):
def test_post(self):
# Need to provide an id, or else an error occurs about the OneToOneField
event = Event(id=1)
serializer = serializers.EventSerializer(event)
res = self.api_client.post('/event/', serializer.data)
views.py
def post(self, request, format=None):
serializer = EventSerializer(
data=request.data)
# ***This always returns false!***
if serializer.is_valid():
try:
instance = serializer.save()
except ValueError:
return Response(status=status.HTTP_400_BAD_REQUEST)
serializers.py
class EventSerializer(serializers.ModelSerializer):
serialization_title = "Event"
event_detail = EventDetailSerializer()
class Meta:
model = Event
exclude = ('id',)
error_status_codes = {
HTTP_400_BAD_REQUEST: 'Bad Request'
}
class EventDetailSerializer(serializers.ModelSerializer):
serialization_title = "Event Detail"
class Meta:
model = models.EventDetail
exclude = ('id',)
error_status_codes = {
HTTP_400_BAD_REQUEST: 'Bad Request'
}
如上面的评论所述,serializer.is_valid()
总是 returns 错误,错误为:
{'event_detail': [u'This field may not be null.']}
我知道这是在抱怨,因为需要创建 EventDetail
和 Event
才能添加 OneToOne 关系,但是当 OneToOneField 时如何使用序列化器处理这个问题是必需的,但客户没有提供?
感谢您的帮助。
免责声明:我使用的是 Django 1.11
您可以使用 read_only=True
或 required=False
声明 EventDetailSerializer
,然后以不同的方式处理 EventDetail
的创建,例如:您可以有一个 post_save
侦听 Event
class 的信号 - 一旦创建了新的 Event
对象,您就可以创建初始的 EventDetail
对象,或者执行此操作在 post
定义的 serializer.save()
之后创建,甚至在 EventSerializer
.
create
方法上创建
编辑:关于如何使用 EventDetailSerializer
执行创建并覆盖 EventSerializer
.
create
方法的示例
def create(self, validated_data):
detail = self.initial_data.get('event_detail')
instance = super().create(validated_data)
if detail:
serializer = EventDetailSerializer(data=detail)
serializer.is_valid(raise_exception=True)
serializer.save(event=instance)
return instance