Django之路由层、请求生命周期、分组、反向解析、路由分发、虚拟环境、JsonResponse
一、创建模型类
1.先在models里建表
以图书管理管理系统为例:
图书表
- 图书和出版社是一对多的外键关系
- 一对多外键关系 外键字段建在多的那一方
出版社表
作者表
- 图书与作者是多对多外键关系
- 多对多外键关系 外键字段无论建在哪张表里面都可以
- 但是推荐你建在查询频率较高的那种表中
- 作者与作者详情是一对一的外键关系
- 一对一外键关系 外键字段建在哪张表里面都可以
- 但是推荐你建在查询频率较高的那种表中
class Book(models.Model): # id是自动创建的 我们就不写了 title = models.CharField(max_length=64) # price为小数字段 总共8位小数位占2位 price = models.DecimalField(max_digits=8,decimal_places=2)
class Publish(models.Model): name = models.CharField(max_length=64) addr = models.CharField(max_length=64)
class Author(models.Model): name = models.CharField(max_length=32) phone = models.BigIntegerField() # 一对一外键关系建立 author_detail = models.OneToOneField(to='AuthorDetail')
class AuthorDetail(models.Model): age = models.IntegerField() addr = models.CharField(max_length=255)
2.建关系(外键字段)
一对多:
class Book(models.Model): # id是自动创建的 我们就不写了 title = models.CharField(max_length=64) # price为小数字段 总共8位小数位占2位 price = models.DecimalField(max_digits=8,decimal_places=2) # 书籍与出版社 是一对多外键关系 publish = models.ForeignKey(to='Publish') # 默认关联字段就是出版社表的主键字段 # publish = models.ForeignKey(to=Publish) # to后面也可以直接写表的变量名 但是需要保证该变量名在当前位置的上方出现
多对多:
class Book(models.Model): # id是自动创建的 我们就不写了 title = models.CharField(max_length=64) # price为小数字段 总共8位小数位占2位 price = models.DecimalField(max_digits=8,decimal_places=2) # 书籍与出版社 是一对多外键关系 publish = models.ForeignKey(to='Publish') # 默认关联字段就是出版社表的主键字段 # publish = models.ForeignKey(to=Publish) # to后面也可以直接写表的变量名 但是需要保证该变量名在当前位置的上方出现 # 书籍与作者 是多对多外键关系 authors = models.ManyToManyField(to='Author') # 书籍和作者是多对多关系 """ authors字段是一个虚拟字段 不会真正的在表中创建出来 只是用来告诉django orm 需要创建书籍和作者的第三张关系表 """
class Author(models.Model): name = models.CharField(max_length=32) phone = models.BigIntegerField() # 一对一外键关系建立 author_detail = models.OneToOneField(to='AuthorDetail')
二、django请求生命周期流程图
三、路由层
1.路由匹配
url方法:第一个参数是一个正则匹配,一旦正则能够匹配到内容 会立刻执行对应的视图函数,不会再继续匹配了,用户输入url不加最后的斜杠, django会默认自动加上 ,你可以在配置文件中指定是否开启该功能
APPEND_SLASH = True/False # 默认为True, 可改成False
2.分组
就是给正则表达式加括号。
无名分组:
加括号的正则表达式匹配到的内容会变成位置参数传入视图函数。
url(r'^test/([0-9]{4})/',views.test)
def index(request,args): return HttpResponse('')
有名分组:
给一段正则起一个别名,匹配的时候会将括号内正则表达式匹配到的内容当做关键字参数传递给对应的视图函数。
url(r'^test/(?P<year>\d+)/',views.test)
def index(request,year): return HttpResponse('index')
补充:
# 无名有名能否混合使用 >>> 不能!!! # url(r'^test/(\d+)/(?P<year>\d+)/', views.test), # 虽然不能混合使用 但是同一种命名方式 可以使用多个 url(r'^test/(\d+)/(\d+)/',views.test), url(r'^test/(?P<xxx>\d+)/(?P<year>\d+)/',views.test),
3.反向解析
通过一些方法,能够得到一个结果 , 该结果可以访问到对应的url。
使用方式:
先给路由与视图函数对应关系 起一个名字 url(r'^testadd/',views.testadd,name='add') 前端解析 {% url 'add' %} 后端解析 from django.shortcuts import render,HttpResponse,redirect,reverse reverse('add')
无名分组反向解析:
url(r'^testadd/(\d+)/',views.testadd,name='add') 前端解析 {% url 'add' 1 %} 后端解析 reverse('add',args=(12,))
有名分组反向解析:
url(r'^testadd/(?P<year>\d+)/',views.testadd,name='add') 前端解析 {% url 'add' 1 %} # 推荐使用 {% url 'add' year= 1 %} # 标准的 后端解析 reverse('add',args=(12,)) reverse('add',kwargs={'year':12})
伪代码诠释:
# url.py url(r'^edit_user/(\d+)/',views.edit_user,names='edit') #html.py #<a href="edit_user/{{ user_obj.id }}/">编辑</a> {% for user_obj in user_queryset %} <a href="{% url 'edit' user_obj.id %}">编辑</a> {% endfor %} #views.py def edit_user(request,edit_id): reverse('edit',args=(edit_id,))
4.路由分发
总路由只做分发工作,子路由(在对应的app里面的url.py中)做路由与视图函数 对应关系。
需要一个分发的模块:
# 1.总路由 from django.conf.urls import url,include
# 路由分发 注意事项 应用名后面千万不能加$ # from app01 import urls as app01_urls # from app02 import urls as app02_urls # url(r'^app01/',include(app01_urls)), # url(r'^app02/',include(app02_urls)) # 简写 url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls'))
#2.子路由 #app01 from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^index/',views.index) ] #app02 from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^index/',views.index) ]
5.名称空间
url(r'^app01/',include('app01.urls',namespace='app01')) url(r'^app02/',include('app02.urls',namespace='app02'))
#后端解析 reverse('app01:index') reverse('app02:index') #前端解析 {% url 'app01:index' %} {% url 'app02:index' %} # 在给路由与视图函数起别名的时候只需要保证永远不出现冲突的情况即可 # 通常情况下我们推荐期别名的时候加上当前应用的应用名前缀 url(r'^index/',views.index,name='app01_index') url(r'^index/',views.index,name='app02_index')
6.虚拟环境
只安装项目所需要的功能模块,避免加载资源时的消耗。
1.创建
7.django版本区别
路由层
- 1.X用的是url
- 2.X、3.X用的是path
url第一个参数是一个正则表达式;
path第一个参数不支持正则表达式写什么就匹配什么;
path('login/<int:year>/',login)
如果你觉得path不好用 2.x、3.x给你提供了一个跟url一样的功能,re_path 等价于1.x里面的url功能。虽然path不支持正则表达式 但是它给你提供了五种默认的转换器如下:
str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式 int,匹配正整数,包含0。 slug,匹配字母、数字以及横杠、下划线组成的字符串。 uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。 path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
支持自定义转换器:
class MonthConverter: regex='\d{2}' # 属性名必须为regex def to_python(self, value): return int(value) def to_url(self, value): return value # 匹配的regex是两个数字,返回的结果也必须是两个数字
8.伪静态
url以.html结尾,给人的感觉好像是这个文件是写死的,内容不会轻易的改变。
做成html的好处是:提高你的网站被搜索引擎收藏的力度,提供网站的SEO查询效率。
9.JsonResponse
向前端返回一个json数据格式的字符串
方式一:
import json def my_view(request): data=['egon','kevin'] return HttpResponse(json.dumps(data) )
方式二:
from django.http import JsonResponse user_dict = {'username':'你好啊'} return JsonResponse(user_dict) 参数 1.json_dumps_params 字典 JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
2.safe
from django.http import JsonResponse def my_view(request): data=['pam','boom'] return JsonResponse(data,safe=False) #默认safe=True代表只能序列化字典对象,safe=False代表可以序列化字典以外的对象