Search code examples
djangodjango-modelsdjango-rest-frameworkdjango-serializer

How to automatically generate a field based on the choice of a previous field


I have a model and some serializers in Django Rest Framework. I would like to have choices for the "service_interval" field and then based on what they choose it generates the date correctly in the database. How would I do this?

Here's my code.

class Snippet(VIPSnippet):
    title = models.CharField(max_length=100, blank=True, default='')
    service_interval_choices = [
        (3, '3 Months'),
        (6 , '6 Months'),
        (9, '9 Months'),
        (12, '1 Year'),
    ]
    service_interval = models.IntegerField(choices=service_interval_choices)
    next_service = models.DateTimeField()

Serializers

class SnippetSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.username')
    highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html')
    
    class Meta:
        model = Snippet
        fields = ['url', 'service_interval']
        next_service = datetime.datetime.now() + datetime.timedelta(3*365/12)

When I do it this way I get the following error

NOT NULL constraint failed: snippets_snippet.next_service

I plan to replace the '3' in datetime.timedelta(3*365/12) with service_interval or whatever variable I would need so that it generates the date however may months in the future as needed.


Solution

  • You can do that by overriding the serializer's validate-method:

    class SnippetSerializer(serializers.HyperlinkedModelSerializer):
        owner = serializers.ReadOnlyField(source='owner.username')
        highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html')
        
        def validate(self, data):
            data["next_service"] = datetime.datetime.now() + datetime.timedelta(data["service_interval"]*365/12)
            return data
    
        class Meta:
            model = Snippet
            fields = [
                'url',
                'service_interval',
                'next_service',
                # also you need to include the fields defined on the serializer here:
                'owner',
                'highlight',
            ]