我有一组相关公司,他们彼此分享他们拥有的物品。每个项目都有一个拥有它的公司和一个拥有它的公司。显然,拥有该物品的公司也可以拥有它。此外,公司有时会永久性地转让物品的所有权而不仅仅是放贷,所以我也必须考虑到这一点。
我正在尝试决定如何建模物品的所有权和拥有权。我有一个Company
表和一个Item
表。
以下是我看到的选项:
Inventory
表,其中包含每个Item
- Company
关系的条目。有company
字段指向Company
并且具有布尔字段is_owner和has_possession。Inventory
表,其中包含每个Item
的条目。有owner_company
字段和possessing_company
字段,每个字段都指向Company
。ItemOwner
和ItemHolder
**。到目前为止,我倾向于选项三,但表格所以类似于感觉就像重复一样。选项二每个项目只有一行(在这方面比选项一更干净),但在一个表上有两个引用Company
表的字段没有闻到正确(并且在ER中绘制很麻烦)图!)。
数据库设计不是我的专长(我主要使用非关系数据库),所以我不知道在这种情况下最佳实践是什么。另外,我是Python和Django的新手,因此我可能会错过一个明显的习惯用语或模式。
在没有Company
和Item
被所有权和占有权知识污染的情况下,对此进行建模的最佳方法是什么?或者我是否因为想让我的模型如此隔离而错过了这一点?什么是Pythonic方式?
我意识到我过于关注数据库设计。只编写好的OO代码并让Django的ORM做到这一点是明智的吗?
答案 0 :(得分:2)
您是否有理由不希望您的商品包含关系信息?感觉主人和拥有者是物品的属性。
class Company(models.Model):
pass
class Item(models.Model):
...
owner = models.ForeignKey(Company, related_name='owned_items')
holder = models.ForeignKey(Company, related_name='held_items')
一些例子:
company_a = Company.objects.get(pk=1)
company_a.owned_items.all()
company_a.held_items.all()
items_owned_and_held_by_a=Items.objects.filter(owner=company_a, holder=company_a)
items_on_loan_by_a=Items.objects.filter(owner=company_a).exclude(holder=company_a)
#or
items_on_loan_by_a=company_a.owned_items.exclude(holder=company_a)
items_a_is_borrowing=Items.objects.exclude(owner=company_a).filter(holder=company_a)
#or
items_a_is_borrowing=company_a.held_items.exclude(owner=company_a)
company_b = Company.objects.get(pk=2)
items_owned_by_a_held_by_b=Items.objects.filter(owner=company_a, holder=company_b)
#or
items_owned_by_a_held_by_b=company_a.owned_items.filter(holder=company_b)
#or
items_owned_by_a_held_by_b=company_b.held_items.filter(owner=company_a)
我认为如果您的商品仅由一家公司拥有并由一家公司持有,则不需要单独的表格。如果物品可以拥有多个所有权或多个持有者,那么通过库存表的m2m表会更有意义。
答案 1 :(得分:0)
class Inventory(models.Model):
REL = (('O','Owns'),('P','Possesses'))
item = models.ForeignKey(Item)
company = models.ForeignKey(Company)
relation = models.CharField(max_length=1,choices=REL)
可以是一个实现,而不是使用布尔值。所以我会选择第一个。如果您决定使用“通过”将项目与公司关联,这甚至可以作为中间表:
Company:
items = models.ManyToManyField(Item, through=Inventory)
答案 2 :(得分:0)
选项#1可能是最干净的选择。物品只有一个所有者公司,只有一个拥有公司。
将两个FK放入Item中的Company,并记住明确定义两个反转的related_name彼此不同。
如果您想避免触摸Item模型,可以从外部添加FK,例如在field.contribute_to_class()中添加,或者将具有一对一rel的新模型添加到Item,再加上外键。
第二种方法更容易实现,但第一种方法一旦实施就会更自然。