目录
一、无名有名分组的反向解析
1 无名分组的反向解析
# 先回顾一下之前的概念
# 什么是无名分组,怎么用?
# 在urls.py中配置路由的时候
url(r'^edit/(\d+/)',views.edit_user) # 在views中的edit_user函数会接收到url传来的位置参数,此参数为d+匹配到的内容
# 什么是反向解析,怎么用?
# 在urls.py中配置路由的时候
url(r'^edit/',views.edit_user,name='aaa')
# 就是给某个url和视图函数的绑定关系起一个别名,以后即使修改url也不会影响其他地方的代码
# 无名分组和反向解析连用
url(r'^edit/(\d+)/',views.edit_user,name='edit')
# 此处的应用场景比如我们之前在修改用户的时候,传给修改页面是手动写的?id=xxx,此处d+的匹配可以让我们更方便的实现修改功能
# 前端修改前
<a href="/edit/?id={{ obj.id }}" class="btn-xs btn-success">编辑</a>
# 前端修改后
<a href="{% url 'edit' obj.id %} " class="btn-xs btn-success">编辑</a>
# 后端修改前
def edit_user(request):
id = request.GET.get('id')
edit_obj = models.Author.objects.filter(id=id).first()
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
models.Author.objects.filter(id=id).update(username=username,password=password)
return redirect('/userlist/')
return render(request,'edit.html',locals())
# 后端修改后,区别就在于一个是需要get请求得到拼接提交的值,而无名分组的反向解析
def edit_user(request,edit_id):
edit_obj = models.Author.objects.filter(id=edit_id).first()
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
models.Author.objects.filter(id=edit_id).update(username=username,password=password)
return redirect('/userlist/')
return render(request,'edit.html',locals())
2 有名分组的反向解析
django为了编辑者的方便有名分组也可以使用无名分组反向解析一样的方式,只是在传参的时候换成关键字参数即可
二、路由分发
django为了每一个应用可以分开进行编程,每一个应用都可以有自己对应的templates文件夹,urls.py static文件夹。基于这种特点,可以更好的做到分组开发。组长只要把每个人写的app整合到一个django项目中即可,然后再配置文件里面注册索引的app,再利用路由分发的特点把所有的app整合起来。
路由分发就是以一个app为单位进行对应关系的绑定。
# 总路由
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 1.路由分发
url(r'^app01/',include(app01_urls)), # 只要url前缀是app01开头 全部交给app01处理
url(r'^app02/',include(app02_urls)) # 只要url前缀是app02开头 全部交给app02处理
# 2.终极写法 推荐使用
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))
# 注意事项:总路由里面的url千万不能加$结尾
]
# 子路由
# app01 urls.py
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^reg/',views.reg)
]
# app02 urls.py
from django.conf.urls import url
from app02 import views
urlpatterns = [
url(r'^reg/',views.reg)
]
三、名称空间(了解)
当我们进行路由分发的时候,如果出现app01和app02里面给一个绑定关系起了同一个别名。这个时候,进行反向解析就会只能找到放在前面的url,这时候就用到了名称空间。
# 总路由
url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02'))
url(r'^app02/',include('app02.urls',namespace='app02'))
# 解析的时候
# app01
urlpatterns = [
url(r'^reg/',views.reg,name='reg')
]
# app02
urlpatterns = [
url(r'^reg/',views.reg,name='reg')
]
reverse('app01:reg')
reverse('app02:reg')
{% url 'app01:reg' %}
{% url 'app02:reg' %}
# 其实只要保证名次不冲突,就没必要使用名称空间
# 通常遇到可能会重名的情况也是直接加上app的前缀
urlpatterns = [
url(r'^reg/',views.reg,name='app01_reg')
]
urlpatterns = [
url(r'^reg/',views.reg,name='app02_reg')
]
四、伪静态(了解)
就是把一个动态网页伪装成静态网页
比如:https://www.cnblogs.com/Dominic-Ji/p/9234099.html
以html为结尾可以伪装成静态页面
伪装的目的是可以增大本网站的seo查询力度,并且增加搜索引擎收藏本网站的概率。
搜索引擎本质上是一个巨大的爬虫程序。
urlpatterns = [
url(r'^reg.html',views.reg,name='app02_reg')
]
五、虚拟环境(了解)
在正常的开发中,我们会给一个项目配备一个这个项目该有的解释器环境,这个环境只有这个项目用得到的模块,其他模块一概不装。
这样可以减轻解释器压力,因为在开启一个项目的时候,会把所有的模块都加载一遍。
在以后开发的过程中,为了避免不同模块不同版本的兼容问题,通常会配备一个requirements.txt文件,里面装了这个项目所有的模块和版本,一键安装即可。
六、django版本区别
1 url的区别
django1.X路由层使用的是url方法,2.X和3.X版本路由层使用的是path方法
url()第一个参数支持正则,path()的第一个参数不支持正则,些什么就匹配什么
# 在2.X中如果想让path第一个参数匹配正则也有办法
from django.urls import path,re_path
from django.conf.urls import url
re_path(r'^index/',index),
url(r'^login/',login)
2 path虽然不支持正则,但是它内部支持五种转换器
# 第一种转换器
path('index/<int:id>/',views.index)
def index(request,id):
...
str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int,匹配正整数,包含0。
slug,匹配字母、数字以及横杠、下划线组成的字符串。
uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
3 path除了有默认的五个转换器之外,还支持自定义转换器(了解)
class MonthConverter:
regex='\d{2}' # 属性名必须为regex
def to_python(self, value):
return int(value)
def to_url(self, value):
return value # 匹配的regex是两个数字,返回的结果也必须是两个数字
from django.urls import path,register_converter
from app01.path_converts import MonthConverter
# 先注册转换器
register_converter(MonthConverter,'mon')
from app01 import views
urlpatterns = [
path('articles/<int:year>/<mon:month>/<slug:other>/', views.article_detail, name='aaa'),
]
七、视图层
1 三板斧
"""
HttpResponse
返回字符串类型
render
返回html页面 并且在返回给浏览器之前还可以给html文件传值
redirect
重定向
如果我们一个视图函数没有返回值的话会报如下错误
The view app01.views.index didn't return an HttpResponse object. It returned None instead.
在点击三板斧的源码,我们会发现最后都是HttpResponse对象,所以视图函数必须要返回HttpResponse对象
"""
# render简单内部原理
from django.template import Template,Context
res = Template('<h1>{{ user }}</h1>')
con = Context({'user':{'username':'jason','password':123}})
ret = res.render(con)
print(ret)
return HttpResponse(ret)
2 jsonResponse对象
json格式的数据可以跨语言交互,前后端数据交互需要使用到json作为过渡。
前端序列化-后端序列化
JSON.stringify() - json.dumps()
JSON.parse() - json.loads()
# 在视图函数中,我们要把一个字符串的数据转换成json数据,然后传递给前端
import json
from django.http import JsonResponse
def ab_json(request):
user_dict = {'username':'黄钊123','password':'123','hobby':'girl'}
# json模块方式,ensure_ascii=False在dumps里默认是True,默认不显示中文字符
json_str = json.dumps(user_dict,ensure_ascii=False)
return HttpRespone(json_str)
# JsonResponse模块方式
# 读源码可以知道,本质上还是用json实现的,只是加了一些其他的功能
return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
# 默认只能序列化字典,序列化其他需要加safe参数
3 form表单上传文件及后端如何操作
"""
form表单上传文件类型的数据
1.method必须指定成post
2.enctype必须换成formdata
"""
def ab_file(request):
if request.method == 'POST':
# print(request.POST) # 只能获取普通的简直对数据 文件不行
print(request.FILES) # 获取文件数据
# <MultiValueDict: {'file': [<InMemoryUploadedFile: u=1288812541,1979816195&fm=26&gp=0.jpg (image/jpeg)>]}>
file_obj = request.FILES.get('file') # 文件对象
print(file_obj.name)
with open(file_obj.name,'wb') as f:
for line in file_obj.chunks(): # 推荐加上chunks方法 其实跟不加是一样的都是一行行的读取
f.write(line)
return render(request,'form.html')
4 request对象方法
"""
request.method
request.POST
request.GET
request.FILES
request.body # 原生的浏览器发过来的二进制数据 后面详细的讲
request.path 获取不带参数的url
request.path_info 获取不带参数的url
request.get_full_path() 能过获取完整的url及问号后面的参数
"""
print(request.path) # /app01/ab_file/
print(request.path_info) # /app01/ab_file/
print(request.get_full_path()) # /app01/ab_file/?username=jason
5 FBV与CBV
function base views
class base views
# CBV路由
url(r'^login/',views.MyLogin.as_view())
from django.views import View
class MyLogin(View):
def get(self,request):
return render(request,'form.html')
def post(self,request):
return HttpResponse('post方法')
# CBV可以根据不同的请求直接匹配到不同的方法去执行