【发布时间】:2015-04-15 18:32:58
【问题描述】:
我对 Django 的数据库抽象层比较陌生。老实说,我没有太多通过任何系统与数据库交互的经验。无论如何,我正在从事一个个人项目,并且对我目前的设计不满意,至少就我的疑问而言。我想我会向社区寻求如何处理我的担忧的建议。
这是一个开始讨论的简化案例。假设我们正在对一个国家/地区的信息进行建模。我们可能会想出以下
class Country(models.Model):
...
class Region(models.Model):
country = models.ForeignKey(Country)
...
class State(models.Model):
region = models.ForeignKey(Region)
...
class County(models.Model):
state = models.ForeignKey(State)
...
class City(models.Model):
state = models.ForeignKey(County)
...
好的。我对这种结构很满意,因为没有多余的信息。耶。但是,当涉及到许多我想做的查询时,我会得到这样的陈述:
# get the country a city is in
def get_country(city):
return Country.objects.get(region__state__county__city=city)
这行得通,但它让我很困扰,原因如下:当我指定我的模型时,我给了 Djano 我的数据库结构。也就是说,系统已经知道一个城市在一个县,一个县在一个州,一个州在一个地区,最后一个地区在一个国家。当我编写上面的查询时,我提供了冗余信息;这种结构已经暗示每个城市只有一个国家。因此,给定一个城市,它在哪个国家/地区一目了然。为什么我必须再次指定它?
出于多种原因,必须这样做会对开发产生负面影响。首先考虑,例如a get_region()函数:
#get the region a city is in:
def get_region(city):
return Region.objects.get(state__county__city=city)
这一切都与 get_country 函数几乎相同; get_country 查询已经包含了获取地区所需的信息,所以我再次通知系统城市在县,在州,在地区。
进一步,考虑以下场景:我意识到我误解了最初的要求,我什至不需要考虑“区域”。因此,擦除该模型并更改 State 模型以包含对 Country 的引用。现在的问题是我们还必须重写所有查询。
这很快就会变得丑陋。假设我们想要模型上的辅助方法来获取层次结构的相关信息。例如,Country 可能有方法get_states()、get_counties()、get_cities()。各州将拥有get_country(),以及get_county() 和get_cities()。以此类推,每个人都得到了图片。这似乎是明智的,因为它将提供一个 API,系统的其他部分可以通过该 API 以与数据库布局无关的方式访问此地理信息。然而,这也意味着,由于我们编写为这些功能提供动力的查询的方式,每个模型都必须对数据库有宏观的理解。如果需要对该结构进行更改,这种未能将地理语义与我们的数据库实现分开将再次导致大量重复信息和大量工作。
所以,请朋友们赐教。我是否没有正确考虑模型之间的关系?我不欣赏 Django 数据库层的哲学吗?我是否遗漏了一些可以帮助我澄清这一点的功能子集?
【问题讨论】:
-
您确定要在此处使用 OneToOne 字段吗?这意味着不仅一个城市只能在一个国家,而且一个国家只能有一个城市,这听起来不对。
-
啊,对不起。我改变了我的例子一百万次,忘了回到 ForeignKey
-
Country被定义了两次。 -
不,有县和国家。抱歉,我怀疑这可能会导致一些问题:(。
标签: python django django-models orm django-orm