暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

接口测试与开发实战(六)_Django ORM查询操作

197

查找是数据库操作中一个非常重要的技术。查询一般就是使用filter
exclude
以及get
三个方法来实现。我们可以在调用这些方法的时候传递不同的参数来实现查询需求。在ORM
层面,这些查询条件都是使用field
+__
+condition
的方式来使用的。以下将那些常用的查询条件来一一解释。


查询条件


exact:


使用精确的=
进行查找。如果提供的是一个None
,那么在SQL
层面就是被解释为NULL
。示例代码如下:

article = Article.objects.get(id__exact=14)
article = Article.objects.get(id__exact=None)

复制


以上的两个查找在翻译为SQL
语句为如下:


select ... from article where id=14;
select ... from article where id IS NULL;

复制


iexact:


使用like
进行查找。示例代码如下:


article = Article.objects.filter(title__iexact='Python')

复制



那么以上的查询就等价于以下的SQL
语句:

select ... from article where title like 'Python';
复制




注意上面这个sql
语句,因为在MySQL
中,没有一个叫做ilike
的。所以exact
iexact
的区别实际上就是LIKE
=
的区别,在大部分collation=utf8_general_ci
情况下都是一样的(collation
是用来对字符串比较的)。


contains:


大小写敏感,判断某个字段是否包含了某个数据。示例代码如下:

articles = Article.objects.filter(title__contains='小白')

复制



在翻译成SQL
语句为如下:

select ... where title like binary '%小白%';

复制



要注意的是,在使用contains
的时候,翻译成的sql
语句左右两边是有百分号的,意味着使用的是模糊查询。而exact
翻译成sql
语句左右两边是没有百分号的,意味着使用的是精确的查询。


icontains:


大小写不敏感的匹配查询。示例代码如下:

articles = Article.objects.filter(title__icontains='PYTHOn')

复制



在翻译成SQL
语句为如下:

select ... where title like '%PYTHOn%';

复制



in:


提取那些给定的field
的值是否在给定的容器中。容器可以为list
tuple
或者任何一个可以迭代的对象,包括QuerySet
对象。示例代码如下:

articles = Article.objects.filter(id__in=[1,2,3])

复制



以上代码在翻译成SQL
语句为如下:


select ... where id in (1,3,4)

复制


当然也可以传递一个QuerySet
对象进去。示例代码如下:

inner_qs = Article.objects.filter(title__contains='web开发')
categories = Category.objects.filter(article__in=inner_qs)

复制


以上代码的意思是获取那些文章标题包含web开发的所有分类。
将翻译成以下SQL
语句,示例代码如下:


select ...from category where article.id in (select id from article where title like '%web开发%');
复制

gt:


某个field
的值要大于给定的值。示例代码如下:

articles = Article.objects.filter(id__gt=4)

复制


以上代码的意思是将所有id
大于4的文章全部都找出来。
将翻译成以下SQL
语句:


select ... where id > 4;

复制


gte:


类似于gt
,是大于等于。


lt:


类似于gt
是小于。


lte:


类似于lt
,是小于等于。


startswith:


判断某个字段的值是否是以某个值开始的。大小写敏感。示例代码如下:

articles = Article.objects.filter(title__startswith='Python')

复制



以上代码的意思是提取所有标题以Python字符串开头的文章。
将翻译成以下SQL
语句:


select ... where title like 'Python%'

复制


istartswith:


类似于startswith
,但是大小写是不敏感的。


endswith:


判断某个字段的值是否以某个值结束。大小写敏感。示例代码如下:

articles = Article.objects.filter(title__endswith='python')

复制



以上代码的意思是提取所有标题以python结尾的文章。
将翻译成以下SQL
语句:


select ... where title like '%python';

复制


iendswith:


类似于endswith
,只不过大小写不敏感。


range:


判断某个field
的值是否在给定的区间中。示例代码如下:



from django.utils.timezone import make_aware
from datetime import datetime
start_date = make_aware(datetime(year=2021,month=1,day=1))
end_date = make_aware(datetime(year=2021,month=3,day=29,hour=16))
articles = Article.objects.filter(pub_date__range=(start_date,end_date))

复制




以上代码的意思是提取所有发布时间在2021/1/1
2021/12/12
之间的文章。
将翻译成以下的SQL
语句:


select ... from article where pub_time between '2021-01-01' and '2021-12-12'

复制


需要注意的是,以上提取数据,不会包含最后一个值。也就是不会包含2018/12/12
的文章。
而且另外一个重点,因为我们在settings.py
中指定了USE_TZ=True
,并且设置了TIME_ZONE='Asia/Shanghai'
,因此我们在提取数据的时候要使用django.utils.timezone.make_aware
先将datetime.datetime
navie
时间转换为aware
时间。make_aware
会将指定的时间转换为TIME_ZONE
中指定的时区的时间。


date:


针对某些date
或者datetime
类型的字段。可以指定date
的范围。并且这个时间过滤,还可以使用链式调用。示例代码如下:


articles = Article.objects.filter(pub_date__date=date(2021,3,29))

复制



以上代码的意思是查找时间为2021/3/29
这一天发表的所有文章。
将翻译成以下的sql
语句:


select ... WHERE DATE(CONVERT_TZ(`front_article`.`pub_date`'UTC''Asia/Shanghai')) = 2021-03-29

复制


注意,因为默认情况下MySQL
的表中是没有存储时区相关的信息的。因此我们需要下载一些时区表的文件,然后添加到Mysql
的配置路径中。如果你用的是windows
操作系统。那么在http://dev.mysql.com/downloads/timezones.html
下载timezone_2018d_posix.zip - POSIX standard
。然后将下载下来的所有文件拷贝到C:\ProgramData\MySQL\MySQL Server 5.7\Data\mysql
中,如果提示文件名重复,那么选择覆盖即可。
如果用的是linux
或者mac
系统,那么在命令行中执行以下命令:mysql_tzinfo_to_sql usr/share/zoneinfo | mysql -D mysql -u root -p
,然后输入密码,从系统中加载时区文件更新到mysql
中。


year:


根据年份进行查找。示例代码如下:


articles = Article.objects.filter(pub_date__year=2021)
articles = Article.objects.filter(pub_date__year__gte=2020)

复制



以上的代码在翻译成SQL
语句为如下:


select ... where pub_date between '2021-01-01' and '2021-12-31';
select ... where pub_date >= '2020-01-01';

复制


month:


year
,根据月份进行查找。


day:


year
,根据日期进行查找。


week_day:


Django 1.11
新增的查找方式。同year
,根据星期几进行查找。1表示星期天,7表示星期六,2-6
代表的是星期一到星期五。


time:


根据时间进行查找。示例代码如下:


articles = Article.objects.filter(pub_date__time=datetime.time(12,12,12));

复制



以上的代码是获取每一天中12点12分12秒发表的所有文章。
更多的关于时间的过滤,请参考Django
官方文档:https://docs.djangoproject.com/en/2.0/ref/models/querysets/#range


isnull:


根据值是否为空进行查找。示例代码如下:

articles = Article.objects.filter(pub_date__isnull=False)

复制



以上的代码的意思是获取所有发布日期不为空的文章。
将来翻译成SQL
语句如下:


select ... where pub_date is not null;

复制


regex和iregex:


大小写敏感和大小写不敏感的正则表达式。示例代码如下:

articles = Article.objects.filter(title__regex=r'^Python')
复制


以上代码的意思是提取所有标题以hello
字符串开头的文章。
将翻译成以下的SQL
语句:


select ... where title regexp binary '^Python';

复制


iregex
是大小写不敏感的。


根据关联的表进行查询:


假如现在有两个ORM
模型,一个是Article
,一个是Category
。代码如下:

class Category(models.Model):
    """文章分类表"""
    name = models.CharField(max_length=100)

class Article(models.Model):
    """文章表"""
    title = models.CharField(max_length=100,null=True)
    category = models.ForeignKey("Category",on_delete=models.CASCADE)

复制



比如想要获取文章标题中包含"测试"的所有的分类。那么可以通过以下代码来实现:


categories = Category.object.filter(article__title__contains("测试"))

复制


ORM模型迁移


迁移命令:


  1. makemigrations:将模型生成迁移脚本。模型所在的app
    ,必须放在settings.py
    中的INSTALLED_APPS
    中。这个命令有以下几个常用选项:

  • app_label:后面可以跟一个或者多个app
    ,那么就只会针对这几个app生成迁移脚本。如果没有任何的app_label,那么会检查INSTALLED_APPS
    中所有的app下的模型,针对每一个app都生成响应的迁移脚本。

  • --name:给这个迁移脚本指定一个名字。

  • --empty:生成一个空的迁移脚本。如果你想写自己的迁移脚本,可以使用这个命令来实现一个空的文件,然后自己再在文件中写迁移脚本。


  1. migrate:将新生成的迁移脚本。映射到数据库中。创建新的表或者修改表的结构。以下一些常用的选项:

  • app_label:将某个app
    下的迁移脚本映射到数据库中。如果没有指定,那么会将所有在INSTALLED_APPS
    中的app
    下的模型都映射到数据库中。

  • app_label migrationname:将某个app
    下指定名字的migration
    文件映射到数据库中。

  • --fake:可以将指定的迁移脚本名字添加到数据库中。但是并不会把迁移脚本转换为SQL语句,修改数据库中的表。

  • --fake-initial:将第一次生成的迁移文件版本号记录在数据库中。但并不会真正的执行迁移脚本。


  1. showmigrations:查看某个app下的迁移文件。如果后面没有app,那么将查看INSTALLED_APPS
    中所有的迁移文件。

  2. sqlmigrate:查看某个迁移文件在映射到数据库中的时候,转换的SQL
    语句。


migrations中的迁移版本和数据库中的迁移版本对不上怎么办?


  1. 找到哪里不一致,然后使用python manage.py --fake [版本名字]
    ,将这个版本标记为已经映射。

  2. 删除指定app
    migrations
    和数据库表django_migrations
    中和这个app
    相关的版本号,然后将模型中的字段和数据库中的字段保持一致,再使用命令python manage.py makemigrations
    重新生成一个初始化的迁移脚本,之后再使用命令python manage.py makemigrations --fake-initial
    来将这个初始化的迁移脚本标记为已经映射。以后再修改就没有问题了。


更多关于迁移脚本的。请查看官方文档:https://docs.djangoproject.com/en/2.0/topics/migrations/


对于ORM相关内容咱们就讲到这吧?ORM其实还有很多内容需要学习的,如果个人感兴趣可以自行去了解!



拒绝白嫖,不给钱就点赞分享、关注、在看吧!!!关注公众号更多精彩教学分享尽在公众号中!!!

文章转载自测试前沿布道者,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论