Django Version: 1.10.4 Exception Type: ValueError
Exception Value:
"<SchoolBook: 0 test1 Test2 Test3 2011 122>" needs to have a value for field "schoolbook" before this many-to-many relationship can be used.
PLease help to avoid this error:
class Subject(models.Model):
name = models.CharField(max_length=256)
slug = models.SlugField(max_length=256, blank=True)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if not self.id:
self.slug = slugify(self.name, separator='_')
return super(Subject, self).save(*args, **kwargs)
class SchoolBook(models.Model):
parent_subject = models.ManyToManyField(Subject)
year = models.SmallIntegerField()
name = models.CharField(max_length=256,blank=True)
autors = models.CharField(max_length=256)
slug = models.SlugField(max_length=256, blank=True, unique=True)
f_file = models.FileField(upload_to=directory_path)
def __str__(self):
return '{0} {1} {2}'.format(
self.name, self.autors, self.year)
def save(self, *args, **kwargs):
if not self.id:
subject_name = [self.parent_subject.values()[i]['name'] for i in range(len(self.parent_subject.values()))]
self.name = ' '.join(subject_name)
self.slug = slugify("{} {} {} {} {}".format(self.name, self.autors,self.year, self.pages, self.c_class))
return super(SchoolBook, self).save(*args, **kwargs)
the issue is when i am trying to save the object.
You cannot access related objects of a many-to-many relation before the instance is saved! The instance must have an id
for the intermediate m2n table to point its foreign key (by the name of schoolbook
, hence the error message) to:
def save(self, *args, **kwargs):
if not self.id:
super(SchoolBook, self).save(*args, **kwargs)
# process self.parent_subject (should be called ...subjects, semantically)
super(SchoolBook, self).save(*args, **kwargs)
This is a minor correction to the (memorably named) @user2390182's answer.
I am not sure when it was introduced, but the model.save()
method now has a force_insert
parameter, which forces a SQL INSERT
statement. However, this does not set .pk
to None before saving.
Therefore just in case anything sets force_insert=True
(eg, factory-boy
does), the following code works, whereas @user2390182's second call to super().save will raise a duplicate key error:
def save(self, force_insert=False, *args, **kwargs):
if not self.pk:
super(SchoolBook, self).save(force_insert, *args, **kwargs)
force_insert = False
# process self.parent_subject (should be called ...subjects, semantically)
super(SchoolBook, self).save(force_insert, *args, **kwargs)
PS. force_insert
is the first parameter, hence it can be passed up as a positional arg.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.