Django: Initial value for a ModelSerializer field

4.9k views Asked by At

I'm writing a Django app using django==1.10 and djangorestframework==3.4.6

Please consider the following code:

I have two models:

class BaselineModel(models.Model):
    subject = models.ForeignKey('custom_auth.User', blank=True)
    weight = models.SmallIntegerField(null=True, blank=True)

class DosageModel(models.Model):
    subject = models.ForeignKey('custom_auth.User', blank=True)
    udca = models.SmallIntegerField(null=True, blank=True)
    weight = models.SmallIntegerField(null=True, blank=True)

And a Serializer:

class DosageSerializer(serializers.ModelSerializer):

    class Meta:
        exclude = ("subject",)
        model = DosageModel

Question: How can I set the initial value for DosageModel.weight to BaselineModel.weight?

Use Case: Weights initial value will be the weight registered at Baseline. The user has the option to overwrite the initial value.

enter image description here

Edit: The initial value should be "initial", meaning it should be displayed i the HTML input field before the data object is created.

3

There are 3 answers

0
Maximilian Kindshofer On

You can try the following

class DosageSerializer(serializers.ModelSerializer):

    weight = models.SmallIntegerField(null=True, blank=True, default=BaselineModel.objects.get(pk=<your pk>)    

    class Meta:
        exclude = ("subject",)
        model = DosageModel

But you will run into a problem: The Default value will be fetched once at the start of the server.

class DosageSerializer(serializers.ModelSerializer):

def __init__(self, *args, **kwargs):
    super(DosageSerializer, self).__init__(*args, **kwargs)
    self.BaselineDefault = BaselineModel.objects.get(pk=<your pk>)

    weight = models.SmallIntegerField(null=True, blank=True, default=BaselineDefault    

    class Meta:
        exclude = ("subject",)
        model = DosageModel

This will fetch the value every time the Model is initialized. This works with ModelForms and I am not sure if the RestSerializers behave the same way.

0
MohTaheri On

You can define an extra field (such as my_weight) for using initial argument in your serializer field. Here is example code:

class DosageSerializer(serializers.ModelSerializer):

    my_weight = serializers.SmallIntegerField(source="weight", initial=BaselineModel.objects.first().weight)

   class Meta:
        exclude = ("subject",)
        model = DosageModel 

May be your initial value dependents to user, in which case the BaselineModel will be filtered based on your desired subject.

3
Mahsa Lotfi On

You could not use default method on weight serializer since subject isn't cleaned at that time. I used a model level validation to achieve the result.

Try this:

class DosageSerializer(serializers.ModelSerializer):
    weight = serializers.IntegerField(required=False)
    class Meta:
        model = DosageModel
        fields = '__all__'

    def validate(self, data):
        if 'weight' not in data:
            data['weight'] = BaselineModel.objects.get(subject=data['subject']).weight
    return data

I assumed that user provides subject when creating the DosageModel object. If it's not the case please provide more details.