ValueError: Невозможно присвоить "1": "LeadFacilityAssign.assigned_facilities" должен быть экземпляром "Facility".

Я пытаюсь создать конечную точку api для обновления моих объектов "lead" и добавления к ним списка объектов при отправке запроса put (каждый раз разное количество объектов). Объекты "lead" уже существуют в базе данных, как и объекты "facility". Поскольку мне нужны дата и время, связанные с каждым объектом, когда они добавляются к свинцу, я создал класс "LeadFacilityAssign". Поскольку я не смог заставить его работать, я попытался сделать это просто с помощью пост-запроса во время процесса создания объекта. Мне сказали, что я должен использовать bulk_create, если мне нужно добавить более одного объекта таким образом. Я не смог найти ничего о bulk_create в документации по drf, поэтому я решил пока сделать это только с одним объектом и улучшать свой код по одному вопросу за раз, так как я новичок в drf.

Кто-нибудь знает, что вызывает эту ошибку? Я пробовал несколько разных вещей, но пока ничего не помогло.

ValueError: Cannot assign "1": "LeadFacilityAssign.assigned_facilities" must be a "Facility" instance.

serializers.py

class LeadUpdateSerializer(serializers.ModelSerializer):
    is_owner = serializers.SerializerMethodField()
    assigned_facilities = serializers.IntegerField(required=True)
    datetime = serializers.DateTimeField(required=True)

    class Meta:
        model = Lead
        fields = (
            "id",
            "first_name",
            "last_name",
            "assigned_facilities",
            "datetime",
        )
        read_only_fields = ("id", "created_at", "agent", "is_owner")

    def get_is_owner(self, obj):
        user = self.context["request"].user
        return obj.agent == user
    
    def create(self, validated_data):
        assigned_facilities = validated_data.pop("assigned_facilities")
        datetime = validated_data.pop("datetime")
        instance = Lead.objects.create(**validated_data)
        instance.leadfacility.create(assigned_facilities=assigned_facilities,datetime=datetime)
        print(instance)
        return instance

models.py

class Facility(models.Model):
    name = models.CharField(max_length=150, null=True, blank=False)

    def __str__(self):
        return self.name

class Lead(models.Model):
    first_name = models.CharField(max_length=40, null=True, blank=True)
    last_name = models.CharField(max_length=40, null=True, blank=True)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"

class LeadFacilityAssign(models.Model):
    assigned_facilities = models.ForeignKey(Facility, on_delete=models.CASCADE, related_name='leadfacility')
    lead = models.ForeignKey(Lead, on_delete=models.CASCADE, related_name='leadfacility')
    datetime = models.DateTimeField()

views.py

class LeadCreateView(CreateAPIView):
    permission_classes = [IsAuthenticated, IsLeadOwner]
    serializer_class = LeadUpdateSerializer

    def perform_create(self, serializer):
        serializer.save(agent=self.request.user)

class LeadUpdateView(UpdateAPIView):
    permission_classes = [IsAuthenticated, IsLeadOwner]
    serializer_class = LeadUpdateSerializer

    def get_queryset(self):
        return Lead.objects.all()

Вы пытаетесь добавить значение Integer в FK field.

У вас есть 2 варианта. Вы можете изменить поле сериализатора.

assigned_facilities = serializers.PrimaryKeyRelatedField(queryset=Facility.objects.all(), required=True)

ИЛИ

instance.leadfacility.create(assigned_facilities_id=assigned_facilities,datetime=datetime)

Я бы предпочел использовать 1 вариант.

Другое потенциальное решение, которое вы можете применить:

class LeadUpdateSerializer(serializers.ModelSerializer):
    is_owner = serializers.SerializerMethodField()
    assigned_facilities = serializers.IntegerField(required=True)
    datetime = serializers.DateTimeField(required=True)

    class Meta:
        model = Lead
        fields = (
            "id",
            "first_name",
            "last_name",
            "assigned_facilities",
            "datetime",
        )
        read_only_fields = ("id", "created_at", "agent", "is_owner")
   
    def validate_assigned_facility(self, facility_pk)->:
        assigned_facility = Facility.objects.filter(pk=facility_pk).first()
        if assigned_facility:
            return assigned_facility
        raise ValidationError('Facility not found, provide a valid pk')

    def get_is_owner(self, obj):
        user = self.context["request"].user
        return obj.agent == user
    
    def create(self, validated_data):
        assigned_facilities = validated_data.pop("assigned_facilities")
        datetime = validated_data.pop("datetime")
        instance = Lead.objects.create(**validated_data)
        instance.leadfacility.create(assigned_facilities=assigned_facilities,datetime=datetime)
        print(instance)
        return instance

Это решение вроде бы большое, но очень гибкое, потому что дает вам возможность добавить больше бизнес-логики вокруг входных и ожидаемых данных в модели или источнике данных.

Вернуться на верх