我在创建具有递归关系的对象时遇到问题。因此,场景就在创建组织之后,将用户插入到刚刚创建的组织中。
# models.py
class Organization(models.Model):
name = models.CharField(max_length=32)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
code = models.CharField(max_length=4, unique=True)
photo_path = models.CharField(max_length=256, null=True)
class Meta:
db_table = 'organization'
def __str__(self):
return self.name
class OrganizationLevel(models.Model):
organization = models.ForeignKey(
Organization,
on_delete=models.CASCADE,
db_index=False
)
parent = models.ForeignKey(
'self',
on_delete=models.CASCADE,
db_index=False
)
name = models.CharField(max_length=48)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'organization_level'
unique_together = ('name', 'organization')
class OrganizationUnit(models.Model):
organization_level = models.ForeignKey(
OrganizationLevel,
on_delete=models.CASCADE,
db_index=False
)
name = models.CharField(max_length=48)
position = models.PointField(geography=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
parent = models.ForeignKey(
'self',
on_delete=models.CASCADE,
db_index=False
)
address = models.CharField(max_length=256)
class Meta:
db_table = 'organization_unit'
unique_together = ('name', 'organization_level')
class User(models.Model):
email = models.CharField(max_length=64)
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
token = models.CharField(max_length=32, null=True)
tokenexp = models.DateTimeField(null=True)
photo_path = models.CharField(max_length=256)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
organization = models.ForeignKey(
Organization,
on_delete=models.CASCADE
)
is_activated = models.BooleanField(default=False)
code = models.CharField(max_length=32, null=True)
name = models.CharField(max_length=64)
birthdate = models.DateTimeField(null=True)
sex = models.CharField(max_length=1)
address = models.CharField(max_length=80)
organization_unit = models.ForeignKey(
OrganizationUnit,
on_delete=models.CASCADE
)
class Meta:
db_table = 'user'
所以从给定的模型来看,这里是流程:
我已经尝试过这样但却出错了
org = Organization.objects.create(
name=name,
code=code.upper()
)
org.save()
lvl = OrganizationLevel.objects.create(
organization=org,
parent=org.id,
name="Level1"
)
lvl.save()
unit = OrganizationUnit.objects.create(
name="Unit Name",
organization_level=lvl,
parent=lvl.id
)
unit.save()
无法分配" 6":" OrganizationLevel.parent"必须是" OrganizationLevel"实例
什么是正确答案?
答案 0 :(得分:1)
如果您更改了组织级别模型,该怎么办:
class OrganizationLevel(models.Model):
organization = models.ForeignKey(
Organization,
on_delete=models.CASCADE,
db_index=False
)
parent = models.ForeignKey(
'self',
on_delete=models.CASCADE,
db_index=False,
blank=True,
null=True
)
name = models.CharField(max_length=48)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'organization_level'
unique_together = ('name', 'organization')
答案 1 :(得分:1)
对于递归关系(ForeignKey to self),外键需要接受null - 否则你将永远无法创建至少第一个实例(否则它将需要对另一个预先存在的记录的引用,这不能是创建时没有引用另一个预先存在的记录等 - 鸡和鸡蛋问题......),所以你想要:
class OrganizationLevel(models.Model):
# ...
parent = models.ForeignKey(
'self',
on_delete=models.CASCADE,
db_index=False,
null=True,
blank=True
)
和
class OrganizationUnit(models.Model):
# ...
parent = models.ForeignKey(
'self',
on_delete=models.CASCADE,
db_index=False,
null=True,
blank=True
)
创建第一个级别和单位时,请留下这些空白:
lvl = OrganizationLevel.objects.create(
organization=org,
parent=None,
name="Level1"
)
unit = OrganizationUnit.objects.create(
name="Unit Name",
organization_level=lvl,
)
请注意,YourModel.objects.create()
会在数据库中创建记录,因此您无需在此处为您的实例调用.save()
。
然后,当您想要添加子级别或子级单元时,您必须将父实例(不是它的id - 实例本身)作为parent
参数传递或将父实例ID传递为parent_id
参数(实际上对于任何ForeignKey都相同:您的传递' fieldname = related_instance'或' fieldname_id = related_instance_id)。