内容:

1.课前复习

2.django路由规则

3.django视图函数

4.django ORM

5.模板

 

django预备知识:https://www.cnblogs.com/wyb666/p/9444150.html

django基础参考:http://www.cnblogs.com/wupeiqi/articles/5237704.html

 

 

 

一、课前复习

1.HTTP协议消息格式

 1    请求(request):
 2         请求方法 路径 HTTP/1.1\r\n
 3         k1:v1\r\n
 4         ...\r\n
 5         \r\n
 6         请求体        <-- 可以有,可以没有
 7     
 8     响应(response):
 9         HTTP/1.1 状态码 状态描述符\r\n
10         k1:v1\r\n
11         Content-Type: text/html; charset=utf8\r\n
12         \r\n
13         响应正文       <-- HTML内容

 

 

2.python的web框架本质

  • 收发socket消息 --> 按照HTTP协议消息格式去解析消息
  • 路径和要执行的函数的对应关系 --> 主要的业务逻辑
  • 字符串替换 --> 模板(特殊符号 --> 数据)

 

 

3.一个完整的请求过程:

  • 启动服务端,等待客户端(用户的浏览器)来连接
  • 在浏览器地址栏输入URL,与服务端建立连接,浏览器发送请求
  • 服务端收到请求消息,解析请求消息,根据路径和函数的对应关系,找到将要执行的函数
  • 执行函数,打开HTML文件,进行字符串替换,得到一个最终要返回的HTML内容
  • 按照HTTP协议的消息格式要求,把HTML内容回复给用户浏览器(发送响应)
  • 浏览器收到响应的消息之后,按照HTML的规则渲染页面.
  • 关闭连接

 

 

 

二、django路由系统

在django程序中,可以通过urls.py文件对所有的url进行任务的分配,根据路由规则的定义选择不同的业务处理函数进行处理,urls.py中规定的对应规则可以说是路由系统(URLconf)

关于路由规则的详细内容:http://www.cnblogs.com/liwenzhou/p/8271147.html

1.基本路由规则

基本格式(1.x版本):

1 from django.conf.urls import url
2 
3 urlpatterns = [
4      url(正则表达式, views视图函数,参数,别名),
5 ]
  • 正则表达式:一个正则表达式字符串
  • views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
  • 参数:可选的要传递给视图函数的默认参数(字典形式)
  • 别名:一个可选的name参数

Django 2.0版本路由系统的写法:

1 from django.urls import path
2 
3 urlpatterns = [
4     path('articles/', views.articles),
5     path('articles/<int:year>/', views.year_archive),
6     path('articles/<int:year>/<int:month>/', views.month_archive),
7     path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
8 ]

 

 

2.路由系统正则表达式详解

基础样例 - 分组匹配:

1 from django.conf.urls import url
2 from . import views
3 
4 urlpatterns = [
5     url(r'^articles/2003/$', views.special_case_2003),
6     url(r'^articles/([0-9]{4})/$', views.year_archive),
7     url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
8     url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
9 ]

注意:

  • urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续
  • 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)
  • 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles
  • 每个正则表达式前面的'r' 是可选的但是建议加上

 

上面的示例使用简单的正则表达式分组匹配(通过圆括号)来捕获URL中的值并以位置参数形式传递给视图;在更高级的用法中,可以使用分组命名匹配的正则表达式组来捕获URL中的值并以关键字参数形式传递给视图

在Python的正则表达式中,分组命名正则表达式组的语法是(?P<name>pattern),其中name是组的名称,pattern是要匹配的模式

分组命名匹配:

1 from django.conf.urls import url
2 from . import views
3 
4 urlpatterns = [
5     url(r'^articles/2003/$', views.special_case_2003),
6     url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
7     url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
8     url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
9 ]

这个实现与前面的示例完全相同,只有一个细微的差别:捕获的值作为关键字参数而不是位置参数传递给视图函数,另外注意无论哪种方法每个在路由中捕获的参数都作为一个普通的Python字符串传递给视图

 

另外views.py中可以给视图函数的参数设置默认值:

django框架基础

 

 

3.django路由分发

1个Django 项目里面有多个APP目录大家共有一个 url容易造成混淆,于是路由分发让每个APP的拥有了自己单独的url:

项目目录下的urls.py:

1 from django.conf.urls import url, include
2 from django.contrib import admin
3 
4 urlpatterns = [
5     # 分发到APP的路由
6     url(r'^basic/', include('basic.urls')),
7     url(r'^app1/', include('app1.urls')),
8     url(r'^app2/', include('app2.urls')),
9 ]

basic这个APP下的urls.py:

1 from django.conf.urls import url
2 from basic import views
3 
4 urlpatterns = [
5     url(r'^index/', views.index),
6     url(r'^login/', views.login),
7     url(r'^register/', views.register),
8 ]

完成上述设置后,basic这个APP的路由只需在自己APP下的urls.py配置即可,访问时前面带上basic路径即可

 

 

4.命名URL和URL反向解析

(1)前言

在使用Django 项目时,一个常见的需求是获得URL的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。
人们强烈希望不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 毫不相关的专门的URL 生成机制,因为这样容易导致一定程度上产生过期的URL。
换句话讲,需要的是一个DRY 机制。除了其它有点,它还允许设计的URL 可以自动更新而不用遍历项目的源代码来搜索并替换过期的URL。
获取一个URL 最开始想到的信息是处理它视图的标识(例如名字),查找正确的URL 的其它必要的信息有视图参数的类型(位置参数、关键字参数)和值。
Django 提供一个办法是让URL 映射是URL 设计唯一的地方。你填充你的URLconf,然后可以双向使用它:

  • 根据用户/浏览器发起的URL 请求,它调用正确的Django 视图,并从URL 中提取它的参数需要的值
  • 根据Django 视图的标识和将要传递给它的参数的值,获取与之关联的URL

 

(2)命名URL和URL反向解析

前言中第一种方式是我们在前面的章节中一直讨论的用法,是直接获得url的最终形式,可以称之为命名URL

而第二种方式叫做反向解析URL或者简单的URL 反查
在需要URL 的地方,对于不同层级,Django 提供不同的工具用于URL 反查:

  • 在模板中:使用url模板标签。
  • 在Python 代码中:使用django.core.urlresolvers.reverse() 函数。
  • 在更高层的与处理Django 模型实例相关的代码中:使用get_absolute_url() 方法。

反向解析URL本质上就是给url匹配模式起别名,然后用过别名拿到具体的URL路径

用法如下:

 1 起别名: 在url匹配模式中,定义name="别名"
 2 
 3 1. 在模板语言里面使用:
 4 {% url "别名" %} --> 得到具体的URL路径
 5 
 6 
 7 2. 在视图中如何使用:
 8 from django.urls import reverse
 9 
10 reverse("别名") --> 得到具体的URL路径
11 
12 
13 3. 如何传参数?
14 模板语言中:
15 {% url "别名" 2018 "nb" %}
16 
17 视图函数中
18 传位置参数:    reverse("别名", args=(2018, "nb"))
19 传关键字参数: reverse("别名" kwargs={"year": 2018, "title": "nb"})
20 
21 
22 4. namespace
23 为了防止不同的app下面的url匹配模式有重复的别名,可以给app起别名

 

(3)实例如下:

urls.py:

1 urlpatterns = [
2     url(r'^admin/', admin.site.urls, name="admin"),
3     # 分发到APP的路由
4     url(r'^basic/', include('basic.urls', namespace="basic")),
5 ]
1 urlpatterns = [
2     url(r'^user_list/', views.user_list, name="user_list"),
3     url(r'^add_user/', views.add_user, name="add_user"),
4 ]

views.py:

 1 def user_list(request):
 2     res = models.UserInfo.objects.all()
 3     return render(request, "user/user_list.html", {"user_list": res})
 4 
 5 def add_user(request):
 6     err_msg = ""
 7     if request.method == "POST":
 8         new_name = request.POST.get("username", None)
 9         new_pwd = request.POST.get("password", None)
10         if new_name and new_pwd:
11             models.UserInfo.objects.create(username=new_name, password=new_pwd)
12             return redirect(reverse("basic:user_list"))
13         else:
14             err_msg = "用户名或密码不能为空!"
15     return render(request, "user/add_user.html", {"error": err_msg})

HTML:

1 <a class="btn btn-default" href="{% url "basic:add_user" %}" role="button">添加用户</a>

 

 

 

三、django视图系统

视图系统简称视图,可以是一个简单的Python 函数,它接受Web请求并且返回Web响应。无论视图本身包含什么逻辑,都要返回响应。

views.py中(一般为了模块化都是放在APP的views里)

关于视图系统详细:http://www.cnblogs.com/liwenzhou/articles/8305104.html

1.最简单的视图

不论什么视图都包含两个对象:

  • request:用户请求的相关所有信息,在django中是HttpRequest对象
  • response:响应信息(字符串 or HTML or 图片、、、),在django中是HttpResponse对象

最简单的视图:

1 from django.shortcuts import HttpResponse
2 
3 def easy_view(request):
4     # 每个视图函数都使用HttpRequest对象作为第一个参数,并且通常称之为request
5     return HttpResponse("hello world!")

视图函数,围绕着两个对象进行:HttpResponse和HttpRequest

 

 

2.HttpRequest

(1)属性

 1 request.path       获取访问文件路径
 2 request.path_info       获取用户请求的路径(不包含IP和端口和URL参数)
 3 request.method      获取请求中使用的HTTP方式(POST/GET)
 4 request.body      含所有请求体信息 是bytes类型
 5 request.GET       GET请求的数据(类字典对象)  请求头中的url中?后面拿值
 6 request.POST       POST请求的数据(类字典对象) 请求体里拿值
 7 
 8 request.FILES:      包含所有上传文件的类字典对象;FILES中的每一个Key都是<input type="file" name="" />标签中
 9                  name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys:
10                  filename:      上传文件名,用字符串表示
11                  content_type:   上传文件的Content Type
12                  content:       上传文件的原始内容
13 
14 request.user:      是一个django.contrib.auth.models.User对象,代表当前登陆的用户。如果访问用户当前
15                  没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你
16                  可以通过user的is_authenticated()方法来辨别用户是否登陆:
17                  if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware
18                  时该属性才可用
19 
20 request.COOKIES    包含所有cookies的标准Python字典对象;keys和values都是字符串。
21 request.session     唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用

 

属性实例 - 上传文件:

 1 def upload(request):
 2     """
 3     保存上传文件前,数据需要存放在某个位置。默认当上传文件小于2.5M时,django会将上传文件的全部内容读进内存。从内存读取一次,写磁盘一次。
 4     但当上传文件很大时,django会把上传文件写到临时文件中,然后存放到系统临时文件夹中。
 5     :param request: 
 6     :return: 
 7     """
 8     if request.method == "POST":
 9         # 从请求的FILES中获取上传文件的文件名,file-name为页面上type=files类型input的name属性值
10         filename = request.FILES["file-name"].name
11         # 在项目目录下新建一个文件
12         with open(filename, "wb") as f:
13             # 从上传的文件对象中一点一点读
14             for chunk in request.FILES["file-name"].chunks():
15                 # 写入本地文件
16                 f.write(chunk)
17         return HttpResponse("上传OK")

 

(2)方法

1 request.GET.get('name', None)            拿到GET请求里name的值(不存在就为None)
2 request.POST.get('username', None)       拿到GET请求里username的值(不存在就为None)
3 如果某个键对应有多个值,则不能直接用get取值,需要用getlist,如:request.POST.getlist("hobby")
4
5 获取请求路径:
6 请求url: http://127.0.0.1:8000/index.html/23?a=1
7 request.path 结果: /index.html/23
8 request.get_full_path() 结果: /index.html/23?a=1

 

 

3.HttpResponse

对于HttpRequest请求对象来说,是由django自动创建的,但是,HttpResponse响应对象就必须我们自己创建。每个view请求处理方法必须返回一个响应。HttpResponse类在django.http.HttpResponse

可以由HttpResponse对象上扩展出多种常用方法,如下所示

(1)HttpResponse函数

1 from django.shortcuts import HttpResponse
2 
3 
4 # 最简单的视图函数
5 def easy_view(request):
6     # 返回最简单的一个响应(一个字符串): hello world!
7     return HttpResponse("hello world!")

 

补充 - JsonResponse

JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应:

1 from django.http import JsonResponse
2 
3 response = JsonResponse({'foo': 'bar'})
4 print(response.content)
5 
6 b'{"foo": "bar"}'

默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数:

response = JsonResponse([1, 2, 3], safe=False)

 

(2)render函数

作用:将特点页面渲染后返回给浏览器

渲染 -> 给页面中的参数赋值

render(request, template_name[, context])

结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象

参数如下:

  • request: 用于生成响应的请求对象
  • template_name:要使用的模板的完整名称,可选的参数
  • context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它
  • content_type:生成的文档要使用的MIME类型。默认为DEFAULT_CONTENT_TYPE 设置的值
  • status:响应的状态码。默认为200

render实例:

1 from django.shortcuts import render
2 
3 def my_view(request):
4     # 视图的代码写在这里
5     return render(request, 'index.html', {'foo': 'bar'})
1 def render(request, template_name, context=None, content_type=None, status=None, using=None):
2     """
3     Returns a HttpResponse whose content is filled with the result of calling
4     django.template.loader.render_to_string() with the passed arguments.
5     """
6     content = loader.render_to_string(template_name, context, request, using=using)
7     return HttpResponse(content, content_type, status)
render源码

相关文章: