简体   繁体   中英

ValueError: needs to have a value for field "" before this many-to-many relationship can be used

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM