我认为我对Django的FK和管理员的理解有点不对,所以我重视如何建模以下案例的任何输入。
首先,我们有通用的Address对象。然后,我们有User,每个都有UserProfile。通过这个,用户属于部门,也有地址。
部门本身也可以有多个地址,也可以是部门主管。所以它可能是这样的(这是我现在正在讨厌的事情):
class Address(models.Model):
street_address = models.CharField(max_length=20)
etc...
class Department(models.Model):
name = models.CharField(max_lenght=20)
head_of_department = models.OneToOneField(User)
address = models.ForeignKey(Address)
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
address = models.ForeignKey(Address)
department = models.OneToOneField(Department)
无论如何,首先,这是建立关系的正确方法吗?
其次,我希望它出现在管理员中,你可以编辑一个部门,在那个页面上,它有一个内联列表,列出了所有要编辑的地址。我已经尝试设置一个AddressInline类,并将其作为内联附加到Department。
class AddressInline(admin.TabularInline):
model = Address
class DepartmentAdmin(admin.ModelAdmin):
inlines = [AddressInline]
但是,当我尝试显示时,我得到:
Exception at /admin/people/department/1/
<class 'people.models.Address'> has no ForeignKey to <class 'people.models.Department'>
干杯, 维克多
答案 0 :(得分:2)
由于您似乎希望UserProfile或Department具有可能的许多地址,因此您的ForeignKeys是向后的。单个ForeignKey只能指向一个模型实例,而可以指向单个模型实例的ForeignKeys数量没有限制。因此,您的ForeignKey应该在地址上(在这种情况下,您的内联将按原样运行)。
复杂因素是你有一个地址模型,你想将它与其他两个模型联系起来;地址上的单个ForeignKey不能同时指向UserProfile和Department。一种解决方案是具有两个地址模型(DepartmentAddress,具有到Department的ForeignKey,以及UserAddress,具有到UserProfile的ForeignKey)。您可以通过从包含所有数据字段的abstract base class继承这些重复来减少代码中的重复,但最终仍会在数据库中使用两个大致相同的表。
另一个选项是在地址上有一个GenericForeignKey,它可以指向任何模型的实例。您的内联将需要成为GenericInlineModelAdmin。这违反了纯数据库规范化,并且不允许数据库进行正确的完整性检查。如果你将来有更多的模型也有地址,我会考虑这个;如果它可能仅限于当前的两个,我可能会选择上面的选项。
答案 1 :(得分:0)
我从你的模特中读到你的模特你想要的东西:
A department has one to many addresses
A department has one and only one user (as head of department)
A user (through his profile) belongs to one to many departments
A user (through his profile) has one to many addresses
如果这是你的意图,意味着没有用户不会有地址或部门的情况,也不会有部门没有地址或部门主管的情况;然后我会说你的模型是好的应该是:
class Department(models.Model):
name = models.CharField(max_lenght=20)
head_of_department = models.OneToOneField(User)
address = models.ForeignKey(Address)
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
address = models.ForeignKey(Address)
department = models.OneToOneField(Department)
class Address(models.Model):
street_address = models.CharField(max_length=20)
...
class Meta:
abstract = True
class UserAddress(Address):
user_profile = models.ForeignKey(UserProfile)
class DepartmentAddress(Address):
department = models.ForeignKey(Department)
详细了解abstract classes。
您的模型未考虑的是两个用户具有相同地址的可能性,和/或两个部门将具有相同地址的可能性。由于您没有在地址上指定唯一约束(我可以看到),我认为您可以在地址表中多次显示实际地址。
如果你没事;细
您收到的错误消息说明了一个事实:地址部门没有外键。 您必须恢复该内联的关系才能工作。这意味着,在编辑地址时,您可以编辑与之关联的任何部门;但不是相反的。根据我上面建议的模型,你不应该看到这个错误。
请参阅example from the docs。注意Author has many Books
如何以及关系的多方面如何是内联的。