Home > Mobile >  Is my DRF create function losing data before saving?
Is my DRF create function losing data before saving?

Time:07-12

I have the following DRF viewset:

class RecordViewSet(ModelViewSet):
    queryset = Record.objects.all()
    serializer_class = RecordSerializer
    filterset_fields = ['task', 'workday']
    
    def get_workday(self, request):
        date = get_date_from_calendar_string(request.data['date'])
        obj, _ = Workday.objects.get_or_create(user=request.user, date=date)
        return obj.id
    
    def create(self, request):
        request.data['workday'] = self.get_workday(request)
        print(request.data)
        return super().create(request)

The create() method is failing on a not-null constraint:

django.db.utils.IntegrityError: null value in column "task_id" violates not-null constraint
DETAIL:  Failing row contains (159, Added via task panel., 0, 0, 0, null, t, f, null, 98).

However, the print statement in create() shows that the data present in the submission:

{'minutes_planned': 5, 'description': 'Added via task panel.', 'minutes_worked': 5, 'task': 148, 'workday': 98}

I am not seeing the pk for task (148) in the error statement for some reason, indicating to me that it is getting dropped somewhere. I am not using any signals, or overriding save() in the model. What else could be causing this problem? I've just started using DRF, so it might be something obvious.

=====

This is the model:

class Record(models.Model):
    task = models.ForeignKey(Task, on_delete=models.CASCADE, related_name='records')
    workday = models.ForeignKey(Workday, on_delete=models.CASCADE, related_name='records')
    description = models.CharField(max_length=128, blank=True, null=True)
    minutes_planned = models.IntegerField(default=0)
    minutes_worked = models.IntegerField(default=0)
    minutes_worked_store = models.IntegerField(default=0)
    user_generated = models.BooleanField(default=True)
    completed = models.BooleanField(default=False)

and the serializer:

class RecordSerializer(serializers.ModelSerializer):
    task = TaskSerializer(read_only=True)

    class Meta:
        model = Record
        fields = ['id', 'workday', 'description', 'completed', 'task', 'minutes_worked', 'minutes_planned']

CodePudding user response:

Your TaskSerializer is read_only for the RecordSerializer which does not allow writing that field and therefor will be ignored on create.

Change your code to the following should work

class RecordSerializer(serializers.ModelSerializer):
    task = TaskSerializer(read_only=True)
    task_id = serializers.PrimaryKeyRelatedField(queryset=models.Task.objects.all(), write_only=True)

https://www.django-rest-framework.org/api-guide/relations/#primarykeyrelatedfield

CodePudding user response:

Since you didn't provide the code of the TaskSerializer, it's hard to say what happens there under the hood.

It looks to me that you are trying to assign somewhere task=148 instead of task_id=148. Normally the model expects that the task field will be and instance of class Task, while task_id can be the pk of this instance.

  • Related