Django ORM模型:想说爱你不容易

  • 时间:
  • 浏览:1
  • 来源:5分时时彩官网_5分时时彩下注平台注册_5分时时彩邀请码

作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁转载。

使用Python的Django模型的话,一般总要用它自带的ORM(Object-relational mapping)模型。你这个 ORM模型的设计比较简单,学起来我越多 很重花时间。不过,Django的ORM模型有我本人的一套语法,有之总要觉得别扭。这里聊一下我我本人的体会。

模型设计

你这个 帕累托图算处理得比较好的帕累托图。Django的数据模型的建立过程很简单,统统继承django.db.models中的Model类,已经 给它增加属性。每一三个小属性还都可以 对应关系数据库中的一三个小字段。比如在一三个小叫myapp的Django App下,创建models.py文件:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=10)

通过manage.py的makemigrations和migrate命令,就还都可以 执行数据库的迁移。底下的name属性,就对应了生成的myapp_person表中名为"name"的一列。这里的max_length=10对应了限制条件:

(在MySQL V4中,代表了10个字节;在MySQL V5中,代表了10个字符。)

除了底下的字符类型,或多或少常见的字段类型,在Django有的是对应的*Field来表达,比如TextField、DateField、DateTimeField、IntegerField、DecimalField。此外,还有或多或少常见的限制条件,除了底下的max_length,还有default、unique、null、primary_key等等。数字类型的限制条件有max、min、max_digits、decimal_places。哪几种限制条件都通过参数的形式传给属性。有或多或少限制条件是Django提供的,并那末数据库层面的对应物,比如blank。

(当blank参数为真时,对应字段还都可以 为留为空白。)

在基本的模型设计上,Django ORM那末留哪几种坑。

关系

Django中的一对一、多对一、多对多关系还都可以 通过下面最好的土法律法律依据表达:

from django.db import models


class Company(models.Model):
    name = models.CharField(max_length=10)


class Group(models.Model):
    name = models.CharField(max_length=10)


class Person(models.Model):
    name = models.CharField(max_length=10)


class Customer(models.Model):

name = models.CharField(max_length=10) person
= models.OneToOneField(Person) company = models.ForeignKey(Company, on_delete=models.CASCADE) groups = models.ManyToManyField(Group)

Customer的定义中,用到一对一、多对一、多对多关系。它们分别通过OneToOneField、ForeignKey和ManyToManyField来实现。

不到注意的是,在Django ORM中,不到通过ForeignKey来定义多对一关系,不到显示地定义一对多关系。但给你使用模型对象的*_set语法来反向调用多对一关系。比如说:

company.customer_set   #company是一三个小Company的实例

就还都可以 根据一对多关系,调到该公司下的所有客户。此外,多对多关系也还都可以 用之类的最好的土法律法律依据反向调用,比如:

此外,你还还都可以 在模型中加入related_name参数,从而在反省调用时,改用"*_set"之外的或多或少名称,比如:

class Customer(models.Model):
   person  = models.OneToOneField(Person)
   address = models.CharField(max_length=100)
   company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name="customers")

不可能 一三个小模型之间有多个关系时,related_name还都可以 处理*_set重名。

总的来说,底下的处理方案还都可以 实现功能,并非影响使用。但我无缘无故觉得你这个 处理方案或多或少丑陋。不可能 不到显式地表达一三个小模型之间的关系,模型之间的关系看起来存在问题明了。很重是读代码时,第一三个小类定义全版那末提示一对多的关系。我必不到看过了第三个小类定义,都可以搞明白一三个小模型之间的关系。真希望某种显式说明关系的最好的土法律法律依据,降低读代码时的认知负担。

查询

Django ORM还都可以 通过或多或少最好的土法律法律依据来实现。其中的统统最好的土法律法律依据返回的是Django自定义的QuerySet类的迭代器。Python看过迭代器总要懒惰求值,统统哪几种最好的土法律法律依据返回时并非会真正进行数据库操作。统统,多个最好的土法律法律依据串联操作时,就处理了重复操作数据库。返回QuerySet的常见最好的土法律法律依据包括:

all()
filter()
exclude()
annotate()
order_by()
reverse()
distinct()
...

对于依赖具体数据的操作,QuerySet会求值。比如遍历QuerySet时,就会先执行数据库操作。用len()获得QuerySet长度时,也会造成QuerySet估值。此外QuerySet或多或少最好的土法律法律依据,比get()、count()、earlist()、exists()等,总要对QuerySet进行求值。已经 ,在写应用线程时,要注意QuerySet求值的时间点,处理重复的数据库操作。

SQL的WHERE条件还都可以 通过参数的形式来传给最好的土法律法律依据。哪几种参数一般是"[字段]__[运算符]"的命名最好的土法律法律依据,比如:

Customer.objects.filter(name__contains="abc")

除了contains,还有in、gt、lt、startswith、date、range等等操作符,能实现的WHERE条件觉得够全的了。

不过,这又是一三个小很重别扭的地方,即通过命名最好的土法律法律依据来控制查询行为。我看过有的ORM是用lambda的形式来表达WHERE条件,还有的会做一三个小之类于contains()的最好的土法律法律依据,有的是比Django ORM的最好的土法律法律依据好看。不可能 是跨表查询,Django的最好的土法律法律依据就更丑了:

Customer.objects.filter(company__name__contains="xxx")

无限的双下划线啊……

聚合

Django实现聚合的最好的土法律法律依据青春恋爱物语是噩梦。貌似ORM对表达GROUP BY很无力,源代码里的注释就认输了:

聚合的aggregate()和annotate()最好的土法律法律依据还都可以 实现基本的功能,但稍微僵化 或多或少,代码就变得魔幻了:

看过一大串values()、annotate()变来变去,有那末觉得头晕?觉得你这个 状况下,还都可以 直接上原始的SQL查询的话了,没必要再我本人折腾我本人。

F表达式和Q表达式

F表达式指代了一列,对于update操作时引用列的值有用。Q表达式代表了WHERE的一三个小条件,还都可以 用于多个WHERE条件的连接。哪几种有的是Django ORM用来弥补存在问题的。就拿Q表达式来说。查询最好的土法律法律依据中跟多个参数的话,合适 多个WHERE条件。哪几种条件会默认为AND关系。为了表达OR和NOT关系,Django ORM就造了个Q表达式,比如:

filter(Q(name__contains="abc")|Q(name__startswith("xxx")))

为了弥补存在问题,Django ORM又增加了某种语法风格。于是,学习路上又多了一三个小坑……

总结

总的来说,Django ORM在实现基础的数据库操作方面没大间题。但不可能 不到构建僵化 的SQL的话,与其在Django ORM里绕来绕去,还不如直接用原始的SQL的话。你这个 是我最强烈的一三个小感受。当然,Django ORM还是可用的工具。我写这篇文章的目的,是提醒大伙儿儿并非误把糟糕的设计当做精巧的语法。