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>
如此可用迭代器方式循环取出列表元素。这里涉及到的主要是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")
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
在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>
其他继承主页面的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)
django组件:(1)Form组件。(2)ModelForm组件。用于解决提交表单中的问题,(1)提交数据教养问题。(2)页面上至少要有错误提示。(3)页面上对应数据库中的每一个字段都要重复填写。(4)关联的数据需要手动获取并循环展示在页面。
具体django多条件查询的编写,具体实例可参考:https://www.jianshu.com/p/a86281df530e。

浙公网安备 33010602011771号