Dhruva Gowda Storz
Dhruva Gowda Storz

Reputation: 511

Integrity Error NOT NULL constraint failed even though I have set blank=True, null=True in my model

Im getting a NOT NULL constraint error in my code when trying to save my model form, even though the fields I have left empty are optional (have set blank=True, null=True) in models.py

Im very confused, what am I doing wrong?

The error is popping up when I leave the first optional field blank (description). Filling any of them manually before work.save() pushes the issue to the next field, and passes when all fields are filled.

EDIT: this also happens when trying to create a work instance from the admin dashboard.

models.py

class Work(models.Model):
    ## core fields
    creator = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True,
                                   default=None)
    created = models.DateTimeField()
    modified = models.DateTimeField()
    work_slug = models.SlugField(max_length=50) # slug -> TBD: find way to assign default value to slug = archival number.

    archive = models.ForeignKey(Archive, on_delete=models.CASCADE)


    # superfolder -> replaces category, series etc with dynamic hierarchical database
    folder = models.ForeignKey(Folder, on_delete=models.CASCADE)
    

    # basic metadata fields
    name = models.CharField(max_length=50)
    year = models.CharField(max_length=50)
    medium = models.CharField(max_length=50)
    description = models.CharField(max_length=1200, blank=True, null=True)

    # optional metadata
    authors = models.CharField(max_length=50, blank=True, null=True)
    classification = models.CharField(max_length=50, blank=True, null=True)
    location = models.CharField(max_length=50, blank=True, null=True)
    link = models.URLField(max_length=50, blank=True, null=True)
    record_creator = models.CharField(max_length=50, blank=True, null=True) # revisit -> 

    # custom descriptors
    cd1_name = models.CharField(max_length=50, blank=True, null=True)
    cd1_value = models.CharField(max_length=50, blank=True, null=True)
    cd2_name = models.CharField(max_length=50, blank=True, null=True)
    cd2_value = models.CharField(max_length=50, blank=True, null=True)
    cd3_name = models.CharField(max_length=50, blank=True, null=True)
    cd3_value = models.CharField(max_length=50, blank=True, null=True)
    cd4_name = models.CharField(max_length=50, blank=True, null=True)
    cd4_value = models.CharField(max_length=50, blank=True, null=True)
    cd5_name = models.CharField(max_length=50, blank=True, null=True)
    cd5_value = models.CharField(max_length=50, blank=True, null=True)
    cd6_name = models.CharField(max_length=50, blank=True, null=True)
    cd6_value = models.CharField(max_length=50, blank=True, null=True)
    cd7_name = models.CharField(max_length=50, blank=True, null=True)
    cd7_value = models.CharField(max_length=50, blank=True, null=True)


    # Standardized Metadata


    # Methods
    def __str__(self):
        return 'Work: {}'.format(self.name)

    def save(self, *args, **kwargs):
        ''' On save, update timestamps '''
        user = get_current_user()

        if not self.id: # if the model is being created for the first time:
            self.creator = user # assign the currently logged in user as the creator
            self.created = timezone.now() # set the 'created' field to the current date and time
            # self.slug = **archival id of work (automatically determined)** 
        self.modified = timezone.now() # set the modified field to the current date and time. This is reassigned everytime the model is updated.

        return super(Work, self).save(*args, **kwargs)

forms.py

class WorkForm(ModelForm):
    class Meta:
        model = Work
        fields = ['name', 'year', 'medium', 'description', 'authors', 'classification', 'location', 'link', 'record_creator', 'cd1_name', 'cd1_value', 'cd2_name', 'cd2_value', 'cd3_name', 'cd3_value', 'cd4_name', 'cd4_value', 'cd5_name', 'cd5_value', 'cd6_name', 'cd6_value', 'cd7_name', 'cd7_value']

views.py

def add_work(request, folder_pk):
    '''
    Add a work to the filesystem.

    folder_pk: the primary key of the parent folder

    Checks if the user is logged in and if the user is the creator of the folder. If so, the user is allowed to add a work to the folder. Otherwise, the user is redirected to the login page.
    '''
    # add work to the database
    parent = Folder.objects.get(pk=folder_pk)
    mediaFormSet = modelformset_factory(MediaFile, fields=('name', 'alt_text', 'caption', 'media'), extra=1)

    

    if request.method == "POST" and parent.archive.creator == get_current_user():
        # if the form has been submitted
        # Serve the form -> request.POST
        form = WorkForm(request.POST)
        # mediaFormSet = mediaFormSet(request.POST)

        if form.is_valid(): # if the all the fields on the form pass validation

            # Generate archival ID for work
            # archival ID is random, unique 6 digit number that identifies the work
            archival_id = get_archival_id()

            # create a new work with the parameters retrieved from the form. currently logged in user is automatically linked
            work = form.save(commit=False)
            work.work_slug = archival_id
            work.folder=parent
            work.archive=parent.archive
            work.save()
            
            # Redirect to dashboard page
            return redirect('add_media_to_work', work_pk=work.pk)

    else:
        # If the form is not submitted (page is loaded for example)
        # -> Serve the empty form
        form = WorkForm()


    return render(request, "archival/add_edit_work.html", {"workForm": form})

Upvotes: 1

Views: 701

Answers (1)

Kimanxo
Kimanxo

Reputation: 11

i was facing the same problem as you, i made a sign up form, and it was giving me the same error because the .save() method was getting executed before i fill in the fields, there was no data to save, because of that: the fields type was None. so i just implemented an if else statement to make sure that the .save() method won't be executed if the type of the field isnNone, here is a snippet:

if field == None:
    pass
else:
    form.save()

Upvotes: 1

Related Questions