Django给出无法在没有主键的情况下强制执行save()更新

Sen*_* H. 4 django

ValueError: Cannot force an update in save() with no primary key.在代码遇到异常并运行get_or_create代码时得到了.Model在数据库中有自动增量id字段的表.而且这不是更新过程.我无法理解为什么Django表现得像这样.

错误:

Traceback (most recent call last):
  File "x.py", line 1980, in <module>
    getattr(a, islem)()
  File "x.py", line 718, in method
    Slug='undefined', Status=False)
  File "~/env/local/lib/python2.7/site-packages/django/db/models/manager.py", line 135, in get_or_create
    return self.get_query_set().get_or_create(**kwargs)
  File "~/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 385, in get_or_create
    obj.save(force_insert=True, using=self.db)
  File ~/core/modules/xx/models.py", line 78, in save
    super(Categories, self).save(args, kwargs)
  File "~/env/local/lib/python2.7/site-packages/django/db/models/base.py", line 460, in save
    self.save_base(using=using, force_insert=force_insert, force_update=force_update)
  File "x/env/local/lib/python2.7/site-packages/django/db/models/base.py", line 541, in save_base
    raise ValueError("Cannot force an update in save() with no primary key.")
ValueError: Cannot force an update in save() with no primary key.
Run Code Online (Sandbox Code Playgroud)

码:

try:
    category = Categories.objects.get(Code=category_code)
except ObjectDoesNotExist:
    category, created = Categories.objects.get_or_create(
        Name='Undefined', Code='undefined',ParentCategoryID=None, OrderID=0,
        Slug='undefined', Status=False)
Run Code Online (Sandbox Code Playgroud)

模型:

class Categories(models.Model):
    Name = models.CharField(max_length=155)
    Code = models.CharField(max_length=255)
    ParentCategoryID = models.ForeignKey('self', related_name='SubCategory', null=True, blank=True)
    Level = models.IntegerField(default=0, max_length=10, editable=False)
    OrderID = models.IntegerField(blank=True, max_length=10)
    Slug = models.SlugField(max_length=250)
    CreateDate = models.DateTimeField(auto_now_add=True)
    LastUpdateDate = models.DateTimeField(auto_now=True)
    Status = models.BooleanField(default=True)

    def save(self, *args, **kwargs):

        if self.ParentCategoryID is not None:
            parent = Categories.objects.get(id=self.ParentCategoryID.id)
            self.Level = parent.Level + 1

        if self.OrderID <= 0:
            try:
                top = Categories.objects.order_by('-OrderID')[0]
                self.OrderID = top.OrderID + 1
            except:
                self.OrderID = 1
        super(Categories, self).save(args, kwargs)
Run Code Online (Sandbox Code Playgroud)

Dan*_*man 8

当你打电话给super时,你需要使用*和**:

super(Categories, self).save(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

请注意,此代码中还有一些其他奇怪的东西.主要是这一行:

parent = Categories.objects.get(id=self.ParentCategoryID.id)
Run Code Online (Sandbox Code Playgroud)

无缘无故地做两个相同的查询; self.ParentCategoryID已经父对象.你应该这样做:

parent = self.ParentCategoryID
Run Code Online (Sandbox Code Playgroud)

这将导致你的结论,即ParentCategoryID是严重命名; 它包含实际对象,而不是ID.

还要注意,有很多样式违规; Python更喜欢lower_case_with_underscore属性名称,而Django更喜欢奇异的模型名称.但是,外键的相关名称应该是复数,因为它将引用多个类别对象.所以:

class Category(models.Model):
    name = models.CharField(max_length=155)
    code = models.CharField(max_length=255)
    parent_category = models.ForeignKey('self', related_name='sub_categories', null=True, blank=True)
    ...
Run Code Online (Sandbox Code Playgroud)

  • 太好了,谢谢你的回答,我有时会完全失明。我很欣赏额外的信息。 (2认同)