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