如何使用 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.']}

我知道这是在抱怨,因为需要创建 EventDetailEvent 才能添加 OneToOne 关系,但是当 OneToOneField 时如何使用序列化器处理这个问题是必需的,但客户没有提供?

感谢您的帮助。

免责声明:我使用的是 Django 1.11

您可以使用 read_only=Truerequired=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