Django REST:用于创建多个模型的端点

问题描述 投票:0回答:1

在我的服务中,注册用户时,必须创建两个实体:用户和公司,用户实体将立即链接到公司。

为此,我创建了一个端点,在其中使用两个序列化器(用于用户和公司)。但这个解决方案存在一些问题:

  • 其中一个序列化器的字段未显示在 Django Spectacular (Swagger) 中;
  • DRF BRowsable API 中不提供序列化器之一的字段;
  • 丑陋的代码;
class UserCreateViewSet(mixins.CreateModelMixin,
                        viewsets.GenericViewSet):
    """
    Creates user accounts
    """
    queryset = User.objects.all()
    serializer_class = CreateUserSerializer
    permission_classes = (AllowAny,)
    REQUIRED_FIELDS = (
        'email', 'password',
        'position', 'company_name',
        'phone_number'
    )
    
    def create(self, request, *args, **kwargs):
        data = request.data
        provided_fields = set(data.keys())
        for field in self.REQUIRED_FIELDS:
            if field not in provided_fields:
                return Response(
                    {"detail":f"{field} not provided"},
                    status=400
                )
                
        # --- Creating company for user
        data['name'] = data['company_name']
        company_serializer = CompanyReducedSerializer(data=request.data)
        company_serializer.is_valid(raise_exception=True)
        self.perform_create(company_serializer)
        data['company'] = company_serializer.data['id']
        # ---
        
        # Code from super()
        # --- Creating user
        user_serializer = self.get_serializer(data=request.data)
        user_serializer.is_valid(raise_exception=True)
        self.perform_create(user_serializer)
        headers = self.get_success_headers(user_serializer.data)
        # ---
        
        return Response(
            status=201,
            data=user_serializer.data,
            headers=headers
        )

我考虑过使用多表继承的选项,但由于某些原因,这个解决方案不适合我。公司和用户实体必须分开。

是否可以编写一个序列化器来创建两个实体?或者还有更好的解决方案吗?

python python-3.x django django-rest-framework django-serializer
1个回答
0
投票

我建议对您的代码进行一些更改。

其中一种方法可以如下。

  • 您创建一个序列化器来验证所需字段
  • 如果所需数据有效,则验证公司序列化程序并创建(如果有效)并为用户重复。

序列化器.py

from rest_framework import serializers

class CreateUserSerializer(serializers.Serializer):
    email = serializers.EmailField(required=True)
    password = serializers.CharField(required=True)
    position = serializers.CharField(required=True)
    company_name = serializers.CharField(required=True)
    phone_number = serializers.CharField(required=True)

views.py

from rest_framework import mixins, viewsets
from rest_framework.status import HTTP_201_CREATED

class UserViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet):
    ...

    def create(self, request, *args, **kwargs):

        # this serializer will take care of your required fields        
        data_serializer = CreateUserSerializer(request.data)
        data_serializer.is_valid(raise_exception=True)

        company_serializer = CompanyCreateSerializer(data=request.data)
        company_serializer.is_valid(raise_exception=True)
        company = company_serializer.save()

        # format data required for user creation
        data = {"company": company, "email": email}
        user_serializer = UserCreateSerializer(data=data)
        user_serializer.is_valid(raise_exception=True)
        user_serializer.save()

        return Response(
            data=user_serializer.data,
            status=HTTP_201_CREATED
        )

其他方法可以是公司或用户序列化程序的

create
方法,具体取决于您想要如何创建相关对象

例如

class UserCreateSerializer(ModelSerializer):
    ...

    def create(self, validated_data: dict):
        company_sz = CompanySerializer(data=<YOUR_DATA>)
        compant_sz.is_valid(raise_exception=True)
        company_sz.save()
        user = super().create(validated_data)
        return user
        
© www.soinside.com 2019 - 2024. All rights reserved.