Django forms: Value won't get processed

Hi again out there,
if you feel like me spamming this forum the last days, then we feel the same :stuck_out_tongue:

Right now i am encountering a strange problem occuring in a part of my project that was considered “done” since weeks…

In processing a ModelForm in Django template, i get an unsupported operand type(s) for -: 'datetime.date' and 'NoneType' error, but last time i tried, it was working ???

Specifically i talk about this:

Models.py:

class ForeignMissions(models.Model):

    mission = models.CharField(max_length=50)
    location = models.CharField(max_length=100)
    position = models.CharField(max_length=100, null=True, blank=True)
    begin = models.DateField(null=True, blank=True)
    end = models.DateField(null=True, blank=True)
    employee = models.ForeignKey(Employees, on_delete=models.CASCADE)

    objects = MissionDurationManager()

    def __str__(self):
        return self.mission

    def mission_duration(self):
        duration = self.end - self.begin
        return duration.days

forms.py:

class ForeignMissionsForm(ModelForm):

    class Meta:
        model = ForeignMissions
        fields = '__all__'

    employee = forms.ModelChoiceField(queryset=Employees.objects.all(), widget=forms.HiddenInput)
    mission = forms.ModelChoiceField(queryset=Mandat.objects.all(), label='',
                                     empty_label="Mandat", required=False, widget=forms.Select(attrs={
                                        'class': "form-select fw-bold border border-1 border-black m-1",
                                        'style': 'max-width: auto;',
                                        'required': 'True',
                                      }))

    location = forms.ModelChoiceField(queryset=Einsatzort.objects.all(), label='',
                                      empty_label="Einsatzort", required=False, widget=forms.Select(attrs={
                                        'class': "form-select fw-bold border border-1 border-black m-1",
                                        'style': 'max-width: auto;',
                                        'required': 'True',
                                      }))

    position = forms.ModelChoiceField(queryset=Verwendung.objects.all(), label='',
                                      empty_label="Einsatzverwendung", required=False, widget=forms.Select(attrs={
                                        'class': "form-select fw-bold border border-1 border-black m-1",
                                        'style': 'max-width: auto;',
                                        'required': 'True',
                                      }))

    begin = forms.DateField(label='', required=False, widget=forms.DateInput(attrs={
        'class': "form-control fw-bold border border-1 border-black m-1",
        'style': 'max-width: auto;',
        'placeholder': 'Beginn',
        'title': 'Beginn',
        'type': 'text',
        'onfocus': "(this.type = 'date')",
        'required': 'True',
    }))

    end = forms.DateField(label='', required=False, widget=forms.DateInput(attrs={
        'class': "form-control fw-bold border border-1 border-black m-1",
        'style': 'max-width: auto;',
        'placeholder': 'Ende',
        'title': 'Ende',
        'type': 'text',
        'onfocus': "(this.type = 'date')",
        'required': 'True',
    }))

managers.py:

class MissionDurationManager(models.Manager):
    def with_duration_days(self):
        return self.annotate(
            duration_days=ExpressionWrapper(
                (F('end') - F('begin')), output_field=fields.DurationField()
            )
        )

    def total_duration_days(self, employee):
        return self.with_duration_days().filter(employee=employee).aggregate(
            total_duration=Sum('duration_days')
        )['total_duration']

views.py:

            if 'save_mission' in request.POST:
                form = ForeignMissionsForm(request.POST)
                if form.is_valid():
                    form.save()
                    context['success'] = 'new entry saved'
                else:
                    context['error'] = 'there where errors'

template part for the form is simply {{ form.as_div }}

The error is raised, because of there is no value passed to database for the begin field and therefore the line duration = self.end - self.begin raises an error, because calculation with “None” is a bit difficult ;-). But I can not understand, why???

I don’t see in your code posted here where you’re calling with_duration_days.

If you’re getting an error, posting the traceback would be extremely helpful.

the problem is, if i exclude the DuraionManager complaetely form execution, then the “begin” value is still not saved in database…will post the traceback!

…total duration days is only used in this line in another function:

context['total_duration_days'] = ForeignMissions.objects.total_duration_days(employee)

and in template by
{{ total_duration_days|cut:" days, 0:00:00" }}

I’d also like to see how those fields (“begin” and “end”) end up actually rendered in the browser.

You might also want to print those values in your view to see what’s being submitted.

In which function, where?

If this context is being set in an area where you don’t yet have values for those fields, it would throw that error.

yeah, this is without a doubt but the error is somewhere else:

i just removed the (null=True, blank=True) from the begin-field in model and then i get an IntegrityError:
(1048, "Column 'begin' cannot be null")

Traceback says:

So the problem is, that clearly no value for “begin” is posted, despite fields are formatted same way and are filled with data when hitting save…

further Traceback information:

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/employees/show.html

Django Version: 4.2.3
Python Version: 3.11.2
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.utils.timezone',
 'django.template',
 'django_bootstrap_icons',
 'django_bootstrap5',
 'django_mysql',
 'haystack',
 'whoosh',
 'fontawesomefree',
 'drop_down',
 'accounts',
 'employees',
 'barcode']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\backends\utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\backends\mysql\base.py", line 75, in execute
    return self.cursor.execute(query, args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\MySQLdb\cursors.py", line 179, in execute
    res = self._query(mogrified_query)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\MySQLdb\cursors.py", line 330, in _query
    db.query(q)
    ^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\MySQLdb\connections.py", line 255, in query
    _mysql.connection.query(self, query)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The above exception ((1048, "Column 'begin' cannot be null")) was the direct cause of the following exception:
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\contrib\auth\decorators.py", line 23, in _wrapper_view
    return view_func(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\employees\views.py", line 237, in show
    form.save()
    ^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\forms\models.py", line 542, in save
    self.instance.save()
    ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\models\base.py", line 814, in save
    self.save_base(
    ^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\models\base.py", line 877, in save_base
    updated = self._save_table(
              
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\models\base.py", line 1020, in _save_table
    results = self._do_insert(
              
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\models\base.py", line 1061, in _do_insert
    return manager._insert(
           
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\models\manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\models\query.py", line 1805, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\models\sql\compiler.py", line 1822, in execute_sql
    cursor.execute(sql, params)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\backends\utils.py", line 102, in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\backends\utils.py", line 67, in execute
    return self._execute_with_wrappers(
           
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\backends\utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    with self.db.wrap_database_errors:
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\backends\utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\django\db\backends\mysql\base.py", line 75, in execute
    return self.cursor.execute(query, args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\MySQLdb\cursors.py", line 179, in execute
    res = self._query(mogrified_query)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\MySQLdb\cursors.py", line 330, in _query
    db.query(q)
    ^^^^^^^^^^^
  File "C:\Users\User\PycharmProjects\klinikXdatabase\venv\Lib\site-packages\MySQLdb\connections.py", line 255, in query
    _mysql.connection.query(self, query)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Exception Type: IntegrityError at /employees/show.html
Exception Value: (1048, "Column 'begin' cannot be null")

Check your browser’s console log to see if an error is being registered there.

Also look at your browser’s network tab to see what’s being submitted - that’ll help determine at which end the problem is occurring.

no, nothing there, and it worked a few days ago and i havent altered things in this part of code… :thinking:

I know we cross-posted here - check your network tab in the browser when you submit to verify that the date is being sent in the POST data.

That`s the point, it seems that is NOT being sent, but only this single field of the form and i don’t have a bit of an idea why…

EDIT: Deleting Browser data or using another browser has also no effect

The next step then would be to look at the actual HTML as it exists in the browser. It might be worth posting the entire form as it has been rendered, before and after data has been entered (and before it has been submitted).

it is no problem to get the actual HTML data that is processed in browser BEFORE data is entered and submitted…but how can i split the events “data entered” from “data submitted” ? if i fill out the form, nothing will happen in developer console…and if i click on submit i get the processed html of the raised error page…

I’m referring to what you can see in the browser’s developer tools.

Extract the html from the browser when the page is first received, enter data in the form, then extract the html again before pressing submit.

never mind, classical “pepkag”…

in template there i found this line, no idea in what tired condition i must have putted in there or why, but removing it did the job…

<input type="hidden" name="begin" value="{{ begin_value }}">

:see_no_evil: :see_no_evil: :see_no_evil: