Reputation: 511
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
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