Django模型,收集模型。自动字段编号,同时覆盖save()方法

时间:2019-01-16 16:05:50

标签: python django django-models model

我有一个用户的Django模型,然后有一个 AccessLevels 的单独模型。

使用Django的ORM保存用户时,我还要在 AccessLevels 表中放置一个条目。

我的问题是 AccessLevels PK Users PK ,我似乎无法覆盖save()方法并收集id = models.AutoField(primary_key=True)的值。

这是我的相关代码:

class Users(models.Model):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    # pk
    id = models.AutoField(primary_key=True)

    # client_id
    client_id = models.IntegerField(null=False, blank=False, default="-1")

    ...

    def save(self, *args, **kwargs):
        AccessLevel(user_id=self.id,
                client_id=self.client_id).save(using='default')

        print('Access Level Set for User while saving')
        super(Users, self).save(*args, **kwargs)

这是 AccessLevel

的重要部分
class AccessLevel(models.Model):

    # pk
    id = models.AutoField(primary_key=True)

    # this is the id for the user, but I get null value
    user_id = models.IntegerField(null=False, blank=False, default="-1")

    client_id = models.IntegerField(null=False, blank=False, default="-1")

调用此代码时出现错误。

root_user = Users(username='root',
                      email='root',
                      first_name='root',
                      last_name='root',
                      phone='root',
                      password=make_password(default_root_pw),
                      type='root').save(using='default')

这是错误

django.db.utils.IntegrityError:“ user_id”列中的空值违反了非空约束 详细信息:失败行包含(3,null,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)。

1 个答案:

答案 0 :(得分:2)

首先,绝对不要将IntegerFields用于这些值。它们是外键,您应该使用ForeignKey字段。这些应称为userclient-请注意,您仍然可以像以前一样访问基础ID。

(此外,无需显式声明id字段;并且您几乎永远都不应覆盖模型中的__init__,但尤其是绝不应该覆盖仅调用super的方法。方法。只需将其删除。)

class AccessLevel(models.Model):
    user = models.ForeignKey('Users', null=False, blank=False)
    client = models.ForeignKey('Client', null=False, blank=False)

class Users(models.Model):
    client = models.ForeignKey('Client', null=False, blank=False)

现在,对于您的实际问题,该ID由数据库分配,直到保存后才会发生。因此,您应该在此之后的 中创建您的相关项目。

def save(self, *args, **kwargs):
    super(Users, self).save(*args, **kwargs)
    AccessLevel(user_id=self.id,
            client_id=self.client_id).save(using='default')

    print('Access Level Set for User while saving')

创建项目的另一种方法(可能会更清楚一点)是使用外键提供的访问器:

self.accesslevel_set.create(client_id=self.client_id)

最后,这可能比a post-save signal更好,而不是用save方法。