如何在一组公司之间建模贷款项目

时间:2011-04-13 22:17:03

标签: django design-patterns database-design django-models python

我有一组相关公司,他们彼此分享他们拥有的物品。每个项目都有一个拥有它的公司和一个拥有它的公司。显然,拥有该物品的公司也可以拥有它。此外,公司有时会永久性地转让物品的所有权而不仅仅是放贷,所以我也必须考虑到这一点。

我正在尝试决定如何建模物品的所有权和拥有权。我有一个Company表和一个Item表。

以下是我看到的选项:

  1. Inventory表,其中包含每个Item - Company关系的条目。有company字段指向Company并且具有布尔字段is_owner和has_possession。
  2. Inventory表,其中包含每个Item的条目。有owner_company字段和possessing_company字段,每个字段都指向Company
  3. 两个单独的表:ItemOwnerItemHolder **。
  4. 到目前为止,我倾向于选项三,但表格所以类似于感觉就像重复一样。选项二每个项目只有一行(在这方面比选项一更干净),但在一个表上有两个引用Company表的字段没有闻到正确(并且在ER中绘制很麻烦)图!)。

    数据库设计不是我的专长(我主要使用非关系数据库),所以我不知道在这种情况下最佳实践是什么。另外,我是Python和Django的新手,因此我可能会错过一个明显的习惯用语或模式。

    在没有CompanyItem被所有权和占有权知识污染的情况下,对此进行建模的最佳方法是什么?或者我是否因为想让我的模型如此隔离而错过了这一点?什么是Pythonic方式?

    更新

    我意识到我过于关注数据库设计。只编写好的OO代码并让Django的ORM做到这一点是明智的吗?

3 个答案:

答案 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,再加上外键。

第二种方法更容易实现,但第一种方法一旦实施就会更自然。