我正在使用Django和PostgreSQL编写简单的应用程序来管理家庭图书库,在那里我可以为借书的人提供许多借阅者档案(Borrower
模型)。我有用户,他们可以自己借书,这样这本书就可以被用户的借阅者资料借出。
另一方面,管理员可以将书籍借给任何借阅者,甚至是未注册为用户的人。
所以我有几个MyUser
s(顺便说一句,那个字段引用了Django的User
)和许多Borrower
,我想在它们之间创建一个一对一的关系,但是每个MyUser
都必须引用一个唯一的Borrower
,但是许多Borrower
不会引用任何现有的MyUser
(它们只能引用一个或没有, 或者换句话说,仅由一个用户引用或没有用户引用)。
我的问题是:如何以最佳方式建模?使用models.OneToOneField
,models.ForeignKey
以及哪个模型应该引用哪个模型?
我可能会有很多借款人,他们没有用户帐户。
自然解决方案似乎在User
模型中OneToOneField(Borrower, null=False)
。但是,在根据借款人搜索用户时,我将不得不主要处理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
,但我想知道在这种情况下哪种方法最有意义。过程和缺点是什么?有没有替代的、更好的解决方案?
我会坚持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