1. 路由系统

1.1 单一路由对应

  1. url(r'^index$', views.index),

1.2 基于正则的路由

  1. url(r'^index/(\d*)', views.index),
  2. url(r'^manage/(?P<name>\w*)/(?P<id>\d*)', views.manage),
  • 找到urls.py文件,修改路由规则
  1. from django.conf.urls import url,include
  2. from django.contrib import admin
  3. from cmdb import views
  4.  
  5. urlpatterns = [
  6. url(r'^index', views.index),
  7. url(r'^detail-(\d+).html/', views.detail),
  8. ]
  • 在views.py文件创建对应方法
  1. USER_DICT = {
  2. '1':{'name':'root1','email':'root@live.com'},
  3. '2':{'name':'root2','email':'root@live.com'},
  4. '3':{'name':'root3','email':'root@live.com'},
  5. '4':{'name':'root4','email':'root@live.com'},
  6. }
  7.  
  8. def index(request):
  9. return render(request,"index.html",{"user_dict":USER_DICT})
  10.  
  11. def detail(request,nid):  # nid指定的是(\d+)里的内容
  12. detail_info = USER_DICT[nid]
  13. return render(request, "detail.html", {"detail_info": detail_info})

  

1.3 url分组

在url.py增加对应路径

  1. from django.conf.urls import url,include
  2. from django.contrib import admin
  3. from cmdb import views
  4.  
  5. urlpatterns = [
  6. url(r'^index', views.index),
  7. url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html/', views.detail),<br>   # nid=\d+ uid=\d+
  8. ]

在views.py文件创建对应方法

  1. def detail(request,**kwargs):
  2. print(kwargs)
  3. #{'nid': '4', 'uid': '3'}
  4. nid = kwargs.get("nid")
  5. detail_info = USER_DICT[nid]
  6. return render(request, "detail.html", {"detail_info": detail_info})

1.4 为路由映射名称

  1. from django.conf.urls import url,include
  2. from django.contrib import admin
  3. from cmdb import views
  4.  
  5. urlpatterns = [
  6. url(r'^asdfasdfasdf/', views.index, name='i1'), #第一种方式i1
  7. url(r'^yug/(\d+)/(\d+)/', views.index, name='i2'), #第二种方式i2
  8. url(r'^buy/(?P<pid>\d+)/(?P<nid>\d+)/', views.index, name='i3'), #第三种方式i3

在templates目录下的index.html

  1. <body>
  2. {#第一种方法i1 路径asdfasdfasdf/#}
  3. {#<form action="{% url "i1" %}" method="post">#}
  4. {#第二种方法i2 路径yug/1/2/#}
  5. {#<form action="{% url "i2" 1 2 %}" method="post">#}
  6. {#第三种方法i3 路径buy/1/9//#}
  7. <form action="{% url "i3" pid=1 nid=9 %}" method="post">
  8. <p><input name="user" type="text" placeholder="用户名"/></p>
  9. <p><input name="password" type="password" placeholder="密码"/></p>
  10. <p><input type="submit" value="提交"/></p>
  11. </form>
  12. </body>

1.5 根据app对路由分类

主程序urls.py文件

  1. from django.conf.urls import url,include
  2. from django.contrib import admin
  3.  
  4. urlpatterns = [
  5. url(r'^monitor/', include('monitor.urls')), #调整到monitor目录中的urls.py文件
  6. ]

cmdb下的url.py文件

  1. from django.conf.urls import url
  2. from django.contrib import admin
  3. from monitor import views
  4. #
  5. urlpatterns = [
  6. url(r'^login', views.login),
  7. ]

1.6 获取当前URL

view.py中配置

  1. def index(request):
  2. print(request.path_info) #获取客户端当前的访问链接
  3. # / index
  4. return render(request,"index.html",{"user_dict":USER_DICT})

在templates目录下的index.html文件

  1. <form action="{{ request.path_info }}" method="post">
  2. <p><input name="user" type="text" placeholder="用户名"/></p>
  3. <p><input name="password" type="password" placeholder="密码"/></p>
  4. <p><input type="submit" value="提交"/></p>
  5. </form>

1.7 默认值

在url.py增加对应路径

  1. from django.conf.urls import url
  2. from django.contrib import admin
  3. from app01 import views
  4. urlpatterns = [
  5. url(r'^index/',views.index,{"name":"root"}),
  6. ]

在views.py文件创建对应方法

  1. from django.shortcuts import render,HttpResponse
  2. def index(request,name):
  3. return HttpResponse("%s is ok"%name)

运行并访问http://127.0.0.1:8000/index,页面显示:root is ok

1.8 命名空间

不同的url指向同一个视图就需要借助命名空间

主程序url.py文件

  1. from django.conf.urls import url,include
  2.  
  3. urlpatterns = [
  4. url(r'^a/', include('app01.urls', namespace='author-polls')),
  5. url(r'^b/', include('app01.urls', namespace='publisher-polls')),
  6. ]

app01下的urls.py文件

  1. from django.conf.urls import url
  2. from app01 import views
  3.  
  4. app_name = 'app01'
  5. urlpatterns = [
  6. url(r'^index/$', views.detail, name='detail')
  7. ]

在views.py文件创建对应方法

  1. from django.shortcuts import render,HttpResponse
  2. def index(request):
  3. return HttpResponse("ok")

访问http://127.0.0.1:8000/a/index,页面显示"ok"

以上定义带命名空间的url之后,使用name生成URL时候,应该如下:

  • v = reverse('author-polls:detail')
  • {% url 'author-polls:detail'%}

2. 视图

2.1 获取用户请求数据

request.GET

request.POST

request.FILES

其中,GET一般用于获取/查询 资源信息,而POST一般用于更新 资源信息 ; FILES用来获取上传文件;

2.2 checkbox等多选的内容

在templates目录下创建login.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="/login" method="POST" >
  9. <p>
  10. 男:<input type="checkbox" name="favor" value="11"/>
  11. 女:<input type="checkbox" name="favor" value="22"/>
  12. 人妖:<input type="checkbox" name="favor" value="33"/>
  13. </p>
  14. <input type="submit" value="提交"/>
  15. </form>
  16. </body>
  17. </html>

修改views.py文件对表单处理

  1. def login(request):
  2. #checkbox 多选框
  3. if request.method == "POST":
  4. favor_list = request.POST.getlist("favor") #getlist获取多个值
  5. print(favor_list) #多选框获取到的是列表格式
  6. #['11', '22', '33']
  7. return render(request,"login.html")
  8. elif request.method == "GET":
  9. return render(request,"login.html")
  10. else:
  11. print("other")

2.3 上传文件

  1. 文件对象 = reqeust.FILES.get()
  2. 文件对象.name
  3. 文件对象.size
  4. 文件对象.chunks()

在templates目录下创建login.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="/login" method="POST" enctype="multipart/form-data">
  9. <p>
  10. <input type="file" name="files"/>
  11. </p>
  12. <input type="submit" value="提交"/>
  13. </form>
  14. </body>
  15. </html>

修改views.py文件对表单处理

  1. def login(request):
  2. #file 上传文件
  3. if request.method == "POST":
  4. obj = request.FILES.get('files') #用files获取文件对象
  5. if obj:
  6. print(obj, type(obj), obj.name)
  7. # test.jpg <class 'django.core.files.uploadedfile.InMemoryUploadedFile'> test.jpg
  8. import os
  9. file_path = os.path.join('upload', obj.name)
  10. f = open(file_path, "wb")
  11. for item in obj.chunks(): #chunks表示所有的数据块,是个迭代器
  12. f.write(item)
  13. f.close()
  14. return render(request,"login.html")
  15. elif request.method == "GET":
  16. return render(request,"login.html")
  17. else:
  18. print("other")

2.4 请求的其他信息

  1. from django.core.handlers.wsgi import WSGIRequest
  2. request.environ #获取所有用户请求信息
  3. request.environ['HTTP_USER_AGENT'] #获取用户请求的设备信息

2.5 FBV & CBV

2.5.1 FBV

1.在templates目录下创建home.html文件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="/home/" method="POST">
  9. <p>
  10. <input type="text" name="user" placeholder="用户名"/>
  11. </p>
  12. <p>
  13. <input type="password" name="pwd" placeholder="密码"/>
  14. </p>
  15. <p>
  16. <input type="submit" value="提交">
  17. </p>
  18. </form>
  19. </body>
  20. </html>

2. 在urls.py文件增加home路径

  1. from django.conf.urls import url,include
  2. from django.contrib import admin
  3. from cmdb import views
  4.  
  5. urlpatterns = [
  6. # 固定语法
  7. url(r'^home/', views.Home.as_view()),
  8. ]

3. 在views.py文件创建函数Home

  1. def home(request):
  2. return render(request,"home.html")

2.5.2 CBV

1. 在templates目录下创建home.html文件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="/home/" method="POST">
  9. <p>
  10. <input type="text" name="user" placeholder="用户名"/>
  11. </p>
  12. <p>
  13. <input type="password" name="pwd" placeholder="密码"/>
  14. </p>
  15. <p>
  16. <input type="submit" value="提交">
  17. </p>
  18. </form>
  19. </body>
  20. </html>

2. 在urls.py文件增加home路径

  1. from django.conf.urls import url,include
  2. from django.contrib import admin
  3. from cmdb import views
  4.  
  5. urlpatterns = [
  6. # 固定语法
  7. url(r'^home/', views.Home.as_view()),
  8. ]

3. 在views.py文件创建类Home

  1. from django.views import View
  2.  
  3. class Home(View):
  4. # 先执行dispatch里面的内容
  5. def dispatch(self,request, *args, **kwargs):
  6. print("before")
  7. # 调用父类中的dispatch
  8. result = super(Home,self).dispatch(request, *args, **kwargs)
  9. print("after")
  10. return result
  11.  
  12. # 根据反射获取用户提交方式,执行get或post方法
  13. def get(self,request):
  14. print(request.method)
  15. return render(request,"home.html")
  16.  
  17. def post(self,request):
  18. print(request.method)
  19. return render(request,"home.html")

3. Templates

  通过之前的学习我们已经可以实现模板功能,但是大家会发现一个问题:按照之前学习的方法,同一个系统下的不同功能页面,我们需要在每个页面复制菜单、左侧右侧导航等;这样虽然也可以实现我们的需求,但是如果菜单、左右侧导航有所修改,我们就需要再挨个去变更。那么有没有其他的方法解决这个问题呢?----这里我们引入母版。

3.1 继承

首先,我们需要新建一个母版html文件(如:master.html),文件内容如下:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>{% block title %}{% endblock %}</title>
  6. <style>
  7. .pg_header{
  8. height: 50px;
  9. background-color: aquamarine;
  10. color:green;
  11. }
  12. </style>
  13. </head>
  14. <body>
  15. <div class="pg_header">母版测试</div>
  16. {% block content %}{% endblock %}
  17. </body>
  18. </html>

再新建一个子板html文件(如:userlist.html),文件内容如下:

  1. {% extends 'master.html' %} <!--有多个母版时,此处可区分继承的是哪个母版-->
  2. {% block title %}用户管理{% endblock %}
  3. {% block content %}
  4. <h1>用户管理</h1>
  5. <ul>
  6. {% for i in u %}
  7. <li>{{ i }}</li>
  8. {% endfor %}
  9. </ul>
  10. {% endblock %}

运行后查看页面,userlist.html继承了母版master.html的CSS和JS。(想要修改导航、菜单等内容,直接修改母版内容即可。)

学习完上面的东西之后,大家很快就会发现另外一个问题:上面的东西虽然能实现我们的需求,但是每个页面想要使用自己的CSS和JS就不行了,如何解决这个问题呢?

1.母版文件内容

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>{% block title %}{% endblock %}</title>
  6. <style>
  7. .pg_header{
  8. height: 50px;
  9. background-color: aquamarine;
  10. color:green;
  11. }
  12. </style>
  13. {% block css %}{%endblock%}
  14. </head>
  15. <body>
  16. <div class="pg_header">母版测试</div>
  17. {% block content %}{% endblock %}
  18. <script src="XXX"></script>
  19. {% block js %}{%endblock%}
  20. </body>
  21. </html>

2. 子板文件内容

  1. {% extends 'master.html' %} <!--有多个母版时,此处可区分继承的是哪个母版-->
  2. {% block title %}用户管理{% endblock %}
  3. {% block content %}
  4. <h1>用户管理</h1>
  5. <ul>
  6. {% for i in u %}
  7. <li>{{ i }}</li>
  8. {% endfor %}
  9. </ul>
  10. {% endblock %}
  11. {% block css%}
  12. <style>
  13. .body{
  14. color:red
  15. }
  16. </style>
  17. {% endblock%}
  18. {% block js%}
  19. <script>.....</script>
  20. {% endblock%}

PS:一个html文件只能继承一个母版

3.2 导入

新建tag.html文件, 文件内容如下:

  1. <form>
  2. <input type="text"/>
  3. <input type="submit"/>
  4. </form>

子板文件中插入代码

  1. <% include "tag.html" %>
  2. <% include "tag.html" %>
  3. <% include "tag.html" %>
  4. <% include "tag.html" %>

3.3 自定义simple_tag

  1. 在app中创建templatetags模块

  2. 创建任意 .py 文件,如:xx.py
  1. #!/usr/bin/env python
  2. #coding:utf-8
  3. from django import template
  4. from django.utils.safestring import mark_safe
  5.  
  6. register = template.Library()
  7.  
  8. @register.simple_tag
  9. def my_simple_time(v1,v2,v3):
  10. return v1 + v2 + v3
  11.  
  12. @register.simple_tag
  13. def my_input(id,arg):
  14. result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
  15. return mark_safe(result)

   3.  在使用自定义simple_tag的html文件顶部导入之前创建的 xx.py 文件名

  1. {% load xx %}

4.  使用simple_tag

  1. {% 函数名 arg1 arg2 %}
  2. {% my_simple_time 1 2 3%}
  3. {% my_input 'id_username' 'hide'%}

 5.  在settings中配置当前app,不然django无法找到自定义的simple_tag

  1. INSTALLED_APPS = (
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. 'app01',
  9. )

3.4 自定义filter

  1. 在app中创建templatetags模块

  2. 创建任意 .py 文件,如:xx.py

  1. #!/usr/bin/env python
  2. #coding:utf-8
  3. from django import template
  4. from django.utils.safestring import mark_safe
  5.  
  6. register = template.Library()
  7.  
  8. @register.filter
  9. def my_simple_time(v1,v2):
  10. return v1 + v2
  11.  
  12. @register.filter
  13. def my_input(id,arg):
  14. result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
  15. return mark_safe(result)

3.  在使用自定义filter的html文件顶部导入之前创建的 xx.py 文件名

  1. {% load xx %}

  4.  使用filter

  1. {{ 参数1|函数名:"参数二,参数三" }} {{ 参数1|函数名:数字 }}

  5.  在settings中配置当前app,不然django无法找到自定义的simple_tag

  1. INSTALLED_APPS = (
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. 'app01',
  9. )

filter和simple_tag的优缺点:

  • simple_tag不能作为if条件;但可使用任意参数;
  • filter可以作为if条件;但最多两个参数,不能加空格;

4. 分页

4.1 django内置分页

  1. Paginator

4.2 自定义分页

分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。

4.2.1 准备基础数据

1. 在url.py增加对应路径

  1. from django.conf.urls import url,include
  2. from django.contrib import admin
  3. from cmdb import views
  4.  
  5. urlpatterns = [
  6. url(r'^index', views.index),
  7. url(r'^userlist/', views.userlist),
  8. ]

2.  在views.py文件创建对应方法

  1. from django.shortcuts import render,HttpResponse
  2. LIST=[]
  3. for i in range(109):
  4. LIST.append(i)
  5. def user_list(request):
  6. return render(request,'userlist.html',{'li':LIST})

3. 在templates目录下的userlist.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <ul>
  9. {% for item in li %}
  10. <li>{{ item }}</li>
  11. {% endfor %}
  12. </ul>
  13. </body>
  14. </html>

运行程序并访问http://127.0.0.1:8000/userlist/,我们会发现该页面直接显示所有数据;

4.2.2 实现简单分页

我们可以考虑在url后带上参数表名用户访问的是第几页,从而返回数据;

views.py文件更改:

  1. def userlist(request):
  2. current_page = request.GET.get('p',1)
  3. current_page = int(current_page)
  4. start = (current_page-1)*10
  5. end = current_page*10
  6. data = LIST[start:end]
  7. return render(request,'userlist.html',{'li':data})

重新运行程序后访问http://127.0.0.1:8000/userlist/?p=2,我们就可以看到第二页的数据了

4.2.3 简单优化

上面虽然可以实现简单分页,但是考虑到用户体验,肯定不能让用户如此访问,我们需要简单优化下:

html文件更改:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <ul>
  9. {% for item in li %}
  10. <li>{{ item }}</li>
  11. {% endfor %}
  12. </ul>
  13. <div>
  14. <a href="user_list/?p=1">1</a>
  15. <a href="user_list/?p=2">2</a>
  16. <a href="user_list/?p=3">3</a>
  17. </div>
  18. </body>
  19. </html>

重新运行程序后访问http://127.0.0.1:8000/userlist/,点击页面的1、2即可实现简单翻页功能;

4.2.4 最终分页实现

现在新的分页需求下来了:

1)每页10条;

2)停留在第一页的时候,上一页不可点击;停留在末页的时候,下一页不可点击;

3)当前页面被默认选中且颜色高亮显示;

4)只显示当前页、前3个页码和后3个页码;

头疼Ing,继续苦逼的写代码吧!

app的同级目录下新建utils目录,目录下新建pagination.py文件,文件内容如下:

  1. 1 from django.utils.safestring import mark_safe
  2. 2 class Page:
  3. 3 def __init__(self,current_page,data_count,per_page_count=10,pager_num=7):
  4. 4 self.current_page = current_page
  5. 5 self.data_count = data_count
  6. 6 self.per_page_count = per_page_count
  7. 7 self.pager_num = pager_num
  8. 8 @property
  9. 9 def start(self):
  10. 10 return (self.current_page-1) * self.per_page_count
  11. 11 @property
  12. 12 def end(self):
  13. 13 return self.current_page * self.per_page_count
  14. 14 @property
  15. 15 def total_count(self):
  16. 16 v,y = divmod(self.data_count, self.per_page_count)
  17. 17 if y:
  18. 18 v += 1
  19. 19 return v
  20. 20 def page_str(self, base_url):
  21. 21 page_list = []
  22. 22 if self.total_count < self.pager_num:
  23. 23 start_index = 1
  24. 24 end_index = self.total_count + 1
  25. 25 else:
  26. 26 if self.current_page <= (self.pager_num+1)/2:
  27. 27 start_index = 1
  28. 28 end_index = self.pager_num + 1
  29. 29 else:
  30. 30 start_index = self.current_page - (self.pager_num-1)/2
  31. 31 end_index = self.current_page + (self.pager_num+1)/2
  32. 32 if (self.current_page + (self.pager_num-1)/2) > self.total_count:
  33. 33 end_index = self.total_count + 1
  34. 34 start_index = self.total_count - self.pager_num + 1
  35. 35 if self.current_page == 1:
  36. 36 prev = '<a class="page" href="javascript:void(0);">上一页</a>'
  37. 37 else:
  38. 38 prev = '<a class="page" href="%s?p=%s">上一页</a>' %(base_url,self.current_page-1,)
  39. 39 page_list.append(prev)
  40. 40 for i in range(int(start_index),int(end_index)):
  41. 41 if i ==self.current_page:
  42. 42 temp = '<a class="page active" href="%s?p=%s">%s</a>' %(base_url,i,i)
  43. 43 else:
  44. 44 temp = '<a class="page" href="%s?p=%s">%s</a>' %(base_url,i,i)
  45. 45 page_list.append(temp)
  46. 46 if self.current_page == self.total_count:
  47. 47 nex = '<a class="page" href="javascript:void(0);">下一页</a>'
  48. 48 else:
  49. 49 nex = '<a class="page" href="%s?p=%s">下一页</a>' %(base_url,self.current_page+1,)
  50. 50 page_list.append(nex)
  51. 51 jump = """
  52. 52 <input type='text' /><a onclick='jumpTo(this, "%s?p=");'>GO</a>
  53. 53 <script>
  54. 54 function jumpTo(ths,base){
  55. 55 var val = ths.previousSibling.value;
  56. 56 location.href = base + val;
  57. 57 }
  58. 58 </script>
  59. 59 """ %(base_url,)
  60. 60 page_list.append(jump)
  61. 61 page_str = mark_safe("".join(page_list))
  62. 62 return page_str
  63. 63
  64. 64 pagination.py

pagination.py

views文件内容如下:

  1. from django.shortcuts import render,HttpResponse
  2. from utils import pagination
  3. LIST=[]
  4. for i in range(109):
  5. LIST.append(i)
  6. def user_list(request):
  7. current_page = request.GET.get('p',1)
  8. current_page = int(current_page)
  9. page_obj = pagination.Page(current_page,len(LIST))
  10. data = LIST[page_obj.start:page_obj.end]
  11. page_str = page_obj.page_str("/userlist/")
  12. return render(request,'userlist.html',{'li':data,'page_str':page_str})

templates文件下的userlist.html文件内容如下:

  1. 1 <!DOCTYPE html>
  2. 2 <html lang="en">
  3. 3 <head>
  4. 4 <meta charset="UTF-8">
  5. 5 <title>Title</title>
  6. 6 <style>
  7. 7 .pagination .page{
  8. 8 display: inline-block;
  9. 9 padding: 5px;
  10. 10 background-color:darkmagenta;
  11. 11 margin: 5px;
  12. 12 }
  13. 13 .pagination .page.active{
  14. 14 background-color: red;
  15. 15 color:white;
  16. 16 }
  17. 17 </style>
  18. 18 </head>
  19. 19 <body>
  20. 20 <ul>
  21. 21 {% for item in li %}
  22. 22 <li>{{ item }}</li>
  23. 23 {% endfor %}
  24. 24 </ul>
  25. 25 <div class="pagination">
  26. 26 {{ page_str }}
  27. 27 </div>
  28. 28 </body>
  29. 29 </html>
  30. 30
  31. 31 userlist.html

userlist.html

运行程序,访问http://127.0.0.1:8000/user_list;

总结,分页时需要做三件事:

  • 创建处理分页数据的类
  • 根据分页数据获取数据
  • 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]

5. cookie

会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。

5.1 cookie机制

在程序中,会话跟踪是很重要的事情。理论上,一个用户的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆。例如,用户A在超市购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,这都是属于同一个会话的,不能放入用户B或用户C的购物车内,这不属于同一个会话。

而Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。即用户A购买了一件商品放入购物车内,当再次购买商品时服务器已经无法判断该购买行为是属于用户A的会话还是用户B的会话了。要跟踪该会话,必须引入一种机制。

Cookie就是这样的一种机制。它可以弥补HTTP协议无状态的不足。在Session出现之前,基本上所有的网站都采用Cookie来跟踪会话。

5.2 什么是cookie?

Cookie意为“甜饼”,是由W3C组织提出,最早由Netscape社区发展的一种机制。目前Cookie已经成为标准,所有的主流浏览器如IE、Netscape、Firefox、Opera等都支持Cookie。

由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理

Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。

注意:Cookie功能需要浏览器的支持。

如果浏览器不支持Cookie(如大部分手机中的浏览器)或者把Cookie禁用了,Cookie功能就会失效。

5.3 获取cookie

  1. request.COOKIES['key']
  2. request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
  3. 参数:
  4. default: 默认值
  5. salt: 加密盐
  6. max_age: 后台控制过期时间

5.4 设置cookie

  1. rep = HttpResponse(...) rep render(request, ...)
  2.  
  3. rep.set_cookie(key,value,...)
  4. rep.set_signed_cookie(key,value,salt='加密盐',...)
  5. 参数:
  6. key,
  7. value='',
  8. max_age=None, 超时时间
  9. expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
  10. path='/', Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
  11. domain=None, Cookie生效的域名
  12. secure=False, https传输
  13. httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。

  1. <script src='/static/js/jquery.cookie.js'></script>
  2. $.cookie("list_pager_num", 30,{ path: '/' });

5.5 基于cookie实现用户登录

主程序urls文件:

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

app目录下的views文件:

  1. 1 from django.shortcuts import render, HttpResponse,redirect
  2. 2 user_info = {
  3. 3 'cc': {'pwd': "123123"},
  4. 4 'root': {'pwd': "111111"},
  5. 5 }
  6. 6 def login(request):
  7. 7 if request.method == "GET":
  8. 8 return render(request,'login.html')
  9. 9 if request.method == "POST":
  10. 10 u = request.POST.get('username')
  11. 11 p = request.POST.get('pwd')
  12. 12 dic = user_info.get(u)
  13. 13 if not dic:
  14. 14 return render(request,'login.html')
  15. 15 if dic['pwd'] == p:
  16. 16 res = redirect('/index/')
  17. 17 res.set_cookie('uname',u)
  18. 18 res.set_cookie('user_type',"asdfjalskdjf",httponly=True)
  19. 19 return res
  20. 20 else:
  21. 21 return render(request,'login.html')
  22. 22 def index(reqeust):
  23. 23 # 获取当前已经登录的用户
  24. 24 v = reqeust.COOKIES.get('uname')
  25. 25 if not v:
  26. 26 return redirect('/login/')
  27. 27 return render(reqeust,'index.html',{'current_user': v})

views

app目录下的templates下新建login.html文件:

  1. 1 <!DOCTYPE html>
  2. 2 <html lang="en">
  3. 3 <head>
  4. 4 <meta charset="UTF-8">
  5. 5 <title></title>
  6. 6 </head>
  7. 7 <body>
  8. 8 <form action="/login/" method="POST">
  9. 9 <input type="text" name="username" placeholder="用户名" />
  10. 10 <input type="password" name="pwd" placeholder="密码" />
  11. 11 <input type="submit" />
  12. 12 </form>
  13. 13 </body>
  14. 14 </html>
  15. 15
  16. 16 login.html

login.html

新建index文件:

  1. 1 <!DOCTYPE html>
  2. 2 <html lang="en">
  3. 3 <head>
  4. 4 <meta charset="UTF-8">
  5. 5 <title></title>
  6. 6 </head>
  7. 7 <body>
  8. 8 <h1>欢迎登录:{{ current_user }}</h1>
  9. 9 </body>
  10. 10 </html>
  11. 11
  12. 12 index.html

index.html

运行程序并访问http://127.0.0.1:8000/login,输入用户名cc,密码123123,显示欢迎页面

5.6 基于cookie实现定制显示数据条数

pass

5.7 CBV和FBV用户认证装饰器

FBV:

views文件

  1. def auth(func):
  2. def inner(reqeust,*args,**kwargs):
  3. v = reqeust.COOKIES.get('uname')
  4. if not v:
  5. return redirect('/login/')
  6. return func(reqeust, *args,**kwargs)
  7. return inner
  8.  
  9. @auth
  10. def index(reqeust):
  11. # 获取当前已经登录的用户
  12. v = reqeust.COOKIES.get('uname')
  13. return render(reqeust,'index.html',{'current_user': v})

CBV:

主程序urls文件:

  1. from django.conf.urls import url,include
  2. from django.contrib import admin
  3. from app01 import views
  4. urlpatterns = [
  5. url(r'^login/', views.login),
  6. url(r'^index/', views.index),
  7. url(r'^order/', views.Order.as_view()),
  8. ]

app下的views文件:

  1. from django.shortcuts import render, HttpResponse,redirect
  2. from django import views
  3. from django.utils.decorators import method_decorator
  4.  
  5. @method_decorator(auth,name='dispatch')
  6. class Order(views.View):
  7. @method_decorator(auth)
  8. def dispatch(self, request, *args, **kwargs):
  9. return super(Order,self).dispatch(request, *args, **kwargs)
  10. @method_decorator(auth)
  11. def get(self,reqeust):
  12. v = reqeust.COOKIES.get('uname')
  13. return render(reqeust,'index.html',{'current_user': v})
  14. @method_decorator(auth)
  15. def post(self,reqeust):
  16. v = reqeust.COOKIES.get('uname')
  17. return render(reqeust,'index.html',{'current_user': v})

  

web前端基础知识 - Django进阶的更多相关文章

  1. web前端基础知识- Django基础

    上面我们已经知道Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Sessi ...

  2. web前端基础知识及快速入门指南

    web前端基础知识及快速入门指南 做前端开发有几个月了,虽然说是几个月,但是中间断断续续的上课.考试以及其它杂七杂八的事情,到现在居然一直感觉自己虽然很多前端的知识很眼熟,却也感觉自己貌似也知识在门口 ...

  3. web前端基础知识学习网站推介

    内容:一.基础知识及学习资料1. HTML入门学习:http://www.w3school.com.cn/html/index.aspHTML5 入门学习:http://www.w3school.co ...

  4. web前端基础知识总结

    上个寒假总结的web前端的一些知识点给大家分享一下 1.<html>和</html> 标签限定了文档的开始和结束点. 属性: (1)  dir: 文本的显示方向,默认是从左向右 ...

  5. web前端基础知识-(七)Django进阶

    通过上节课的学习,我们已经对Django有了简单的了解,现在来深入了解下~ 1. 路由系统 1.1 单一路由对应 url(r'^index$', views.index), 1.2 基于正则的路由 u ...

  6. web前端基础知识-(八)Django进阶之数据库对象关系映射

    Django ORM基本配置 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去 ...

  7. web前端基础知识-(六)Django基础

    上面我们已经知道Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Sessi ...

  8. web前端基础知识-(八)Ajax

    Ajax即"Asynchronous Javascript And XML"(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术,AJAX = 异步 Ja ...

  9. web前端基础知识

    #HTML    什么是HTML,和他ML...    网页可以比作一个装修好了的,可以娶媳妇的房子.    房子分为:毛坯房,精装修    毛坯房的修建: 砖,瓦,水泥,石头,石子....    精 ...

随机推荐

  1. 2016 ACM/ICPC Asia Regional Dalian Online(更新到五道题)

    1006 Football Games 这道题输入也很阴险!!! 这道题过题姿势最优雅的,不是if else if else if.那样很容易wa的. 如果没有平手选项, 赢得加一分的话, 可以用La ...

  2. BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树

    [题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...

  3. Hdu 3564 Another LIS 线段树+LIS

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...

  4. Python入门练习

    0.基本知识 Number.String.Lists 1.if判断的使用       

  5. Web服务器基础学习

    1)Socket通信相当于两个人通过电话联系,Http协议相当于电话联系时所使用的中文2)Http1.1前均为短连接,1.1版本为长连接,即服务器接收一次请求并发送响应后会等待一段时间看浏览器是否在这 ...

  6. Hibernate学习笔记5

    hql语句的查询(hibernate query language) hql和sql语句的区别sql:语言关系型数据库里面的通用查询,结构化查询语言,查看的是表以及表的列hql是hibernate中独 ...

  7. bigint数据类型

    尽管int依然是SQL Server 2000中最主要的整数数据类型,但是SQL Server 2000还是新增加了整数数据类型bigint,它应用于整数超过int数据范围的场合. int数据类型所表 ...

  8. [转]Flash Player、AIR、Flex SDK 大全

    平时不断看到有朋友在各种论坛.空间.知道.群里求 Flash 平台各种版本的运行时(Flash Player)和SDK(Flex.AIR).今天就看到不下10次!所以决定把 Macromedia.Ad ...

  9. javascript面向对象(二):构造函数的继承

    本文来自阮一峰 这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例. 今天要介绍的是,对象之间的"继承"的五种方法. 比如,现在有 ...

  10. oracle[insert 时报错: 单行子查询返回多行]

    -- 错误的写法 insert into t_b_partner_vehicle(id, partner_id, vehicle_id) (seq_t_b_partner_vehicle.nextva ...