Django - 一对一关系,一端多为NULL,另一端为NOT NULL

时间:2014-11-19 21:31:26

标签: python django postgresql django-models

我正在用Django和PostgreSQL编写简单的应用程序来管理一个家庭图书馆,我可以为那些借书的人(Borrower模型)提供许多借阅者资料。我有用户,他们可以自己借书,这样书就会被用户的借款人资料借用。

另一方面,管理员可以借书给任何借款人,甚至是未注册的用户。

所以我有一些MyUser s(以及那个字段,顺便说一句,引用Django的User)和许多Borrower,我想创建一对一的关系它们之间,但每个MyUser 引用一个唯一的Borrower,但许多Borrower不会引用任何现有的MyUser(它们可以只引用一个或不引用,或者换句话说,只引用一个或没有用户)。

我的问题是:如何以最佳方式进行建模?使用models.OneToOneFieldmodels.ForeignKey以及哪个模型应该引用哪个?

我可能会有很多借款人,他们没有用户帐户。

自然解决方案似乎是OneToOneField(Borrower, null=False)模型中的User。但是,当根据借款人搜索用户时,我将不得不主要处理DoesNotExists例外,并且只会偶尔处理一次,我会得到正确的结果。

我也可以ForeignKey(Borrower, unique=True, null=False) - 然后我将检查具有单个元素或空的集合。

我可以双向ForeignKey

class Borrower(models.Model):
    # ...
    user = models.ForeignKey(MyUser, unique=True, null=True)

class MyUser(models.Model):
    # ...
    borrower = models.ForeignKey(Borrower, unique=True, null=False)

这隐含地定义了关系,我可以轻松地进行搜索,但它也在数据库表中创建了一个额外的冗余字段。

我现在可能只会坚持使用OneToOneField,但我想知道在这种情况下哪种方法最有意义。什么是触发和缺点?还有其他更好的解决方案吗?

1 个答案:

答案 0 :(得分:0)

我会坚持使用OneToOneField;正如你所说,这是最自然的解决方案。

您提到的唯一缺点是borrower.user可能会引发DoesNotExist例外。如果您不喜欢这样,您可以随时定义自己的方法(或属性)以返回其他内容(如None)。类似的东西:

class MyUser(models.Model):
    borrower = models.OneToOneField(Borrower, null=False)

class Borrower(models.Model):
    @property
    def user(self):
        try:
            return self.myuser
        except DoesNotExist:
            return None

    @user.setter
    def user(self, user):
        self.myuser = user