django框架学习(1)

1、

win10系统中,新建django项目,用stratproject创建项目后,默认目录中manage.py配置文件负责项目管理设置,包含启动、创建APP、数据管理,一般不用动,是经常使用的部分。urls文件是管理url和函数的对应关系的配置,settings文件是项目具体配置,这两个文件是经常修改的。(使用虚拟环境安装第三方库时,需要cmd中激活env,具体命令可在对应虚拟环境目录/Scripts下,用 activate django_mager 激活env环境)

所谓APP概念,是项目的具体功能模块,eg:比如用户管理、订单管理、问题管理、进度管理、网站、API等等,每个模块功能都可能涉及表结构、函数、HTML、CSS等结构设置。

在cmd中通过命令行新建app01后,打开app01目录,发现结构为

1 admin.py   #django提供的默认的admin管理 【固定不用动】
2 apps.py    #app启动类【固定不用动】
3 migrations  #文件夹,涉及数据库变更记录【固定不用动】
4 models.py   #对数据库操作【重要】
5 tests.py   #单元测试用【一般不动】
6 views.py   #函数定义【重要】,与上一层级中的urls.py关联。
7 __init__.py

app运行使用前,需要先注册。如何注册呢?需要在django项目目录下的settings中添加注册。该部分内容见django文档https://docs.djangoproject.com/zh-hans/4.1/intro/tutorial02/中激活模型部分。

2、

在vscode中,如何检查当前解释器是否用的env中的python呢?见下:

【Ctrl+Shift+P】后,出现:

"Python: Select Interpreter" 或 "Python: 选择解释器"

显示当前:...

粘贴,如C:\Users\21abc.HAIER\AppData\Local\Continuum\anaconda3\envs\study\python.exe

 3、

简单编写django项目

(1)确保app已注册。(2)编写url和视图函数对应关系【urls.py】。(3)编写视图函数【views.py】。重复2→3过程,就可以新增多个静态html页面。前端页面交互发来的资源请求,会通过urls.py找到对应的views.py中视图函数,然后返回资源,通过css/js渲染为templates网页。

4、

在vscode中,用资源管理器直接打开文件夹,虚拟环境就运行开始了。按 ctrl+` 直接打开vscode终端,可查看到终端中虚拟环境已经激活、运行,当前处于虚拟环境目录下,可直接执行manage.py启动app。根据文档阐述,django设计思路是 Django 应用是“可插拔”的。你可以在多个项目中使用同一个应用。除此之外,你还可以发布自己的应用,因为它们并不会被绑定到当前安装的 Django 上 。而views.py的功能是视图函数, jango 中的视图的概念是「一类具有相同功能和模板的网页的集合」 。

vscode会自动保存打开的环境,下一次启动时会自动加载。

5、

关于视图函数中定义的def函数,在urls.py中添加对应路径后,编写html页面,如何将传入的列表进行for循环呢?可在app01目录下新建templates目录,其中新建urls.py中对应路径的网页,代码可以参照下面的:

 1 {% load static %}
 2 
 3 <!DOCTYPE html>
 4 <html lang="en">
 5 <head>
 6     <meta charset="UTF-8">
 7     <title>Title</title>
 8 </head>
 9 <body>
10     <h1>项目问题管理</h1>
11     <div>{{ n1 }}</div>
12     <div>
13         {% for item in n2 %}
14         <span>{{ item }}</span>
15         {% endfor %}
16     </div>
17 </body>
18 </html>
View Code

如此可用迭代器方式循环取出列表元素。这里涉及到的主要是django的前端模板语法,当然推荐用vue或react进行前端开发,后端仅进行数据处理、API开发,Django的前端模板语法作为参考学习。

关键词是views.py中的return render()返回含有模板语法的html文件,通过内部渲染,得到前端页面。

前端展示的同样格式数据,比如说新闻、股票行情等,用python中类型举例,应为列表中嵌套的字典格式数据。比如示例代码中,head写错了,导致执行时报错 AttributeError: 'set' object has no attribute 'items' ,将head内容改为key:value格式后,获取成功,真的是“基础不牢,地动山摇”。

1 def news(req):
2     import requests
3     url = "http://www.xxx.com/api/article/NewsByIndex/xx/xxx/"
4     head = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"}
5     res = requests.get(url=url, headers=head)
6     data_list = res.json()
7     print(data_list)
8     return render(req, "news.html")
View Code

 6、

django中ORM学习

orm可以帮助我们做:(1)对数据库表进行映射方式的增删改查,但无法创建数据库。(2)映射方式进行操作数据表中的数据。

问1. 如何用orm创建数据库表?

答:(1)在settings中配置好mysql数据库连接。(2)在app目录下,在models.py中写好需要建表的相关class类。(3)在cmd中进入项目根目录下,用manage.py依次执行语句

1 python manage.py makemigrations
2 python manage.py migrate

用navicat查看数据库,数据表已经生成。如果想要删除表或表中字段,在models.py中将对应表的class或class中字段注释,继续执行上面两条语句,django会自动删除对应的表或字段。

 

如上图是 ORM 与数据库的映射关系图。ORM 把类映射成数据库中的表,把类的一个实例对象映射成数据库中的数据行,把类的属性映射成表中的字段,通过对象的操作对应到数据库表的操作,实现了对象到 SQL、SQL 到对象转换过程。
Django 把表模型定义为 Model,他需要继承自django.db.models中的 Model 类,只要是与数据表相关的操作,都需要继承这个类。同时ORM 对于数据库的的增删改查,也提供了一些简单的 API,例如 F 查询、Q 查询。

7、

Django的orm中,filter条件查询是用的比较多的,具体可能多涉及到对filter过滤字段的操作,记录如下

  1 基本操作
  2 
  3 # 获取所有数据,对应SQL:select * from User
  4 
  5 User.objects.all()
  6 
  7 # 匹配,对应SQL:select * from User where name = '运维咖啡吧'
  8 
  9 User.objects.filter(name='运维咖啡吧')
 10 
 11 # 不匹配,对应SQL:select * from User where name != '运维咖啡吧'
 12 
 13 User.objects.exclude(name='运维咖啡吧')
 14 
 15 # 获取单条数据(有且仅有一条,id唯一),对应SQL:select * from User where id = 724
 16 
 17 User.objects.get(id=123)
 18 
 19 常用操作
 20 
 21 # 获取总数,对应SQL:select count(1) from User
 22 
 23 User.objects.count()
 24 
 25 # 获取总数,对应SQL:select count(1) from User where name = '运维咖啡吧'
 26 
 27 User.objects.filter(name='运维咖啡吧').count()
 28 
 29 # 大于,>,对应SQL:select * from User where id > 724
 30 
 31 User.objects.filter(id__gt=724)
 32 
 33 # 大于等于,>=,对应SQL:select * from User where id >= 724
 34 
 35 User.objects.filter(id__gte=724)
 36 
 37 # 小于,<,对应SQL:select * from User where id < 724
 38 
 39 User.objects.filter(id__lt=724)
 40 
 41 # 小于等于,<=,对应SQL:select * from User where id <= 724
 42 
 43 User.objects.filter(id__lte=724)
 44 
 45 # 同时大于和小于, 1 < id < 10,对应SQL:select * from User where id > 1 and id < 10
 46 
 47 User.objects.filter(id__gt=1, id__lt=10)
 48 
 49 # 包含,in,对应SQL:select * from User where id in (11,22,33)
 50 
 51 User.objects.filter(id__in=[11, 22, 33])
 52 
 53 # 不包含,not in,对应SQL:select * from User where id not in (11,22,33)
 54 
 55 User.objects.exclude(id__in=[11, 22, 33])
 56 
 57 # 为空:isnull=True,对应SQL:select * from User where pub_date is null
 58 
 59 User.objects.filter(pub_date__isnull=True)
 60 
 61 # 不为空:isnull=False,对应SQL:select * from User where pub_date is not null
 62 
 63 User.objects.filter(pub_date__isnull=True)
 64 
 65 # 匹配,like,大小写敏感,对应SQL:select * from User where name like '%sre%',SQL中大小写不敏感
 66 
 67 User.objects.filter(name__contains="sre")
 68 
 69 # 匹配,like,大小写不敏感,对应SQL:select * from User where name like '%sre%',SQL中大小写不敏感
 70 
 71 User.objects.filter(name__icontains="sre")
 72 
 73 # 不匹配,大小写敏感,对应SQL:select * from User where name not like '%sre%',SQL中大小写不敏感
 74 
 75 User.objects.exclude(name__contains="sre")
 76 
 77 # 不匹配,大小写不敏感,对应SQL:select * from User where name not like '%sre%',SQL中大小写不敏感
 78 
 79 User.objects.exclude(name__icontains="sre")
 80 
 81 # 范围,between and,对应SQL:select * from User where id between 3 and 8
 82 
 83 User.objects.filter(id__range=[3, 8])
 84 
 85 # 以什么开头,大小写敏感,对应SQL:select * from User where name like 'sh%',SQL中大小写不敏感
 86 
 87 User.objects.filter(name__startswith='sre')
 88 
 89 # 以什么开头,大小写不敏感,对应SQL:select * from User where name like 'sh%',SQL中大小写不敏感
 90 
 91 User.objects.filter(name__istartswith='sre')
 92 
 93 # 以什么结尾,大小写敏感,对应SQL:select * from User where name like '%sre',SQL中大小写不敏感
 94 
 95 User.objects.filter(name__endswith='sre')
 96 
 97 # 以什么结尾,大小写不敏感,对应SQL:select * from User where name like '%sre',SQL中大小写不敏感
 98 
 99 User.objects.filter(name__iendswith='sre')
100 
101 # 排序,order by,正序,对应SQL:select * from User where name = '运维咖啡吧' order by id
102 
103 User.objects.filter(name='运维咖啡吧').order_by('id')
104 
105 # 多级排序,order by,先按name进行正序排列,如果name一致则再按照id倒叙排列
106 
107 User.objects.filter(name='运维咖啡吧').order_by('name','-id')
108 
109 # 排序,order by,倒序,对应SQL:select * from User where name = '运维咖啡吧' order by id desc
110 
111 User.objects.filter(name='运维咖啡吧').order_by('-id')
112 
113 进阶操作
114 
115 # limit,对应SQL:select * from User limit 3;
116 
117 User.objects.all()[:3]
118 
119 # limit,取第三条以后的数据,没有对应的SQL,类似的如:select * from User limit 3,10000000,从第3条开始取数据,取10000000条(10000000大于表中数据条数)
120 
121 User.objects.all()[3:]
122 
123 # offset,取出结果的第10-20条数据(不包含10,包含20),也没有对应SQL,参考上边的SQL写法
124 
125 User.objects.all()[10:20]
126 
127 # 分组,group by,对应SQL:select username,count(1) from User group by username;
128 
129 from django.db.models import Count
130 
131 User.objects.values_list('username').annotate(Count('id'))
132 
133 # 去重distinct,对应SQL:select distinct(username) from User
134 
135 User.objects.values('username').distinct().count()
136 
137 # filter多列、查询多列,对应SQL:select username,fullname from accounts_user
138 
139 User.objects.values_list('username', 'fullname')
140 
141 # filter单列、查询单列,正常values_list给出的结果是个列表,里边里边的每条数据对应一个元组,当只查询一列时,可以使用flat标签去掉元组,将每条数据的结果以字符串的形式存储在列表中,从而避免解析元组的麻烦
142 
143 User.objects.values_list('username', flat=True)
144 
145 # int字段取最大值、最小值、综合、平均数
146 
147 from django.db.models import Sum,Count,Max,Min,Avg
148 
149 User.objects.aggregate(Count(‘id’))
150 
151 User.objects.aggregate(Sum(‘age’))
152 
153 时间字段
154 
155 # 匹配日期,date
156 
157 User.objects.filter(create_time__date=datetime.date(2018, 8, 1))
158 
159 User.objects.filter(create_time__date__gt=datetime.date(2018, 8, 2))
160 
161 # 匹配年,year
162 
163 User.objects.filter(create_time__year=2018)
164 
165 User.objects.filter(create_time__year__gte=2018)
166 
167 # 匹配月,month
168 
169 User.objects.filter(create_time__month__gt=7)
170 
171 User.objects.filter(create_time__month__gte=7)
172 
173 # 匹配日,day
174 
175 User.objects.filter(create_time__day=8)
176 
177 User.objects.filter(create_time__day__gte=8)
178 
179 # 匹配周,week_day
180 
181 User.objects.filter(create_time__week_day=2)
182 
183 User.objects.filter(create_time__week_day__gte=2)
184 
185 # 匹配时,hour
186 
187 User.objects.filter(create_time__hour=9)
188 
189 User.objects.filter(create_time__hour__gte=9)
190 
191 # 匹配分,minute
192 
193 User.objects.filter(create_time__minute=15)
194 
195 User.objects.filter(create_time__minute_gt=15)
196 
197 # 匹配秒,second
198 
199 User.objects.filter(create_time__second=15)
200 
201 User.objects.filter(create_time__second__gte=15)
202 
203 # 按天统计归档
204 
205 today = datetime.date.today()
206 
207 select = {'day': connection.ops.date_trunc_sql('day', 'create_time')}
208 
209 deploy_date_count = Task.objects.filter(
210 
211     create_time__range=(today - datetime.timedelta(days=7), today)
212 
213 ).extra(select=select).values('day').annotate(number=Count('id'))
214 
215 Q 的使用
216 
217 Q对象可以对关键字参数进行封装,从而更好的应用多个查询,可以组合&(and)、|(or)、~(not)操作符。
218 
219 例如下边的语句
220 
221 from django.db.models import Q
222 
223 User.objects.filter(
224 
225     Q(role__startswith='sre_'),
226 
227     Q(name='公众号') | Q(name='运维咖啡吧')
228 
229 )
230 
231 转换成SQL语句如下:
232 
233 select * from User where role like 'sre_%' and (name='公众号' or name='运维咖啡吧')
234 
235 通常更多的时候我们用Q来做搜索逻辑,比如前台搜索框输入一个字符,后台去数据库中检索标题或内容中是否包含
236 
237 _s = request.GET.get('search')
238 
239 _t = Blog.objects.all()
240 
241 if _s:
242 
243     _t = _t.filter(
244 
245         Q(title__icontains=_s) |
246 
247         Q(content__icontains=_s)
248 
249     )
250 
251 return _t
252 
253 外键:ForeignKey
254 
255 表结构:
256 
257 class Role(models.Model):
258 
259     name = models.CharField(max_length=16, unique=True)
260 
261 class User(models.Model):
262 
263     username = models.EmailField(max_length=255, unique=True)
264 
265     role = models.ForeignKey(Role, on_delete=models.CASCADE)
266 
267 正向查询:
268 
269 # 查询用户的角色名
270 
271 _t = User.objects.get(username='运维咖啡吧')
272 
273 _t.role.name
274 
275 反向查询:
276 
277 # 查询角色下包含的所有用户
278 
279 _t = Role.objects.get(name='Role03')
280 
281 _t.user_set.all()
282 
283 另一种反向查询的方法:
284 
285 _t = Role.objects.get(name='Role03')
286 
287 # 这种方法比上一种_set的方法查询速度要快
288 
289 User.objects.filter(role=_t)
290 
291 第三种反向查询的方法:
292 
293 如果外键字段有related_name属性,例如models如下:
294 
295 class User(models.Model):
296 
297     username = models.EmailField(max_length=255, unique=True)
298 
299     role = models.ForeignKey(Role, on_delete=models.CASCADE,related_name='roleUsers')
300 
301 那么可以直接用related_name属性取到某角色的所有用户
302 
303 _t = Role.objects.get(name = 'Role03')
304 
305 _t.roleUsers.all()
306 
307 M2M:ManyToManyField
308 
309 表结构:
310 
311 class Group(models.Model):
312 
313     name = models.CharField(max_length=16, unique=True)
314 
315 class User(models.Model):
316 
317     username = models.CharField(max_length=255, unique=True)
318 
319     groups = models.ManyToManyField(Group, related_name='groupUsers')
320 
321 正向查询:
322 
323 # 查询用户隶属组
324 
325 _t = User.objects.get(username = '运维咖啡吧')
326 
327 _t.groups.all()
328 
329 反向查询:
330 
331 # 查询组包含用户
332 
333 _t = Group.objects.get(name = 'groupC')
334 
335 _t.user_set.all()
336 
337 同样M2M字段如果有related_name属性,那么可以直接用下边的方式反查
338 
339 _t = Group.objects.get(name = 'groupC')
340 
341 _t.groupUsers.all()
342 
343 get_object_or_404
344 
345 正常如果我们要去数据库里搜索某一条数据时,通常使用下边的方法:
346 
347 _t = User.objects.get(id=734)
348 
349 但当id=724的数据不存在时,程序将会抛出一个错误
350 
351 abcer.models.DoesNotExist: User matching query does not exist.
352 
353 为了程序兼容和异常判断,我们可以使用下边两种方式:
354 
355 方式一:get改为filter
356 
357 _t = User.objects.filter(id=724)
358 
359 # 取出_t之后再去判断_t是否存在
360 
361 方式二:使用get_object_or_404
362 
363 from django.shortcuts import get_object_or_404
364 
365 _t = get_object_or_404(User, id=724)
366 
367 # get_object_or_404方法,它会先调用django的get方法,如果查询的对象不存在的话,则抛出一个Http404的异常
368 
369 实现方法类似于下边这样:
370 
371 from django.http import Http404
372 
373 try:
374 
375     _t = User.objects.get(id=724)
376 
377 except User.DoesNotExist:
378 
379     raise Http404
380 
381 get_or_create
382 
383 顾名思义,查找一个对象如果不存在则创建,如下:
384 
385 object, created = User.objects.get_or_create(username='运维咖啡吧')
386 
387 返回一个由object和created组成的元组,其中object就是一个查询到的或者是被创建的对象,created是一个表示是否创建了新对象的布尔值
388 
389 实现方式类似于下边这样:
390 
391 try:
392 
393     object = User.objects.get(username='运维咖啡吧')
394 
395     created = False
396 
397 exception User.DoesNoExist:
398 
399     object = User(username='运维咖啡吧')
400 
401     object.save()
402 
403     created = True
404 
405 returen object, created
406 
407 执行原生SQL
408 
409 Django中能用ORM的就用它ORM吧,不建议执行原生SQL,可能会有一些安全问题,如果实在是SQL太复杂ORM实现不了,那就看看下边执行原生SQL的方法,跟直接使用pymysql基本一致了
410 
411 from django.db import connection
412 
413 with connection.cursor() as cursor:
414 
415     cursor.execute('select * from accounts_User')
416 
417     row = cursor.fetchall()
418 
419 return row
View Code

在Django中,如果未前后端分离,在前端页面提交form时,别忘了在表单函数中添加字段 {% csrf_token %} ,否则会报错。

问题:如果mysql中已有表,如何用django的orm生成表结构类?

要保存到文件,可以指定重定向文件,比如输出到 models.py 文件中,需要在cmd中执行: python manage.py inspectdb > models.py 。注意执行完成的models.py在执行命令的项目根目录下,而非直接输出到app目录下的models中。如果想要对对应表输出表结构模型,可以用 ython manage.py inspectdb table_name > models.py 。

8、

关于django中orm的表结构设计,比如涉及用户表,其中所属部门字段,应该设置为直接的部门名称还是间接关联其余表的部门id?要看具体的应用情景,存储部门id可以节约存储开销,但查询时需要联表查找,查询速度相对较慢,不太适合特大型集团企业。

用户表新建时,部门ID应施加约束,必须是部门表中已存在的ID才允许关联新增。具体如何实现呢?models.py表模型映射中,要使用 depart_id = models.ForeignKey(to="Department", to_field="id") 类似的外键关联约束实现。但又出现问题,员工离职,删除相关信息时,因外键关联,会影响到部门表;删除关联的用户信息,可能存在2种情况:(1)级联删除部门信息。(2)部门ID列置空。

9、

html如何实现模板继承?共用的页面样式部分避免重复修改。可以用如下的格式在html页面中实现body部分的模板样式,其他页面可以实现继承。

1 <div>
2     <div class="container">
3         {% block content %}-{% endblock%}
4     </div>
5 </div>
View Code

其他继承主页面的html,只要编写div部分即可,如下图继承模板。

 10、

django中如何进行Q查询?可以参考文章:https://www.cnblogs.com/oiqwyig/p/16993017.html。问:Q查询的应用场景是什么?答:这里主要就是让查询数据的时候,可以使用input获取的信息,进行用户交互。

from django.db.models import Q
q_obj = Q()  # 1.产生q对象
q_obj.connector = 'or'  # 默认多个条件的连接是and可以修改为or
q_obj.children.append(('pk', 1))  # 2.添加查询条件
q_obj.children.append(('price__gt', 2000))  # 支持添加多个
res = models.Book.objects.filter(q_obj)  # 查询支持直接填写q对象
print(res)
View Code

django组件:(1)Form组件。(2)ModelForm组件。用于解决提交表单中的问题,(1)提交数据教养问题。(2)页面上至少要有错误提示。(3)页面上对应数据库中的每一个字段都要重复填写。(4)关联的数据需要手动获取并循环展示在页面。

具体django多条件查询的编写,具体实例可参考:https://www.jianshu.com/p/a86281df530e。

posted @ 2022-12-16 00:26  dion至君  阅读(147)  评论(0)    收藏  举报