NOT NULL constraint failed

Hey,

I created a Job Model with a ModelForm to create the Job. If I click the submit button at the form this error messages appears:

Internal Server Error: /createjob/
Traceback (most recent call last):
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\sqlite3\base.py", line 423, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: Site_job.job_creator_id

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Finn\PyCharmProjects\JobMaze\JobMaze\Site\views.py", line 77, in job_create
    form.save()
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\forms\models.py", line 468, in save
    self.instance.save()
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 726, in save
    self.save_base(using=using, force_insert=force_insert,
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 763, in save_base
    updated = self._save_table(
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 868, in _save_table
    results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 906, in _do_insert
    return manager._insert(
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\query.py", line 1270, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\sql\compiler.py", line 1416, in execute_sql
    cursor.execute(sql, params)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 98, in execute
    return super().execute(sql, params)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\Finn\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\sqlite3\base.py", line 423, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: NOT NULL constraint failed: Site_job.job_creator_id

I guess something is wrong with the job_creator Field in my Models.py. I’ve used the normal user from the Auth Library for my ForeignKey.

Models.py

from django.db import models
from django.contrib.auth.models import User



class Job(models.Model):
    job_name = models.CharField(max_length=50)
    job_description = models.CharField(max_length=200)
    job_creator = models.ForeignKey(User, on_delete=models.CASCADE)
    job_price = models.IntegerField()

Forms.py

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.forms import ModelForm

from .models import Job


class CreateUserForm(UserCreationForm):
    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']


class JobForm(ModelForm):
    class Meta:
        model = Job
        fields = ['job_name', 'job_description', 'job_price']

views.py

def job_create(request):
    if request.method == 'POST':
        form = JobForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('home:adjust')
    else:
        form = JobForm()
    return render(request,
                  'home/job_create.html',
                  {'form': form}

                  )
1 Like

The job_creator field is not in your JobForm, nor are you assigning a value to it in your view.
Since you’re not providing a value for it, it’s null. Your model definition for that field does not allow nulls, so it’s throwing the error.

yeah that part with the creator in the form should be like this because the person who fills the form is always the creator so I removed the job_creator field from the form. What should I change in the views and in the Model Field that the error doesnt appear?

You’ll want to set a value on that field.

(In any view, how do you know who the user is making a request?)

Also see the docs on the save() method, particularly the text after the first example block and the second example.

and how can I set a value on that field, like automaticly by submitting the form not as a seperate field on the form. The user which is submitting should be the job_creator.

I tried to set the job creator manually in the views:

def job_create(request):

    if request.method == 'POST':

        form = JobForm(request.POST)

        if form.is_valid():

            Job.job_creator = request.user

            form.save()

            return redirect('home:adjust')

    else:

        form = JobForm()

    return render(request,

                  'home/job_create.html',

                  {'form': form}

                  )

But the NOT NULL Error things still shows up

You are really close - you need to save the form first (using the commit=False parameter). This call returns an instance of the object. Then you can assign request.user to the field on the object and then call save on the object. (Basically the process in the second example as referenced above, with the exception that there’s no many-to-many field involved.)

2 Likes

So I’ve addet the commit=false Parameter and it worked. And I saved my Object with Job.save()

def job_create(request):
    if request.method == 'POST':
        form = JobForm(request.POST)
        if form.is_valid():
            Job.job_creator = request.user
            form.save(commit=False)
            Job.save
            return redirect('home:adjust')
    else:
        form = JobForm()
    return render(request,
                  'home/job_create.html',
                  {'form': form}

                  )

Is this how you meant?

And another question how can I see all Job Model Instances I’ve created is there an command or a list to look that up?

And thanks for your help again!

Please post the code here from the second example in the docs on the save() method.

Are you talking about creating a page with such a list or something else? (You also have the Django shell and dumpdata commands that you could use.)

Ahh you mean the many to many save type.

def job_create(request):

    if request.method == 'POST':

        form = JobForm(request.POST)

        if form.is_valid():

            Job.job_creator = request.user

            form.save(commit=False)

            form.save_m2m()

            return redirect('home:adjust')

    else:

        form = JobForm()

    return render(request,

                  'home/job_create.html',

                  {'form': form}

                  )

And:

No I’m not trying to make a site with them I just want to see how much and which ones I have, I’m going to look at the commands you’ve send me, maybe there is smthng like I search

From my earlier response:

Basically the process in the second example as referenced above, with the exception that there’s no many-to-many field involved. (Emphasis added)

So please post that example, not your code.

Create a form instance with POST data.

f = AuthorForm(request.POST)

Create, but don’t save the new author instance.

new_author = f.save(commit=False)

Modify the author in some way.

new_author.some_field = ‘some_value’

Save the new instance.

new_author.save()

Now, save the many-to-many data for the form.

f.save_m2m()

# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)

# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)

# Modify the author in some way.
>>> new_author.some_field = 'some_value'

# Save the new instance.
>>> new_author.save()

So this is the common pattern.

  1. The form is bound to the posted data
  2. The form is saved with commit=False, the return value is an instance of the Model.
  3. The model field has a field set to some value not from the form.
  4. The modified model is saved.

These steps, in this order.

Like this? I’ve done it like in your pattern.

def job_create(request):
    if request.method == 'POST':
        form = JobForm(request.POST)
        if form.is_valid():
            Job = form.save(commit=False)
            Job.job_creator = request.user
            Job.save()

            return redirect('home:adjust')
    else:
        form = JobForm()
    return render(request,
                  'home/job_create.html',
                  {'form': form}

                  )

But the Job=form.save… thing is another like in my Model how does the code know that the Job Variable belongs to the Model

And btw this code works I logged myself in the DB and there is a list of all jobs I’ve created

grafik

You can see the job_creator id on job 3 is another because I used another account there, so it works as it should right?

Yep, the pattern is correct.

What confused me the first time you posted this was the reuse of “Job” as the name of an instance of an object. You really want to pick a different name because you don’t want to confuse your use of “Job” the variable with “Job” the Model class, and changing what Job is referring to can cause problems.

Because you define it as such:

The save method returns the instance of the model created by that form.

So I’ve now renamed the Model to “JobModel” that I dont confound both.

Thanks for your help.

You still ought to conform with the standard Python conventions.

At a minimum, you want it to be job = form.save(...) and not Job = form.save(...). What you get back from the save method is an instance, not a class.

Yup,
Changed it! I have to read the Python conventions never did that tbh because I came from web development to Python.

I have the same issues too, have no idea how to fix