百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

「Django框架」-模型(3)-查询操作(django框架数据库)

toyiye 2024-04-04 11:41 21 浏览 0 评论

更多知识关注公众号:Python野路子

要检索数据库中的对象,就要为model类构造一个查询集QuerySet,一个QuerySet就代码数据库中的一组数据,它可以有一个或很多个,也可以通过filter根据给定的参数对数据集进行筛选。在SQL术语中,QuerySet相当于SELECT语句,filter相当于wherelimit这样的限定从句。

查询对象

all()查询所有结果,返回QuerySet

article_list = Article.objects.all()
article_list
<QuerySet [<Article: python数据类型>, <Article: Python快速入门>, <Article: MySQL快速入门>, <Article: MySQL快速入门>, <Article: 中间件通讯>, <Article: 最近,火遍朋友圈的地摊经济>, <Article: create>]>

我们可以使用for循环遍历一个个文章对象:

for article in article_list:
    print(article, type(article))
    
python数据类型  <class 'article.models.Article'>
Python快速入门  <class 'article.models.Article'>
MySQL快速入门  <class 'article.models.Article'>
MySQL快速入门  <class 'article.models.Article'>
中间件通讯  <class 'article.models.Article'>
最近,火遍朋友圈的地摊经济  <class 'article.models.Article'>
create  <class 'article.models.Article'>

上面打印出标题,是因为我们在model中通过__str__方法返回标题:

def __str__(self):
    return self.title

get(**kwargs)查询单个数据,只会返回一个实例对象,如果所有条件都不满足或者是满足条件的有多个,将抛出DoesNotExist异常,所以一般情况下,我们会这么用:

try:
    article = Article.objects.get(pk=1) # 在django 的ORM查询中,数据库的主键可以用PK代替, 官方推荐使用pk
    
    article = Article.objects.get(id=1)  # 等同于select * from hello_article where id=1;
    
except Article.DoesNotExist:
    print('异常处理')

filter(**kwargs)返回满足筛选条件的QuerySet

Article.objects.filter(status = 0) # select * from article where status=0

exclude(**kwargs)排除符合条件的数据,返回一个QuerySet

Article.objects.exclude(status = 0)  # select * from article where status<>0

*values(field)返回一个ValueQuerySet,一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列。

articles = Article.objects.all()  # 获取所有Article对象
articles
<QuerySet [<Article: python数据类型>, <Article: Python快速入门>, <Article: MySQL快速入门>, <Article: MySQL快速入门>, <Article: 中间件通讯>, <Article: 最近,火遍朋友圈的地摊经济>, <Article: create>]>

articles_value = Article.objects.values('title', 'tags')
articles_value
<QuerySet [{'title': 'python数据类型', 'tags': None}, {'title': 'Python快速入门', 'tags': None}, {'title': 'MySQL快速入门', 'tags': None}, {'title': 'MySQL快速入门', 'tags': 4}, {'title': '中间件通讯', 'tags': 1}, {'title': '中间件通讯', 'tags': 2}, {'title': '最近,火遍朋友圈的地摊经济', 'tags': None}, {'title': 'create', 'tags': None}]>

同样我们可以使用for循环进行遍历:

for article_dict in articles_value:
    print(article_dict)
    
{'title': 'python数据类型', 'tags': None}
{'title': 'Python快速入门', 'tags': None}
{'title': 'MySQL快速入门', 'tags': None}
{'title': 'MySQL快速入门', 'tags': 4}
{'title': '中间件通讯', 'tags': 1}
{'title': '中间件通讯', 'tags': 2}
{'title': '最近,火遍朋友圈的地摊经济', 'tags': None}
{'title': 'create', 'tags': None}

从上面可以看出遍历出来的是字典。

*values_list(field)它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列。

articles_values_list = Article.objects.values_list('title', 'tags')

# 输出结果:
<QuerySet [('python数据类型', None), ('Python快速入门', None), ('MySQL快速入门', None), ('MySQL快速入门', 4), ('中间件通讯', 1), ('中间件通讯', 2), ('最近,火遍朋友圈的地摊经济', None), ('create', None)]>

遍历获取的是元组:

for article_tuple in articles_values_list:
    print(article_tuple)
    
('python数据类型', None)
('Python快速入门', None)
('MySQL快速入门', None)
('MySQL快速入门', 4)
('中间件通讯', 1)
('中间件通讯', 2)
('最近,火遍朋友圈的地摊经济', None)
('create', None)

*order_by(args)根据给定的参数进行排序。

# 正序
article_list = Article.objects.order_by('id')

# 输出结果:
<QuerySet [<Article: python数据类型>, <Article: Python快速入门>, <Article: MySQL快速入门>, <Article: MySQL快速入门>, <Article: 中间件通讯>, <Article: 最近,火遍朋友圈的地摊经济>, <Article: create>]>

# 倒序,字段前面加-
article_list = Article.objects.order_by('-id')

# 输出结果:
# <QuerySet [<Article: create>, <Article: 最近,火遍朋友圈的地摊经济>, <Article: 中间件通讯>, <Article: MySQL快速入门>, <Article: MySQL快速入门>, <Article: Python快速入门>, <Article: python数据类型>]>


# 可以根据多个
# 首先根据阅读量进行排序,如果阅读量相同,则根据点赞量进行排序
article_list = Article.objects.order_by('read_num', 'like_num')

一定要注意的一点是,多个order_by,会把前面排序的规则给打乱,而使用最后面的排序方式,例如:

article_list = Article.objects.order_by('read_num').order_by('like_num')

它会根据点赞数排序,而不是两者,因为前面一个排序得到一个queryset,然后又来排序了。

distinct()

给查询结果去重,一般都是在valuesvalues_list方法后面,因为他们两个可以或取出指定字段数据,然后再去重。

这里需要注意的是,当模型类中指定了默认排序字段,那么当我们使用distinct方法进行去重时,默认会按照我们指定的排序字典进行去重,会导致去重结果不是我们想要的,所以要么我们在模型类中不指定排序字段,如果需要指定排序,则在查询集中,在distinct方法前面加上order_by方法,并且order_by方法中的字段就是我们要去重的字段数据。

count()将返回当前查询到的数据的总数。

article_count = Article.objects.count()  # 7, 相当于select count(*) from tb_article

first()获取查询到的数据的第一条数据,如果使用用了order_by排序,那么将获取排序后的第一条,如果没有用order_by,那么将按主键进行默认排序。

article = Article.objects.first()   # <Article: python数据类型>

last()first方法一样,只不过是获取的是最后一条的数据。

article = Article.objects.last()   # <Article: create>

latest(field_name=None)根据提供的参数field_name来进行排序,然后提取离现在最近的一条数据。

latest_article = Article.objects.latest('id')  # <Article: create>

field_name通常是DateFieldDateTimeFieldIntegerField一起使用。应该避免和其他字段一起使用, 因为语义上是错误的。这两种方法主要是提供代码的方便性和可读性, 如果和非时间字段一起使用,会带来新的混淆。

还可以在模型的Meta类中先定义get_latest_by属性:

class Article(models.Model):
    ...
    public_date = models.DateTimeField(blank=True, null=True)

    class Meta:
        db_table = 'tb_article'
        get_latest_by = 'public_date'  # 用来排序的字段

然后直接使用:

latest_article = Article.objects.latest()

earliest(field_name=None)用法和latest一样,只是这个是获取最久远的一个。

exists()返回 True或者 False ,在数据库层面执行select (1) as a from table_name limit 1的查询。判断QuerySet是否有数据,用这个接口是最合适的,不要用count或者len(queryset )这样的操作来判断是否存在 。 相反, 如果可以预期接下来会用到 Query 的方式来做判断 ,这样可以减少一次 查询请求。

Article.objects.exists() #  True

update(**kwargs)更新数据方法,这个方法可以对查询出来的QuerySet里面的所有元素进行更新,并且更新参数的个数也是不限的。另外要注意的是,因为get方法返回的不是QuerySet对象,因此使用get方法提取出来的数据不能使用update方法。出于这种情况,建议应该使用filter(pk=xx)来替代get(pk=xxx)方法。并且,使用get出来的模型,修改数据后再save,会更新所有的数据,比update的效率更低。

Article.objects.filter(id=2).update(title="文章标题")

**delete():**删除QuerySet中的模型。

查询条件

我们可以在调用这些方法的时候传递不同的参数来实现查询需求。相当于是SQL语句中的where语句后面的条件,在ORM层面,这些查询条件都是使用field__condition方式使用。

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

article = Article.objects.get(id=2)  # <Article: python数据类型>
article = Article.objects.get(id__exact=2)   # <Article: python数据类型>

article_list = Article.objects.filter(id=2)  # <QuerySet [<Article: python数据类型>]>
article_list = Article.objects.filter(id__exact=2) # <QuerySet [<Article: python数据类型>]>

**iexact:**同exact,只是忽略大小写。

contains判断某个字段是否包含了某个数据。

articles = Article.objects.filter(title__contains='快速')
# <QuerySet [<Article: Python快速入门>, <Article: MySQL快速入门>, <Article: MySQL快速入门>]>

# 相当于select title from tb_article where title like '%快速%';

# 我们可以使用查看执行的SQL语句:查询结果集.query

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

**icontains:**同contains,只是忽略大小写。

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

articles = Article.objects.filter(id__in=[2,3,4,5]) 
# <QuerySet [<Article: python数据类型>, <Article: Python快速入门>]>


# 相当于select title from tb_article where id in(2,3,4,5)

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

articles = Article.objects.filter(id__gt=4)  # 将所有id大于4的文章全部都找出来。

# select ... where id > 4;

**gte:**类似于gt,是大于等于。

**lt:**小于。

**lte:**小于等于。

startswith字段的值以某个值开始,大小写敏感。

articles = Article.objects.filter(title__startswith = 'py')
# <QuerySet [<Article: python数据类型>]>

# 相当于select ... where title like 'py%'

**istartswith:**同startswith,但忽略大小写。

endswith以某个字符串结尾。

articles = Article.objects.filter(title__endswith = '入门')
# <QuerySet [<Article: Python快速入门>, <Article: MySQL快速入门>, <Article: MySQL快速入门>]>

# 相当于select ... where title like '%入门'

**iendswith:**同startswith,但忽略大小写。

range范围查询,多用于时间范围。

from article.models import Category, Article, Tag

from datetime import datetime

start_date = datetime(2020, 7, 4, 10)
end_date = datetime(2020, 7, 4, 11)
articles = Article.objects.filter(create_time__range=(start_date, end_date))

# <QuerySet [<Article: python数据类型>, <Article: Python快速入门>, <Article: MySQL快速入门>, <Article: MySQL快速入门>, <Article: 中间件通讯>, <Article: 最近,火遍朋友圈的地摊经济>, <Article: create>]>


start_date = datetime(2020, 7, 4, 2)
end_date = datetime(2020, 7, 4, 3)
articles = Article.objects.filter(update_time__range=(start_date, end_date))

# <QuerySet [<Article: python数据类型>, <Article: Python快速入门>, <Article: MySQL快速入门>, <Article: MySQL快速入门>, <Article: 中间件通讯>, <Article: 最近,火遍朋友圈的地摊经济>, <Article: create>]>


# print(create_time)  # 2020-07-04 10:35:04.265011
# print(update_time)  # 2020-07-04 02:25:53.175317

以上代码的意思是提取所有发布时间在start_dateend_date之间的文章。

需要注意的是,以上提取数据,不会包含最后一个值。也就是不会包含end_date的文章。

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

from article.models import Category, Article, Tag
from datetime import date

articles = Article.objects.filter(create_time__date=date(2020,7,4))

# 相当于 select * from  tb_article where date(create_time) = 2020 - 07 - 04

year根据年份进行查找,代码如下:

from article.models import Category, Article, Tag
from datetime import datetime

articles = Article.objects.filter(create_time__year=2020)
# <QuerySet [<Article: python数据类型>, <Article: Python快速入门>, <Article: MySQL快速入门>, <Article: MySQL快速入门>, <Article: 中间件通讯>, <Article: 最近,火遍朋友圈的地摊经济>, <Article: create>]>

# 相当于select * from tb_article where create_time between 2020-01-01 00:00:00 and 2020-12-31 23:59:59.999999


articles = Article.objects.filter(create_time__year__gte=2020)
# select * from tb_article where  create_time >= 2020-01-01 00:00:00

关于日期类的查询还有很多 , 比如 monthday 等,具体等需要时查文档 即可 。

isnull判断是否为空。

articles = Article.objects.filter(create_time__isnull=True)
# 相当于select * from tb_article where create_time is null;

**切片:**可以用python的数组切片语法来限制你的QuerySet以得到一部分结果。它等价于SQL中的LIMIT和OFFSET。

articles = Article.objects.all()[:2]  # 返回前2个对象。
# <QuerySet [<Article: python数据类型>, <Article: Python快速入门>]>

Django 不支持对查询集做负数索引。

切片可以用来实现翻页显示内容,比如每一页显示10条内容可以利用切片,第page页,如下:

articles = Article.objects.all()  # 获取Article的QuerySet集
counts = articles.count()    # 总记录数
per_page = 4   # 每页显示多少条记录

for page in range(counts/per_page + counts%per_page):
    for article in articles[page*per_page: per_page(page+1)]:
        print(article.title)  

F和Q查询

F查询

之前的查询都是对象的属性与常量值比较,2个属性怎么比较呢?

Django中提供F来做这样的比较。F的实例可以在查询中引用字段,来比较同一个model 实例中两个不同字段的值。

# F语法形式
filter(字段名__运算符=F('字段名'))

例如,要查询阅读量大于等于点赞数的文章。可以这样实现:

articles = Article.objects.all() 
for article in articles:
    if article.read_num >= article.like_num:
        print(article)

如果使用F表达式,那么一行代码就可以搞定。示例代码如下:

from django.db.models import F

# 要查询阅读量大于等于点赞数的文章
articles = Article.objects.filter(read_num__gte=F('like_num')) 

# 要查询阅读量大于等于2倍点赞数的文章
articles = Article.objects.filter(read_num__gte=F('like_num')*2) 

F对象还可以对自身属性进行运算。例如,将公司全体员工薪水都增加500元,如果按照一般流程,应该是先从数据库中提取所有的员工工资到内存中,然后进行增加500,最后保存数据库中。

employees = Employee.objects.all()
for employee in employees:
    employee.salary += 1000
    employee.save()

这个需要先将数据从数据库中提取出来,再进行计算,最后再保存到数据库。

而使用F对象,可以来优化ORM操作数据库的,F对象并不会马上从数据库中获取数据,而是在生成SQL语句的时候,动态的获取传给F表达式的值。

from djang.db.models import F
Employee.object.update(salary=F('salary')+1000)

Q查询

现在,我们要查询阅读量大于20,并且点赞大于10的文章。

# 使用链式调用,2个filter
articles = Article.objects.filter(read_num__gte=20).filter(like_num__gte=10) 

# 使用一个filter
articles = Article.objects.filter(read_num__gte=20, like_num__gte=10) 

以上是一个并集查询,可以简单的通过传递多个条件进去来实现。

但是,如果想要实现一些复杂的查询语句,比如要查询阅读量大于20,或者是点赞大于10的文章。那就没有办法通过传递多个条件进去实现了。这时候就需要使用Q表达式来实现了。

# Q语法形式:filter(Q(字段名__运算符=值))

from django.db.models import Q

articles = Article.objects.filter(Q(read_num__gte=20) | Q(like_num__gte=10))

以上是进行【或】运算,当然还可以进行其他的运算,比如有&~(非)等。

'''
或     Q()|Q()
并且   Q()&Q() 
非    ~Q()
'''

from django.db.models import Q

# 查询阅读量大于20,并且点赞大于10的文章
articles = Article.objects.filter(Q(read_num__gte=20) & Q(like_num__gte=10))

# 获取id不等于3的文章
articles = Article.objects.exclude(id=3)
# 或
articles = Article.objects.filter(~Q(id=3))

聚合查询aggregate

SQL中,我们可以使用聚合函数来提取数据。比如提取某个商品销售的数量,那么可以使用Count,如果想要知道商品销售的平均价格,那么可以使用Avg

ORM中聚合函数是通过aggregate方法来实现的,返回的是一个字典。

'''
Avg, Max, Min, Count, Sum
语法形式:aggregate(Xxx('字段'))
'''

from django.db.models import Avg, Max, Min, Count, Sum

# Avg: 求平均值。 求文章平均阅读量
read_avg = Article.objects.aggregate(Avg('read_num'))
# {'read_num__avg': 20.0}

# 其中read_num__avg的结构是按照【字段名__聚合函数小写】构成的,如果想要修改默认的名字,那么可以将Avg赋值给一个关键字参数。
read_avg = Article.objects.aggregate(read_avg=Avg('read_num'))    # {'read_avg': 20.0}

# Count: 统计格数。 统计总共有多少篇文章
article_num = Article.objects.aggregate(article_num=Count('id'))   # {'article_num': 7}
# 如果需要去重,使用distinct=True,例如,获取用户表中所有的不重复的密码总共有多少个
pwd_num = Account.objects.aggregate(pwd_num=Count("password", distinct=True))


# 其他 Max, Min, Sum类似


# 多个聚合
result = Article.objects.aggregate(Count('id'), Sum('read_num'), Max('read_num'), Min('read_num')) 
# {'id__count': 7, 'read_num__sum': 140, 'read_num__max': 20, 'read_num__min': 20}

分组查询annotate

我们有时候查看一些博客,侧边栏有分类列表,显示博客已有的全部文章分类。

现在想在分类名后显示该分类下有多少篇文章,即统计每个分类下有多少篇文章,该怎么做呢?

这个时候,我们就可以用到annotateannotateQuerySet中的每个对象添加一个独立的汇总值。先按类名进行分组,然后再统计每个组分别为多少数量即可。

from django.db.models import Avg, Max, Min, Count, Sum

# 统计每个分类下有多少篇文章。
# 这里先对Category进行分类,使用annotate分组,再使用Count统计每个分组下的数量,同时给每一个对象增加这个数量。

# 这相当于给Category动态增加了属性articles__count,而这个属性的值来源于Count("articles")
category_list=Category.objects.annotate(Count("articles")) # 类似反向查询,使用related_name定义的名称来查
# <QuerySet [<Category: Python基础>, <Category: 数据库知识>]>
'''
相当于SQL
select  tb_category.id,tb_category.name,count(tb_article.id) as articles__count
from tb_category left join tb_article on tb_category.id=tb_article.category_id
group by tb_category.id
'''
for category in category_list:
    # annotate为QuerySet中每一个对象都增加了一个独立的articles__count值。
    print(category.name, category.articles__count) 
    
# Python基础 2
# 数据库知识 1


# 统计每个分类阅读最多的文章
# 方式一:
category_list=Category.objects.annotate(article_read_max = Max("articles__read_num"))
# <QuerySet [<Category: Python基础>, <Category: 数据库知识>]>
'''
相当于SQL
select tb_category.id,tb_category.name,MAX(tb_article.read_num) as article_read_max
from tb_category left join tb_article on (tb_category.id = tb_article.category_id)
group by tb_category.id
'''

for category in category_list:    
    print(category.name, category.article_read_max)
# Python基础 22
# 数据库知识 25

# 方式2:
# values 就等同于group by,返回的是一个字典,values_list 就等同于group by,, 返回的是一个元祖
# 正向查询,外键属性__字段
Article.objects.values('category__name').annotate(article_read_max = Max("read_num"))
# <QuerySet [{'category__name': 'Python基础', 'article_read_max': 22}, {'category__name': '数据库知识', 'article_read_max': 25}, {'category__name': None, 'article_read_max': 33}]>

'''
相当于SQL
select tb_category.name, max(tb_article.read_num) as article_read_max
from tb_article left join tb_category on tb_article.category_id=tb_category.id
group by tb_category.name
'''

# 给每个文章对象实例,添加一个category__name属性,用来显示对应分类的名称,这里使用F取对应的分类名称。
articles = Article.objects.annotate(category_name=F("category__name"))
print(articles.query) # 输出对应的SQL语句
'''
select
 tb_article.id,
 tb_article.title,
 tb_article.content,
 tb_article.category_id,
 tb_article.create_time,
 tb_article.update_time,
 tb_article.read_num,
 tb_article.like_num,
 tb_category.name as category_name
from
 tb_article
left join tb_category ON (tb_article.category_id = tb_category.id)
'''

aggregate和annotate的区别:

  1. aggregate:返回使用聚合函数后的字段和值,返回的是一个字典,执行后就是最终结果。
  2. annotate:返回的是一个QuerySet,可以继续进行查询。annotate的聚合结果是针对每行数据的,而不是整个查询结果。在原来模型字段的基础之上添加一个使用了聚合函数的字段,并且在使用聚合函数的时候,会使用当前这个模型的主键进行分组group by

Djangoaggregateannotate方法属于高级查询方法,主要用于组合查询,可以大大提升数据库查询效率。当你需要对查询集(queryset)的某些字段进行聚合操作时(比如Sum, Avg, Max),请使用aggregate方法。如果你想要对数据集先进行分组(Group By)然后再进行某些聚合操作或排序时,请使用annotate方法。

value与annotate

valueannotate的顺序不同时,查询结果大相径庭。

1)valueannotate前面时,相当于group by

ret=Student.objects.values('gender').annotate(count=Count('sid')).order_by('-count')
print(ret)

等价于以下sql语句:

select gender, COUNT(sid) AS count 
from student 
group by gender 
order by count DESC

执行结果:

<QuerySet [{'gender': '女', 'count': 6}, {'gender': '男', 'count': 5}]>

可以看到结果是按性别分组的。

2)value放在annotate后面时,相当于select

ret = Student.objects.annotate(count=Count('sid')).values('gender').order_by('-count')
print(ret)

等价于以下sql语句:

SELECT gender 
FROM student
GROUP BY sid
ORDER BY COUNT(sid) DESC

执行结果:

<QuerySet [{'gender': '女'}, {'gender': '男'}, {'gender': '女'}, {'gender': '女'}, {'gender': '男'}, {'gender': '女'}, {'gender': '男'}, {'gender': '男'}, {'gender': '女'}, {'gender': '女'}, {'gender': '男'}]>

annotate前面没有value时,默认按当前表的主键分组。

可以看到结果并没有按性别分组,而是每个学生作为一组,说明上述结论是正确的

关联查询

关联查询有两种方式:一种是创建类对象,通过类对象查询。另外一种是通过模型类查询。

例如:

① 查询分类名字包含“Python”的所有文章信息;

② 查询文章标题中包含“python”的文章所属的分类信息;

③ 查询标签含有“快速入门”的文章;

④ 查询标签为“快速入门”的文章所属的分类信息;

我们分别使用2种方式处理。

方式一:类对象查询

① 通过 【分类】 查询 【文章】,即根据一类,查询多类的信息:

# 创建一类的对象
# 一类对象.多类类名小写_set.all()  # 或者使用related_name设置的名字

② 通过 【文章】 查询 【分类】,即根据多类,查询一类的信息:

# 创建多类的对象
# 多类对象.关联属性(外键)

方式二:模型类查询

Django提供一种强大而又直观的方式来 处理 查询中的关联关系,它能自动处理join联系。要做跨关系查询,就使用双下划线来连接模型(model)间关联字段的名称,直到想要的model为止。

① 已知条件是一类信息,查询多类信息。(正向查询):

# 多类类名.objects.filter(多类中的外键属性__一类属性名__条件)

# 例如,查询分类名字包含‘Python’的所有文章信息
articles = Article.objects.filter(category__name__icontains='python')
# <QuerySet [<Article: python数据类型>, <Article: Python快速入门>]>

正向查询按字段,比如上面Article中的category

② 已知条件为多类信息,查询一类信息。(反向查询):

# 一类类名.objects.filter(多类类名小写__多类属性名__条件)  # 若使用related_name设置了名字,则需要使用设置的名字

# 查询文章标题中包含'python'的文章所属的分类信息
categories = Category.objects.filter(articles__title__icontains='python')   
# <QuerySet [<Category: Python基础>, <Category: Python基础>]>

反向查询按子表的模型类名小写,如果设置了related_name,则使用related_name替换表名。

③ 多个表进行查询:

# 查询标签为‘快速入门’的文章所属的分类信息
categories = Category.objects.filter(articles__tags__name__icontains='快速入门')
# <QuerySet [<Category: Python基础>]>

多对多和一对多类似。

最后对模型类查询来个小总结:**

1、想查询哪个类中的信息,就以哪个类名.object.filter开头

2、多类类名开头,filter括号内 关联属性开头。一类类名开头,filter括号内 多类类名小写开头。后面都是条件判断(如上面的一类有条件判断或多类有条件判断)。

查询集QuerySet

Django的ORM中存在查询集的概念,也称查询结果集QuerySet,表示从数据库中获取的对象集合。

当调用如下过滤器方法时,Django会返回查询集(而不是简单的列表):

  • all:返回所有数据;
  • filter:返回满足条件的数据;
  • exclude:返回满足条件之外的数据;
  • order_by:对结果进行排序;
  • and so on ....

对查询集可以再次调用过滤器进行过滤,即链式调用方式,如:

articles = Article.objects.filter(read_num__gte=20).filter(like_num__gte=10)

在每个方法的执行结果上可以继续调用同样的方法,因为每个方法的返回值都是它自己,也就是 QuerySet 。

两大特性

1) QuerySet是惰性的

Django中的QuerySet本质上是一个懒加载的对象,创建查询集QuerySet的动作不涉及任何数据库操作,只是返回一个 QuerySet对象,你可以一直添加过滤器,在这个过程中,Django不会执行任何数据库查询,除非QuerySet被执行,等真正调用它时才会执行查询。

from article.models import Category, Article, Tag
from django.db import connection

article_list = Article.objects.all()  # 此时还未访问数据库操作

print(connection.queries)  # []  该方法会打印出所有执行过的sql语句

我们可以看到在打印connection.quries的时候打印的是一个空的列表。说明上面的QuerySet并没有真正的执行。

在以下情况下QuerySet会被转换为SQL语句执行:

# 1.遍历
for article in Article.objects.all(): # 第一次遍历的时候查询,后面再次遍历就不会查询了。
    print(article)
'''
# 执行相关SQL:
select tb_article.id, tb_article.title, tb_article.content, tb_article.category_id, tb_article.create_time, tb_article.update_time, tb_article.read_num, tb_article.like_num 
from tb_article
'''
for article in Article.objects.filter(title__icontains='快速'): 
    print(article)
    
for sql in connection.queries: # 第一次遍历的时候查询,后面再次遍历就不会查询了。
    print('='*30)
    print(sql) 
'''
select tb_article.id, tb_article.title, tb_article.content, tb_article.category_id, tb_article.create_time, tb_article.update_time, tb_article.read_num, tb_article.like_num 
from tb_article where tb_article.title like '%快速%'
'''
    
# 2. 使用步长做切片操作
# 3. 调用len函数用来获取QuerySet中总共有多少条数据
# 4. 调用list函数用来将一个QuerySet对象转换为list对象
# 5. 对某个QuerySet进行判断

2) 缓存机制

每个QuerySet都包含一个缓存,以减少对数据库的访问。要编写高效代码,就要理解缓存是如何工作的。

使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询时会使用缓存的数据,减少了数据库的查询次数。

场景一:如下是两个QuerySet,这2个是无法使用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载。

[article.id for article in Article.objects.all()]
print(connection.queries)
# [{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'}, {'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'}, {'sql': 'SELECT `tb_article`.`id`, `tb_article`.`title`, `tb_article`.`content`, `tb_article`.`category_id`, `tb_article`.`create_time`, `tb_article`.`update_time`, `tb_article`.`read_num`, `tb_article`.`like_num` FROM `tb_article`', 'time': '0.000'}]

[article.id for article in Article.objects.all()]
print(connection.queries)
# [{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'}, {'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'}, {'sql': 'SELECT `tb_article`.`id`, `tb_article`.`title`, `tb_article`.`content`, `tb_article`.`category_id`, `tb_article`.`create_time`, `tb_article`.`update_time`, `tb_article`.`read_num`, `tb_article`.`like_num` FROM `tb_article`', 'time': '0.000'}, {'sql': 'SELECT `tb_article`.`id`, `tb_article`.`title`, `tb_article`.`content`, `tb_article`.`category_id`, `tb_article`.`create_time`, `tb_article`.`update_time`, `tb_article`.`read_num`, `tb_article`.`like_num` FROM `tb_article`', 'time': '0.001'}]

通过上面输出所执行的SQL记录,我们可以看出第二次执行同样的语句,明显比第一次多了一条SQL语句,即第二次又进行数据库查询操作。

如何优化,减少对数据库的操作呢??

我们先来测试几个数据,看看效果:

articles = Article.objects.all()
print(connection.queries)
[]
[article.id for article in articles] # 访问数据库
# [2, 5, 6, 7, 8, 9, 10]
print(connection.queries)
#[{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'}, {'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'}, {'sql': 'SELECT `tb_article`.`id`, `tb_article`.`title`, `tb_article`.`content`, `tb_article`.`category_id`, `tb_article`.`create_time`, `tb_article`.`update_time`, `tb_article`.`read_num`, `tb_article`.`like_num` FROM `tb_article`', 'time': '0.000'}]

[article.id for article in articles]  # 使用缓存
# [2, 5, 6, 7, 8, 9, 10]
print(connection.queries)
# [{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'}, {'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'}, {'sql': 'SELECT `tb_article`.`id`, `tb_article`.`title`, `tb_article`.`content`, `tb_article`.`category_id`, `tb_article`.`create_time`, `tb_article`.`update_time`, `tb_article`.`read_num`, `tb_article`.`like_num` FROM `tb_article`', 'time': '0.000'}]

通过上面测试可知,只要简单的保存QuerySet,然后重用即可,上面第二个就使用了缓存,只要查询一次数据库即可,提高了性能。

但是,查询集并不总是缓存结果,当查询集执行部分查询时,会先检查缓存,如果它没有被填充,部分查询返回的结果不会被缓存。这意味着,使用切片查询不会填充缓存。

articles = Article.objects.all()  # 没有访问数据库
print(connection.queries) # []

# 重复的切片查询每次都会访问数据库,例如下面相当于只查询了一条记录,没有覆盖全部
articles[1] # 访问数据库
articles[2] # 再次访问数据库

# 但是,如果整个查询集已经被求值,切片查询会使用缓存
articles = Article.objects.all()
[article.id for article in articles] # 查询数据库

articles[1] # 使用缓存
articles[2] # 使用缓存


# 下面是一些会填充缓存的操作,因为会全部查询,即覆盖所有
[article.id for article in articles] # 列表推导式,会遍历queryset所有的
bool(articles)  
article in articles
list(articles)

几个提升性能的接口

在优化Django项目,提高性能时,尤其要考虑这几种接口的用法 。

**defer接口:**把不需要展示的字段做延迟加载,比如我们在获取文章列表的时候,文章的内容我们是不需要的,因此这时候我们就可以使用defer来过滤掉一些字段,但是当我们需要用到这个字段时,在使用时回去加载。这个字段跟values有点类似,只不过defer返回的不是字典,而是模型。

from article.models import Category, Article, Tag
from django.db import connection

articles = Article.objects.all().defer('content')  # 没有访问数据库
print(connection.queries) # []

for article in articles:  # 这里遍历的时候会执行一次数据库查询
    # 因为在上面提取的时候过滤了content
    # 这个地方重新获取content,会执行数据库查询,for遍历多少次,即执行多少次数据库查询,加上上面一次,即要查询N+1次
    print(article.content)
    
for sql in connection.queries:
    print('='*30)
    print(sql)
    

# 输出结果:
'''
[]
本篇将针对Python做一个简单入门,帮助小白迅速了解Python。
本篇将针对Mysql做一个简单入门,帮助小白迅速了解MySQL。
本篇将针对Mysql做一个简单入门,帮助小白迅速了解MySQL。
开始学习通讯领域,我们从CTI开始吧
相信,最近朋友圈都在讨论各种有关摆地摊的话题,你是否有种冲动也去试下呢?
添加不存在的数据,将数据直接存入数据库,创建一个新的对象,将它保存并放在新创建的对象。(一对一,多对多)
==============================
{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'}
==============================
{'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'}
============================== # 下面一条除了content字段,其他字段值都查出来,因为前面过滤此字段
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`title`, `tb_article`.`category_id`, `tb_article`.`create_time`, `tb_article`.`update_time`, `tb_article`.`read_num`, `tb_article`.`like_num` FROM `tb_article`', 'time': '0.000'}  
============================== # 后面查询content字段和id字段
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`content` FROM `tb_article` WHERE `tb_article`.`id` = 2', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`content` FROM `tb_article` WHERE `tb_article`.`id` = 5', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`content` FROM `tb_article` WHERE `tb_article`.`id` = 6', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`content` FROM `tb_article` WHERE `tb_article`.`id` = 7', 'time': '0.000'}
==============================   

'''  

上面代码会产生N+1的查询问题,在实际使用时千万要注意!

defer虽然能过滤字段,但是有些字段是不能过滤的,比如id,即使你过滤了,也会提取出来。

**only接口:**与defer刚好相反,only提取指定的字段。如果只想获取文章标题title的内容。

from article.models import Category, Article, Tag
from django.db import connection


articles = Article.objects.all().only('title')  # 没有访问数据库
print(connection.queries) # []

for article in articles:  # 这里遍历的时候会执行一次数据库查询,只查询title字段值
    # 因为在上面提取的时候过滤了title
    # 这个地方重新获取title,会执行数据库查询,for遍历多少次,即执行多少次数据库查询,加上上面一次,即要查询N+1次
    print(article.content)
    
for sql in connection.queries:
    print('='*30)
    print(sql)


#
'''
[]
本篇将针对Python做一个简单入门,帮助小白迅速了解Python。
本篇将针对Mysql做一个简单入门,帮助小白迅速了解MySQL。
本篇将针对Mysql做一个简单入门,帮助小白迅速了解MySQL。
开始学习通讯领域,我们从CTI开始吧
相信,最近朋友圈都在讨论各种有关摆地摊的话题,你是否有种冲动也去试下呢?
添加不存在的数据,将数据直接存入数据库,创建一个新的对象,将它保存并放在新创建的对象。(一对一,多对多)
==============================
{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'}
==============================
{'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`title` FROM `tb_article`', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`content` FROM `tb_article` WHERE `tb_article`.`id` = 2', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`content` FROM `tb_article` WHERE `tb_article`.`id` = 5', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`content` FROM `tb_article` WHERE `tb_article`.`id` = 6', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`content` FROM `tb_article` WHERE `tb_article`.`id` = 7', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`content` FROM `tb_article` WHERE `tb_article`.`id` = 8', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`content` FROM `tb_article` WHERE `tb_article`.`id` = 9', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`content` FROM `tb_article` WHERE `tb_article`.`id` = 10', 'time': '0.000'}

'''

**select_related:**在提取某个模型的数据的同时,也提前将相关联的数据提取出来。比如提取文章数据,可以使用select_relatedcategory信息提取出来,以后再次使用article.category的时候就不需要再次去访问数据库了。可以减少数据库查询的次数。示例代码如下:

from article.models import Category, Article, Tag
from django.db import connection


articles = Article.objects.all() # 没有访问数据库
print(connection.queries) # []

for article in articles:  # 查询数据库
    print(article.category)  # 再次查询数据库
    
'''
Python基础
Python基础
None
None
None
数据库知识
None

'''   

for sql in connection.queries:
    print('='*30)
    print(sql)    
    
    
'''
==============================

{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`title`, `tb_article`.`content`, `tb_article`.`category_id`, `tb_article`.`create_time`, `tb_article`.`update_time`, `tb_article`.`read_num`, `tb_article`.`like_num` FROM `tb_article`', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_category`.`id`, `tb_category`.`name` FROM `tb_category` WHERE `tb_category`.`id` = 2', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_category`.`id`, `tb_category`.`name` FROM `tb_category` WHERE `tb_category`.`id` = 2', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_category`.`id`, `tb_category`.`name` FROM `tb_category` WHERE `tb_category`.`id` = 4', 'time': '0.000'}
'''

上面外键产生了N+1查询问题,我们可以使用select_related来解决此类问题。

articles = Article.objects.all().select_related("category") # 没有访问数据库
print(connection.queries) # []

print(articles.query) 
'''
select tb_article.id, tb_article.title, tb_article.content, tb_article.category_id, tb_article.create_time, tb_article.update_time, tb_article.read_num, tb_article.like_num, tb_category.id, tb_category.name 
from tb_article left outer join tb_category on (tb_article.category_id = tb_category.id)
'''

for article in articles:   # 查询数据库,category数据也会一次性查出来
    print(article.category)    # 使用缓存

for sql in connection.queries:
    print('='*30)
    print(sql)
    
    
'''
[]
==============================
{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'}
==============================
{'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'}
==============================
{'sql': 'SELECT `tb_article`.`id`, `tb_article`.`title`, `tb_article`.`content`, `tb_article`.`category_id`, `tb_article`.`create_time`, `tb_article`.`update_time`, `tb_article`.`read_num`, `tb_article`.`like_num`, `tb_category`.`id`, `tb_category`.`name` FROM `tb_article` LEFT OUTER JOIN `tb_category` ON (`tb_article`.`category_id` = `tb_category`.`id`)', 'time': '0.000'}

'''

selected_related只能用在一对多或者一对一中,不能用在多对多或者多对一中。比如可以提前获取文章的作者,即正向获取关联对象时,关联对象会被缓存,后续根据外键访问时这个实例,就会从缓存中获得。

但是不能通过作者获取这个作者的文章(逆向关联),或者是通过某篇文章获取这个文章所有的标签(多对多的关系)。这个还得使用下面的接口解决。

**prefetch_related:**这个方法和select_related非常的类似,就是在访问多个表中的数据的时候,减少查询的次数。这个方法可用于多对多关系字段,也可用于反向外键关系(related_name)的查询问题。例如:

# 获取标题中带有`python`字符串的文章以及它的所有标签,
articles = Article.objects.prefetch_related("tags").filter(title__icontains="python")
print(articles.query) # 通过这条命令查看在底层的SQL语句

'''
select tb_article.id, tb_article.title, tb_article.content, tb_article.category_id, tb_article.create_time, tb_article.update_time, tb_article.read_num, tb_article.like_num from tb_article 
where tb_article.title like %python%
'''

for article in articles:     # 查询article文章对象的同时提取tag标签对象
    print(article.title)     # 使用缓存
    print(article.tags.all())    # 使用缓存
   
'''
python数据类型
<QuerySet [<Tag: MySQL>, <Tag: 快速入门>]>
Python快速入门
<QuerySet [<Tag: 快速入门>]>
'''

for sql in connection.queries:
    print('='*30)
    print(sql)
'''
触发的相关SQL,for循环时产生访问数据库的操作,查询article文章对象的同时提取tag标签对象
==============================
select tb_article.id, tb_article.title, tb_article.content,tb_article.category_id, tb_article.create_time, tb_article.update_time, tb_article.read_num,tb_article.like_num
from tb_article
where tb_article.title like '%python%'

==============================

select (tb_article_tags.article_id) as _prefetch_related_val_article_id, tb_tag.id, tb_tag.name
from tb_tag inner join tb_article_tags on(tb_tag.id = tb_article_tags.tag_id)
where tb_article_tags.article_id IN (2, 5)
'''

第一条SQL查询仅仅是获取标题中带有python字符串的Article对象,第二条比较关键,它选取中间表tb_article_tagsarticle_id带有python字符串的行,然后和tb_tag表内联(INNER JOIN)得到结果表。

现在问题来了,如果我们获取tags对象时只希望获取带有入门的tag对象怎么办呢?

articles = Article.objects.prefetch_related('tags').filter(title__icontains="python")
print(articles.query)

'''
select tb_article.id, tb_article.title, tb_article.content, tb_article.category_id, tb_article.create_time, tb_article.update_time, tb_article.read_num, tb_article.like_num 
from tb_article 
where tb_article.title like %python%
'''

for article in articles: #for循环时产生访问数据库的操作,查询article文章对象的同时提取tag标签对象
    print(article.title)  # 使用缓存
    print(article.tags.filter(name__icontains='入门')) # 之前用prefetch_related缓存的数据将会被忽略掉

'''
python数据类型
<QuerySet [<Tag: 快速入门>]>
Python快速入门
<QuerySet [<Tag: 快速入门>]>

'''    
    
for sql in connection.queries:
    print('-'*30)
    print(sql)
    
'''
触发的相关SQL,for循环时产生访问数据库的操作,查询article文章对象的同时提取tag标签对象
------------------------------
select tb_article.id, tb_article.title, tb_article.content, tb_article.category_id, tb_article.create_time, tb_article.update_time, tb_article.read_num, tb_article.like_num 
from tb_article 
where tb_article.title like '%python%'

------------------------------
select (tb_article_tags.article_id) as _prefetch_related_val_article_id, tb_tag.id, tb_tag.name 
from tb_tag inner join tb_article_tags on (tb_tag.id = tb_article_tags.tag_id) 
where tb_article_tags.article_id in (2, 5)

------------------------------
# 但是这里多了2条查询语句,一个为查询id=2对应的文章和id=5对应文章。

select tb_tag.id, tb_tag.name 
from tb_tag inner join tb_article_tags on (tb_tag.id = tb_article_tags.tag_id) 
where (tb_article_tags.article_id = 2 and tb_tag.name like '%入门%') 
limit 21

------------------------------
select tb_tag.id, tb_tag.name 
from tb_tag inner join tb_article_tags on (tb_tag.id = tb_article_tags.tag_id) 
where (tb_article_tags.article_id = 5 and tb_tag.name like '%入门%')  
limit 21
'''

注意:在使用QuerySet的时候,一旦在链式操作中改变了数据库请求,之前用prefetch_related缓存的数据将会被忽略掉,这会导致Django重新请求数据库来获得相应的数据,从而造成性能问题,这里提到的改变数据库请求指各种filter()、exclude()等等最终会改变SQL代码的操作。而all()并不会改变最终的数据库请求,因此是不会导致重新请求数据库的。

那如果确实是想要在查询的时候指定过滤条件该如何做呢,这时候我们可以使用django.db.models.Prefetch来实现,Prefetch这个可以提前定义好queryset,给prefect_related方法添加条件和属性,示例代码如下:

from django.db.models import Prefetch

articles = Article.objects.prefetch_related(Prefetch('tags', queryset=Tag.objects.filter(name__icontains='入门'))).filter(title__icontains="python")
print(articles.query)  #  通过这条命令查看在底层的SQL语句
                                            

for article in articles:     # 产生两条查询语句,分别查询article和tags
    print(article.title)     # 使用缓存
    print(article.tags.filter(name__icontains='入门'))
   

'''
select tb_article.id, tb_article.title, tb_article.content, tb_article.category_id, tb_article.create_time, tb_article.update_time, tb_article.read_num, tb_article.like_num from tb_article where tb_article.title like %python%
'''

for article in articles:
    print(article.title)
    tags = article.tags.filter(name__icontains='入门')
    for tag in tags:
        print(tag)
'''    
python数据类型
快速入门
Python快速入门
快速入门
'''    

for sql in connection.queries:
    print('='*30)
    print(sql) 


'''
==============================
{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'}
==============================
{'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'}
==============================
{'sql': "SELECT `tb_article`.`id`, `tb_article`.`title`, `tb_article`.`content`, `tb_article`.`category_id`, `tb_article`.`create_time`, `tb_article`.`update_time`, `tb_article`.`read_num`, `tb_article`.`like_num` FROM `tb_article` WHERE `tb_article`.`title` LIKE '%python%'", 'time': '0.000'}
==============================
{'sql': "SELECT (`tb_article_tags`.`article_id`) AS `_prefetch_related_val_article_id`, `tb_tag`.`id`, `tb_tag`.`name` FROM `tb_tag` INNER JOIN `tb_article_tags` ON (`tb_tag`.`id` = `tb_article_tags`.`tag_id`) WHERE (`tb_tag`.`name` LIKE '%入门%' AND `tb_article_tags`.`article_id` IN (2, 5))", 'time': '0.000'}
==============================
{'sql': "SELECT `tb_tag`.`id`, `tb_tag`.`name` FROM `tb_tag` INNER JOIN `tb_article_tags` ON (`tb_tag`.`id` = `tb_article_tags`.`tag_id`) WHERE (`tb_tag`.`name` LIKE '%入门%' AND `tb_article_tags`.`article_id` = 2 AND `tb_tag`.`name` LIKE '%入门%')", 'time': '0.000'}
==============================
{'sql': "SELECT `tb_tag`.`id`, `tb_tag`.`name` FROM `tb_tag` INNER JOIN `tb_article_tags` ON (`tb_tag`.`id` = `tb_article_tags`.`tag_id`) WHERE (`tb_tag`.`name` LIKE '%入门%' AND `tb_article_tags`.`article_id` = 5 AND `tb_tag`.`name` LIKE '%入门%')", 'time': '0.000'}


'''

#django#

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码