一 路由系统进阶(urls.py)
动态路由
urls.py中通过正则表达式的分组匹配,捕获用户访问的url中的值,传递给视图函数
1 分组匹配(通过圆括号): 相当于给视图函数传递 位置参数例子:
1 from django.conf.urls import url 2 3 from . import views 4 5 urlpatterns = [ 6 url(r'^articles/2003/$', views.special_case_2003), 7 url(r'^articles/([0-9]{4})/$', views.year_archive), 8 url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), 9 url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),10 ]
2 分组命名匹配:
相当于给视图函数传递 关键字参数在Python的正则表达式中,分组命名正则表达式组的语法是(?P<name>pattern)
,其中name
是组的名称,pattern
是要匹配的模式。
例子:
1 from django.conf.urls import url 2 3 from . import views 4 5 urlpatterns = [ 6 url(r'^articles/2003/$', views.special_case_2003), 7 url(r'^articles/(?P[0-9]{4})/$', views.year_archive), 8 url(r'^articles/(?P [0-9]{4})/(?P [0-9]{2})/$', views.month_archive), 9 url(r'^articles/(?P [0-9]{4})/(?P [0-9]{2})/(?P [0-9]{2})/$', views.article_detail),10 ]
3 name
防止将url硬编码到我们的业务逻辑代码中,给url起别名
通过别名,反向找到 url配置:
在views.py中:
from django.urls import reverse 具体的url = reverse('url别名')例子:
urls.py里面配置:
url(r'^publisher_list/$', views.publisher_list, name="alex")
vivews.py引用:
# def edit_publisher(request, edit_id):# print(reverse('alex'))# print("=" * 120)# if request.method == "POST":# new_name = request.POST.get("name888")# # 去数据库修改出版社名字# obj = models.Publisher.objects.get(id=edit_id)# obj.name = new_name# obj.save()# return redirect(reverse('alex')) #返回一个url# print(edit_id)# publisher_obj = models.Publisher.objects.get(id=edit_id)# return render(request, "edit_publisher.html", {"obj": publisher_obj})
4 传参数的两种写法(一不小心就被坑了)
例子一:url传参
1 urls.py配置:
url(r'^edit_publisher/$', views.edit_publisher),
2 views.py
3 def edit_publisher(request): if request.method=="POST": 4 #获取用户更改的id 5 edit_id=request.POST.get("id")#从浏览器传的参数获取的id 6 new_name=request.POST.get("name")#从form表单获取的名字 7 #去数据库找到这条记录 8 obj=models.Publisher.objects.get(id=edit_id) 9 obj.name=new_name10 obj.save()11 return redirect("/publisher_list/")12 else:13 edit_id = request.GET.get("id")14 publisher_edit = models.Publisher.objects.get(id=edit_id)15 return render(request,"edit_publisher.html",{"obj":publisher_edit})
注意:#上面红色字体里面的的obj一定要和你相应的edit_publisher里面的value,里面的一致,比如value=obj.name 这里就一定用obj
3 html配置:
publisher_list.html
1 2 3 4 5出版社列表 6 7 8 9 40 41 42
edit_publisher.html
1 2 3 4 525 26 27编辑 6 7 8 9
例子二 动态传参
1 urls配置:
url(r'^edit_publisher/(\d+)/$', views.edit_publisher),
2 views.py配置
1 # def edit_publisher(request,edit_id): 2 # if request.method=="POST": 3 # #获取用户更改的id 4 # 5 # new_name=request.POST.get("name")#从form表单获取的名字 6 # #去数据库找到这条记录 7 # obj=models.Publisher.objects.get(id=edit_id) 8 # print(obj.name) 9 # obj.name=new_name10 # obj.save()11 # return redirect("/publisher_list/")12 # else:13 #14 # publisher = models.Publisher.objects.get(id=edit_id)15 # return render(request,"edit_publisher.html",{"obj":publisher})
3 html配置:
publisher_list.html
edit_publisher.html不变
二 视图函数进阶(views.py)
1. 1-views.py
1.基础必会三件套 1. HttpResponse('字符串') 2. render(request, "xx.html", {"key": value}) 3. redirect("/其它的url/")2. FBV(Function Base View) 基于函数的视图
通过request.method == "POST" 去判断例子:
1 # def edit_publisher(request, edit_id): 2 # print(reverse('alex')) 3 # print("=" * 120) 4 # if request.method == "POST": 5 # new_name = request.POST.get("name888") 6 # # 去数据库修改出版社名字 7 # obj = models.Publisher.objects.get(id=edit_id) 8 # obj.name = new_name 9 # obj.save()10 # return redirect(reverse('alex'))11 # print(edit_id)12 # publisher_obj = models.Publisher.objects.get(id=edit_id)13 # return render(request, "edit_publisher.html", {"obj": publisher_obj})
3. CBV(Class Base View) 基于类的视图
1. 必须继承views.View -->在views.py里面导入: from django import views 2. 写一个自己的视图类 3. 通过定义不同的方法,来处理用户不同的请求 4. 在urls.py中注册视图的时候要写 views.类名.as_view()urls.py中配置:
url(r'^edit_publisher/(?P\d+)/$', views.EditPublisher.as_view(), name="wusir"),
view.py配置:
例子:
1 class EditPublisher(views.View): 2 def get(self, request, edit_id): 3 publisher_obj = models.Publisher.objects.get(id=edit_id) 4 return render(request, "edit_publisher.html", { "obj": publisher_obj}) 5 6 def post(self, request, edit_id): 7 new_name = request.POST.get("name888") 8 # 去数据库修改出版社名字 9 obj = models.Publisher.objects.get(id=edit_id)10 obj.name = new_name11 obj.save()12 return redirect(reverse('alex'))
2.1 request对象的常用属性和方法(常用的几个)
request表示的是和用户请求相关的所有数据
1. request.method --> 用户当前请求的请求方法 2. request.GET --> 用户请求中url中的参数 3. request.POST --> 用户POST请求的数据 4. request.path_info --> 用户访问的url路径是什么
3.1 Django上传文件
1. 前端页面
1. form表单一定要有action,method必须是post 2. 一定要配置enctype="multipart/form-data 2. 后端:def upload(request): """ 保存上传文件前,数据需要存放在某个位置。默认当上传文件小于2.5M时,django会将上传文件的全部内容读进内存。从内存读取一次,写磁盘一次。 但当上传文件很大时,django会把上传文件写到临时文件中,然后存放到系统临时文件夹中。 :param request: :return: """ if request.method == "POST": # 从请求的FILES中获取上传文件的文件名,file为页面上type=files类型input的name属性值 filename = request.FILES["file"].name # 在项目目录下新建一个文件 with open(filename, "wb") as f: # 从上传的文件对象中一点一点读 for chunk in request.FILES["file"].chunks(): # 写入本地文件 f.write(chunk) return HttpResponse("上传OK")
4.1 JsonResponse
专门用来返回JSON格式数据的响应对象 from django.http import JsonResponse例子:
from django.http import JsonResponseresponse = JsonResponse({ 'foo': 'bar'})print(response.content)b'{"foo": "bar"}'
默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。
例子:
urls.pyurl(r'^json_test/$', views.JsonTest.as_view()),views.pyclass JsonTest(views.View): def get(self, request): res = { "code": 0, "data": "alex"} res2 = ["alex", "污Sir", "金老板", "小姨妈", "MJJ"] return JsonResponse(res2,safe=False)
三 模板引擎进阶
1 模板语法:
1. 两个语法:
1. { { }} --> 跟变量相关的操作 2. {% %} --> 跟逻辑相关的操作2. 变量相关
1. 传字典或对象类型的数据 obj.name/obj.age 2. 传数组类型的数据 obj.索引值例子:
1 def template_test(request): 2 l = [11, 22, 33] 3 d = { "name": "alex"} 4 5 class Person(object): 6 def __init__(self, name, age): 7 self.name = name 8 self.age = age 9 10 def dream(self):11 return "{} is dream...".format(self.name)12 13 Alex = Person(name="Alex", age=34)14 Egon = Person(name="Egon", age=9000)15 Eva_J = Person(name="Eva_J", age=18)16 17 person_list = [Alex, Egon, Eva_J]18 return render(request, "template_test.html", { "l": l, "d": d, "person_list": person_list})
取值:
{ # 取l中的第一个参数 #}{ { l.0 }}{ # 取字典中key的值 #}{ { d.name }}{ # 取对象的name属性 #}{ { person_list.0.name }}{ # .操作只能调用不带参数的方法 #}{ { person_list.0.dream }}
3. 日期格式化
<p>{ { today|date:"Y-m-d H:i:s"}}</p> 4. 显示真正的html代码 <p>{ { link|safe }}</p>例子:
view配置:
1 def template_test(request): 2 data = ["金老板", "景女神", "MJJ"] 3 # data = "" 4 filesize = 1234567890 5 import datetime 6 today = datetime.datetime.today() 7 link = "" 8 9 10 class Person(object):11 def __init__(self, name, dream):12 self.name = name13 self.dream = dream14 15 def dream(self):16 return "我的梦想是学好Python!"17 pw = Person("彭玮", "不去下一期!")18 19 return render(request, "t.html", {20 "data": data,21 "file_size": filesize,22 "today": today,23 "link": link,24 "person": pw25 })
html中配置:
1 2 3 4 5Title 6 7 8 9 10 {#{
{ data.1 }}#}11{
{ data|default:"暂无数据" }}12{
{ file_size|filesizeformat }}13{
{ today }}14 15 16{
{ link }}17 {#{
{ link|safe }}#}18 19
20 2122 {% for teacher in data %}23 {% if forloop.last %}24 {
{ teacher }}25 {% else %}26 { { teacher }},27 {% endif %}28 {% endfor %}29 30 {#{% if 3 > 2 > 1 %}{% endif %}
#}(不支持这样写)31 {##}32 {#{% if 3 > 2 and 2 > 1 %}{% endif %}
#}33 34
35 36 { { person.name }}37 { { person.dream }}38 39 40 41
2. 母板
1. 为什么要用母版? 不同的页面有大量重复的代码,我们可以把公用的部分提取出来放在单独一个文件 2. 怎么使用? 1.1. 在子页面 通过使用 {% extends ‘模板名’ %} --> 放在子页面的最上面 2. 1{% block xx %}{% endblock %}母版例子:
1 2 3 4 5{ { html_title }} 6 7 {% block page-css %} 8 9 {% endblock %}10 11 12 {% include 'nav.html' %}131424 25 {% block page-js %}26 27 {% endblock %}28 29152316 17 {% block page-main %}18 19 {% endblock %}20 2122
3. 组件
可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方按如下语法导入即可。
使用 {% include '组件名' %}导入如何继承母版例子:
1 {% extends 'mama.html' %} 2 3 {% block page-main %} 4
# | 8id | 9出版社名称 | 10操作 | 11
---|---|---|---|
{ { forloop.counter }} | 17{ { publisher.id }} | 18{ { publisher.name }} | 1920 编辑21 删除22 | 23
四 CSRF
1. 为什么要有csrf_token?
2. Django中如何使用? 在render的页面上写上{% csrf_token %} 3. 如果是form表单形式提交,必须放在form表单中 4 如果不加csrf_token默认是不让提交的报403错误例子:
urls.py配置
1 url(r'^csrf_test/$', views.csrf_test),
views.py配置:
def csrf_test(request): if request.method=="POST": print(request.POST) return HttpResponse("OK") else: return render(request,"csrf_test.html")
html配置: