djangodjango-formsgunicorn

Frozen day in Django form


I use django, nginx, gunicorn. Please help, this form records the date of record creation. For a long time everything worked fine, but recently the date was fixed at 2024-10-07, although it was 2024-10-09. The time on the server is correct. Restarting gunicorn helped, but now it records 2024-10-09. Can you indicate the reason for the failure?

class MyForm(forms.ModelForm):
    create_date = forms.DateField(input_formats=['%Y-%m-%d'],
                                  widget=forms.DateInput(attrs={'type': 'date', 'value': (datetime.today() + timedelta(hours=3)).strftime('%Y-%m-%d'), 'readonly': True}),
                                  label='Create date')
    product_cost = forms.IntegerField(label='Cost')


Solution

  • Explanation of the problem

    The problem is in this part of the line:

    'value': (datetime.today() + timedelta(hours=3)).strftime('%Y-%m-%d')
    

    The expression that you used for attribute value is evaluated during your form class creation – i.e. when the form is first imported and it's most probably when your application starts. As you said, when you restarted the app on 2024-10-09, the value was frozen on this date and it won't change until you restart the app again.

    Solution

    You should set the value dynamically when the form is initialized (if you want to display the value in a rendered form on website) OR during form save if you only want to set the current date on the model.

    Case #1 – on init:

    class MyForm(forms.ModelForm):
        def __init__(self, *args, **kwargs):
             super().__init__(*args, **kwargs)
        
             create_date = (datetime.today() + timedelta(hours=3)).strftime('%Y-%m-%d')
             self.fields["create_date"].widget.attrs["value"] = create_date
    

    Case #2 – on save:

    class MyForm(forms.ModelForm):
        def save(self, *args, **kwargs):
             instance = super().save(*args, **kwargs)
        
             create_date = (datetime.today() + timedelta(hours=3)).strftime('%Y-%m-%d')
             instance.create_date = create_date
             instance.save()
             return instance
    

    Alternative solution

    If your goal is to have create_date automatically set on your model instance, you can set the default param of your model field to a callable. Something like this:

    def auto_create_date():
        return datetime.today() + timedelta(hours=3)
    
    class MyModel(models.Model):
        create_date = models.DateField(default=auto_create_date)
    

    Using the above, you don't need the field in your form.