Django REST: игнорирование пользовательских полей, которые не являются частью модели

Моя модель TimeReport выглядит следующим образом:


class TimeReport(models.Model):
    minutes_spent = models.PositiveIntegerField()
    task = models.ForeignKey(Task, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)
    reported_for = models.DateField()
    note = models.TextField(null = True, blank=True)
    status = models.CharField(max_length=50, choices=State.choices, default=State.new)
    user = models.ForeignKey(User, on_delete=models.PROTECT)

И мой сериализатор модели:

class TimeReportCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = TimeReport
        fields = (
            'id',
            'minutes_spent',
            'reported_for', 
            'note',
            'status',
            'task_custom_id',
            )
    
    task_custom_id = serializers.CharField()

    def create(self, validated_data):
        user = User.objects.get(auth_user_id = self.context['user_id'])
        task = Task.objects.filter(custom_id = validated_data['task_custom_id']).filter(user = user.id).first()
        
        report = TimeReport(**validated_data)
        report.user = user
        report.task = task
        report.save()
        return report

Итак, проблема в том, что я хочу взять пользовательское значение в сериализаторе, которое не является частью модели, и выполнить с ним некоторую пользовательскую логику - в данном случае поиск нужной "задачи" в базе данных. Но когда я пытаюсь разобрать модель, используя report = TimeReport(**validated_data), это дает мне исключение:

TypeError at /api/report/
TimeReport() got an unexpected keyword argument 'task_custom_id'

Я вроде как новичок в Django и самом python, так что - какой подход лучше?

Если вы собираетесь использовать это поле только для создания, вам следует использовать опцию write_only.

task_custom_id = serializers.CharField(write_only=True)

См. документацию здесь https://www.django-rest-framework.org/api-guide/fields/#write_only

Вам просто нужно удалить task_custom_id из словаря

class TimeReportCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = TimeReport
        fields = (
            'id',
            'minutes_spent',
            'reported_for', 
            'note',
            'status',
            'task_custom_id',
            )
    
    task_custom_id = serializers.CharField()

    def create(self, validated_data):
        user = User.objects.get(auth_user_id = self.context['user_id'])
        task_custom_id = validated_data.pop("task_custom_id")
        task = Task.objects.filter(custom_id = task_custom_id).filter(user = user.id).first()
        report = TimeReport(**validated_data)
        report.user = user
        report.task = task
        report.save()
        return report
task = Task.objects.filter(custom_id = validated_data.pop('task_custom_id')).filter(user = user.id).first()

**validated_data вернет (task_custom_id=value, field1=value1 ...), а task_custom_id не является полем TimeReport, поэтому все, что вам нужно, это поместить его из validated_data перед вызовом конструктора TimeReport

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