我有一个用户的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)。
答案 0 :(得分:2)
首先,绝对不要将IntegerFields用于这些值。它们是外键,您应该使用ForeignKey字段。这些应称为user
和client
-请注意,您仍然可以像以前一样访问基础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方法。