DRF-Как сохранить данные внешних ключей с помощью APIView

#django #django-rest-framework #foreign-keys

Вопрос:

все, я абсолютно новичок в джангоре. У меня есть путаница, связанная с отношениями в DRF. Как сохранить данные внешних ключей с помощью APIView?

Модели

    class User(AbstractUser):
        email = models.EmailField(max_length=255, unique=True)
        is_client = models.BooleanField(default=False)
        is_professional = models.BooleanField(default=False)
        
    
    class Client(models.Model):
            user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='client')
            ##
        
    class Professionals(models.Model):
            user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='professional')
            ##


    class HireProfessional(models.Model):
        client = models.ForeignKey(Client, related_name='user', on_delete=models.CASCADE)
        professional = models.ForeignKey(Professionals, on_delete=models.CASCADE, related_name="professsional")
        hire_start_date_time = models.DateTimeField(default=timezone.now)
 

Сериализаторы

     class ProfessionalSerializer(serializers.ModelSerializer):
        profilePicture = serializers.ImageField(allow_empty_file=True, use_url='professional/profiles', required=False)
        skill = SkillSerializer(many=True,read_only=True)
        class Meta:
            model = Professionals
            fields = fields = ['first_name', 'last_name', 'profilePicture', 'profession', 'phone_number', 'experience', 'skill', 'charge_fee', 'about_me']


    class ClientSerializer(serializers.ModelSerializer):
        class Meta:
            model = Client
            fields = ['user_id', 'first_name', 'last_name', 'phone_number', 'profilePicture']

    class UserSerializer(serializers.ModelSerializer):
        client = ClientSerializer()
        professional = ProfessionalSerializer()
        class Meta:
        model = User
        fields = ('email', 'username', 'is_client', 'is_professional', 'client', 'professional')

    




    class HireProfessionalSerializer(serializers.ModelSerializer):
        client = ClientSerializer()
        professional = professionalSerializer()

        class Meta:
        model = HireProfessional
        fields = ['id','client', 'professional', 'hire_start_date_time']


 

просмотры ##Отредактировано

     
class HireProfessionalCreateApp(APIView):
    permission_classes = (IsAuthenticated, IsClientUser,)

    def current_user(self):
        user = self.request.user.client
        return user


    

    def post(self, request, username, format=None):
        try:
            professional = Professionals.objects.get(user__username=username)
            # print('hello', professional.user_id)
            data = request.data
            
            data['client'] = self.current_user()
            data['professional'] = professional.user_id

            serializer = HireProfessionalSerializer(data=data)
            data = {}
            if serializer.is_valid():
                hire = serializer.save()
                hire.save()
                                    
                return JsonResponse ({
                    "message":"professional hired success.",
                    # "remaning_time":remaning_datetime,
                    "success" : True,
                    "result" : serializer.data,
                    "status" : status.HTTP_201_CREATED
                })
            else:
                data = serializer.errors
                print(data)


            return Response(serializer.data)
         except Professionals.DoesNotExist:
            return JsonResponse ({"status":status.HTTP_404_NOT_FOUND, 'message':'professional does not exists'})

 

Это приложение для найма персонала.

Клиент, способный нанять профессионала

клиент=зарегистрированный пользователь

профессионал=передал идентификатор или имя пользователя через URL

Нравится: path('hire-professional/<professional id or username>', views)

У кого-нибудь есть какие-нибудь идеи? как это решить.

Ответ №1:

Рассмотрите возможность использования a ModelViewSet вместо an APIView , так как вы непосредственно изменяете HireProfessional модель. Кроме того, модель использует ForeignKey поля для Client и Professional , вам не нужно включать в них соответствующие сериализаторы HireProfessionalSerializer .

Реализация только этого ModelViewSet (и добавление его в urls.py использование маршрутизатора) будет означать, что пользователь может самостоятельно выбрать клиента и профессионала, а это значит, что мы еще не закончили. Рекомендуется использовать a router в DRF вместо добавления всех представлений urls.py вручную.

Вы можете использовать ModelViewSet для переопределения функций perform_create и perform_update , в которых вы автоматически заполняете поля сериализатора. :

функция создания по умолчанию

 def perform_create(self, serializer):
       serializer.save()
 

пример автозаполнения

 def perform_create(self, serializer):
        # client is derived from logged in user
        client = Client.objects.get(user=self.request.user)

        # Autofill FK Client.
        serializer.save(client=client)
 

Теперь клиент заполнен автоматически, но профессионал еще нет. Если вы также хотите автоматически заполнить профессионала, вам придется изучить возможность использования вложенного маршрутизатора, так как вы хотите получить PK(идентификатор) из URL-адреса. Если вы сделаете это, ваш URL-адрес будет выглядеть примерно так:

 url='/professionals/{professionals_pk}/hire/'
 

Я надеюсь, что это даст вам представление о том, с чего начать. Если у вас есть какие-либо вопросы, дайте мне знать.