一、Web框架概述 

Web框架本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. # _author_soloLi
  4.  
  5. import socket
  6.  
  7. def handle_request(client):
  8. buf = client.recv(1024)
  9. client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf-8"))
  10. client.send("Hello, solo".encode("utf-8"))
  11.  
  12. def main():
  13. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  14. sock.bind(('localhost', 8000))
  15. sock.listen(5)
  16. while True:
  17. connection, address = sock.accept()
  18. handle_request(connection)
  19. connection.close()
  20.  
  21. if __name__ == '__main__':
  22. main()
  23. #执行上面程序,直接用浏览器访问http://127.0.0.1:8000/就能显示发送的信息: Hello, solo

开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。
①服务器程序:负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。
②应用程序:负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。
  不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器;WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的服务器程序和应用程序之间接口格式,实现服务器程序和应用程序间的解耦。

wsgiref:python标准库提供的独立WSGI服务器

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. # _author_soloLi
  4.  
  5. from wsgiref.simple_server import make_server
  6.  
  7. def RunServer(environ, start_response):
  8. start_response('200 OK', [('Content-Type', 'text/html')])
  9. return ['Hello, solo'.encode("utf-8"),]
  10.  
  11. if __name__ == '__main__':
  12. httpd = make_server('', 8000, RunServer)
  13. print("Serving HTTP on port 8000...")
  14. httpd.serve_forever()

<1>自定义Web框架 (通过python标准库提供的wsgiref模块)

1.简单框架

  1. #!/usr/bin/env python
  2. # -*- coding:utf-8 -*-
  3. # _author_soloLi
  4. from wsgiref.simple_server import make_server
  5.  
  6. def handel_index():
  7. return ['<h1>Hello, index!</h1>'.encode("utf-8"), ]
  8.  
  9. def handel_data():
  10. return ['<h1>Hello, data!</h1>'.encode("utf-8"), ]
  11.  
  12. URL_DICT={
  13. '/index':handel_index,
  14. '/data':handel_data,
  15. }
  16.  
  17. def RunServer(environ, start_response):
  18. start_response('200 OK', [('Content-Type', 'text/html')]) #start_response 封装返回给用户的数据
  19. current_url = environ['PATH_INFO'] #environ 客户发来的数据
  20. func = None
  21. if current_url in URL_DICT:
  22. func = URL_DICT[current_url]
  23. if func:
  24. return func()
  25. else:
  26. return ['<h1>Error 404</h1>'.encode("utf-8"), ]
  27.  
  28. if __name__ == '__main__':
  29. httpd = make_server('', 8000, RunServer)
  30. print("Serving HTTP on port 8000...")
  31. httpd.serve_forever()

2.模板引擎

在上一步骤中,对于所有的login、index均返回给用户浏览器一个简单的字符串,在现实的Web请求中一般会返回一个复杂的符合HTML规则的字符串,所以我们一般将要返回给用户的HTML写在指定文件中,然后再返回。

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. </head>
  7. <body>
  8. <form>
  9. <input type="text" />
  10. <input type="text" />
  11. <input type="submit" />
  12. </form>
  13. </body>
  14. </html>

data.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head lang="en">
  4. <meta charset="UTF-8">
  5. <title></title>
  6. </head>
  7. <body>
  8. <h1>Index</h1>
  9. </body>
  10. </html>

index.html

  1. from wsgiref.simple_server import make_server
  2.  
  3. def handel_index():
  4. f = open('index.html','rb')
  5. data = f.read()
  6. return [data,]
  7. # return ['<h1>Hello, index!</h1>'.encode("utf-8"), ]
  8.  
  9. def handel_data():
  10. f = open('data.html','rb')
  11. data = f.read()
  12. return [data,]
  13. # return ['<h1>Hello, data!</h1>'.encode("utf-8"), ]
  14.  
  15. URL_DICT={
  16. '/index':handel_index,
  17. '/data':handel_data,
  18. }
  19.  
  20. def RunServer(environ, start_response):
  21. start_response('200 OK', [('Content-Type', 'text/html')]) #start_response 封装返回给用户的数据
  22. current_url = environ['PATH_INFO'] #environ 客户发来的数据
  23. func = None
  24. if current_url in URL_DICT:
  25. func = URL_DICT[current_url]
  26. if func:
  27. return func()
  28. else:
  29. return ['<h1>Error 404</h1>'.encode("utf-8"), ]
  30.  
  31. if __name__ == '__main__':
  32. httpd = make_server('', 8000, RunServer)
  33. print("Serving HTTP on port 8000...")
  34. httpd.serve_forever()

3.返回动态页面数据
对于上述代码,虽然可以返回给用户HTML的内容以现实复杂的页面,但是还是存在问题:如何给用户返回动态内容?
  ①自定义一套特殊的语法,进行替换
  ②使用开源工具jinja2,遵循其指定语法

  1. from wsgiref.simple_server import make_server
  2.  
  3. def handel_index():
  4. f = open('index.html','rb')
  5. data = f.read()
  6. data = data.replace(b'Index',"小祥祥吃骨头".encode("utf-8"))
  7. return [data,]
  8. # return ['<h1>Hello, index!</h1>'.encode("utf-8"), ]
  9.  
  10. def handel_data():
  11. f = open('data.html','rb')
  12. data = f.read()
  13. return [data,]
  14. # return ['<h1>Hello, data!</h1>'.encode("utf-8"), ]
  15.  
  16. URL_DICT={
  17. '/index':handel_index,
  18. '/data':handel_data,
  19. }
  20.  
  21. def RunServer(environ, start_response):
  22. start_response('200 OK', [('Content-Type', 'text/html')]) #start_response 封装返回给用户的数据
  23. current_url = environ['PATH_INFO'] #environ 客户发来的数据
  24. func = None
  25. if current_url in URL_DICT:
  26. func = URL_DICT[current_url]
  27. if func:
  28. return func()
  29. else:
  30. return ['<h1>Error 404</h1>'.encode("utf-8"), ]
  31.  
  32. if __name__ == '__main__':
  33. httpd = make_server('', 8000, RunServer)
  34. print("Serving HTTP on port 8000...")
  35. httpd.serve_forever()

<2>MVC/MTV

MVC
        Model       View            Controller
        数据库     模板文件       业务处理
MTV
       Model      Template           View
       数据库     模板文件        业务处理

django采用的是MTV模式。

 二、Django概述 

<0>Django生命周期

Django大致工作流程:
  ① 客户端发送请求(get/post)经过web服务器、Django中间件、 到达路由分配系统
  ② 路由分配系统根据提取 request中携带的的url路径(path)与视图函数映射关系列表中,匹配到1个视图函数,foo(request)执行;
  ③ 视图函数 使用原生SQL或者ORM去数据库拿到数据,在服务端进行渲染(模板+数据渲染)
  ④ 视图函数return一个 response对象 返回客户端

<1>Django基本配置

Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。

0、Django安装(略,自己百度去。。。)

1、创建Django工程

  1. django-admin startproject 工程名
  2. #django-admin startproject mysite # 终端上直接输入,创建sitename项目名
  3. mysite目录结构:
  4. - mysite # 对整个程序进行配置
  5. - init
  6. - settings # 配置文件
  7. - urls # URL对应关系
  8. - wsgi # 遵循WSIG规范;Django里面没封装socket,当进行socket数据交互时要用到wsgi,一般用第三方模块uwsgi+nginx
  9. - manage.py # 管理Django程序:

2、创建APP

  1. cd 工程名
  2. python manage.py startapp 应用名
  3. #python manage.py startapp cmdb
  4. # 目录结构
  5. - cmdb
  6. - migrations   #数据库操作记录(只是修改表结构的记录)
  7. - init       #表示python数据包(python3中有无均可)
  8. - admin      #Django为我们提供的后台管理
  9. - apps       #配置当前app
  10. - models      #创建数据库表结构,写指定的类,通过命令可以创建数据库结构
  11. - tests      #单元测试
  12. - views      #写业务逻辑代码,最重要的就是这个文件了

3、配置数据库(暂时默认不修改)

  1. DATABASES = {
  2. 'default': {
  3. 'ENGINE': 'django.db.backends.mysql',
  4. 'NAME':'dbname',
  5. 'USER': 'root',
  6. 'PASSWORD': 'xxx',
  7. 'HOST': '',
  8. 'PORT': '',
  9. }
  10. }
  11. # 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
  12. # 如下设置放置的与project同名的配置的 __init__.py文件中
  13. import pymysql
  14. pymysql.install_as_MySQLdb() 

4、配置静态文件

  1. #①创建static目录:放置css、js样式文件
  2.  
  3. #②settings.py
  4. STATICFILES_DIRS = (
  5. os.path.join(BASE_DIR, 'static'),
  6. )
  7.  
  8. #③templates目录下的xx.html(可以使用static目录里面的css、js样式)
  9. <link rel="stylesheet" href="/static/commons.css" />

5、配置模板路径

  1. #settings.py
  2. 'DIRS': [os.path.join(BASE_DIR, 'templates')],

6、注释 csrf(暂时)

  1. #settings.py
  2. MIDDLEWARE = [
  3. #'django.middleware.csrf.CsrfViewMiddleware',
  4. ]

7、定义路由规则(#url)

  1. #url.py
  2. #"login" --> 函数名 (暂时记一种)
  3. urlpatterns = [
  4. url(r'^login', views.login),
  5. ]

8、定义视图函数(#view)

  1. #app下views.py
  2. def func(request): # request 包含了用户提交的所有信息
  3. # request.method GET / POST
  4.  
  5. # http://127.0.0.1:8009/home?nid=123&name=alex
  6. # request.GET.get('',None) # 获取请求发来的而数据
  7. # request.POST.get('',None)
  8.  
  9. # return HttpResponse("字符串")
  10. # return render(request, "HTML模板的路径")
  11. # return redirect('/只能填URL')

 三、路由分配系统(URL) 

定义:project目录中的urls.py文件中, 以一个url()实例的列表urlpatterns,记录了可以访问到该站点的url 和 视图函数一一对应关系
作用:当request请求到达路由系统,Django通过request中携带的path 遍历这个关系表,匹配到对应的视图函数,break;(所以1个 url 只能从路由关系表中自上而下匹配到1个视图函数)
方式:①通过get请求携带参数的方式向server端传数据; https://i.cnblogs.com/%EF%BC%9Fid=1&name=solo
          ②通过path路径的方式向server端传值(以下主要介绍②);
注意事项:按位置、按关键字,路由系统只能用1种,不能混合使用;

1、单一路由对应
 ① url(r'^index/', views.index), url(r'^域名',对应的处理函数) 注意不要忘了写 ^ 表示正则匹配以。。开头的URL

  1. #编写URLconf的注意:
  2. #若要从url中捕获一个值,需要在它周围设置一对圆括号
  3. #不需要添加一个前导的反斜杠,如应该写作'test/',而不应该写作'/test/'
  4. #每个正则表达式前面的r表示字符串不转义
  5. #请求的url被看做是一个普通的python字符串,进行匹配时不包括get或post请求的参数及域名

2、基于正则的路由(未分组)
 ② url(r'^detail-(\d+).html/', views.detail),     #通过位置参数传递给视图

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. {% for k,item in user_dict.items %}
  9. <li><a target="_blank" href="/detail-{{ k }}.html">{{ item.name}}</a></li>
  10. {% endfor %}
  11.  
  12. </body>
  13. </html>

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <h2>详细信息</h2>
  9. <h4>用户名:{{ detail_info.name }}</h4>
  10. <h4>邮箱:{{ detail_info.email }}</h4>
  11. </body>
  12. </html>

detail.html

  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. ]

urls.py

  1. USER_DICT = {
  2. '':{'name':'root1','email':'root@live.com'},
  3. '':{'name':'root2','email':'root@live.com'},
  4. '':{'name':'root3','email':'root@live.com'},
  5. '':{'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})

views.py

3、基于正则的路由(分组)
 ③ url(r'^detail-(\d+)-(\d+).html', views.detail),     #严格按照分组顺序传参数,一个出错,所有的都跟着出错
 ④ url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html/', views.detail)   #可以不按照顺序传参数
#参数匹配规则:优先使用命名参数,如果没有命名参数则使用位置参数
#每个捕获的参数都作为一个普通的python字符串传递给视图
#性能:urlpatterns中的每个正则表达式在第一次访问它们时被编译,这使得系统相当快

  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. ]

urls.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})

views.py

  1. 2url(r'^detail-(\d+).html', views.detail),
  2. 3url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail)
  3.  
  4. PS:
  5. def detail(request, *args,**kwargs):
  6. pass
  7.  
  8. 实战:
  9. a.
  10. #③ url(r'^detail-(\d+)-(\d+).html', views.detail),
  11.  
  12. def func(request, nid, uid):
  13.  
  14. pass
  15.  
  16. def func(request, *args):
  17. args = (2,9)
  18.  
  19. def func(request, *args, **kwargs):
  20. args = (2,9)
  21.  
  22. b.
  23. #④ url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail)
  24.  
  25. def func(request, nid, uid):
  26. pass
  27.  
  28. def funct(request, **kwargs):
  29. kwargs = {'nid': 1, 'uid': 3}
  30.  
  31. def func(request, *args, **kwargs):
  32. args = (2,9)

总结

4、为路由映射设置名称
对URL路由关系进行命名, ***** 以后可以根据此名称生成自己想要的URL *****
设置名称之后,可以在不同的地方调用,如:
  --模板中使用生成URL {% url 'i2' 2012 %}
  --函数中使用生成URL reverse('i2', args=(2012,)) 路径:django.urls.reverse
  --Model中使用获取URL 自定义get_absolute_url() 方法

  1. class NewType(models.Model):
  2. caption = models.CharField(max_length=16)
  3.  
  4. def get_absolute_url(self):
  5. """
  6. 为每个对象生成一个URL
  7. 应用:在对象列表中生成查看详细的URL,使用此方法即可!!!
  8. :return:
  9. """
  10. # return '/%s/%s' % (self._meta.db_table, self.id)
  11. # 或
  12. from django.urls import reverse
  13. return reverse('NewType.Detail', kwargs={'nid': self.id})
  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>

index.html

  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
  9. ]

urls.py

  1. def index(request,*args,**kwargs):
  2. return render(request,"index.html")

views.py

  1. URL路由关系进行命名, ***** 以后可以根据此名称生成自己想要的URL *****
  2.  
  3. #settings.py
  4. url(r'^asdfasdfasdf/', views.index, name='i1'),
  5. url(r'^yug/(\d+)/(\d+)/', views.index, name='i2'),
  6. url(r'^buy/(?P<pid>\d+)/(?P<nid>\d+)/', views.index, name='i3'),
  7.  
  8. #views.py
  9. def func(request, *args, **kwargs):
  10. from django.urls import reverse
  11.  
  12. url1 = reverse('i1') # url1=asdfasdfasdf/
  13. url2 = reverse('i2', args=(1,2,)) # url2=yug/1/2/
  14. url3 = reverse('i3', kwargs={'pid': 1, "nid": 9}) # url3=buy/1/9/
  15.  
  16. #xxx.html
  17. {% url "i1" %} # --> asdfasdfasdf/
  18. {% url "i2" 1 2 %} # --> yug/1/2/
  19. {% url "i3" pid=1 nid=9 %} # --> buy/1/9/
  20.  
  21. 注:
  22. # 当前的URL
  23. request.path_info

总结

5、request.path_info:获取客户端当前的访问链接
     request.path:获取当前客户端的访问路径

  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>

index.html

  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. ]

urls.py

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

views.py

6、路由分发(多级路由)

include()
#使用include可以去除urlconf的冗余
#匹配过程:先与主URLconf匹配,成功后再用剩余的部分与应用中的URLconf匹配

  1. from django.conf.urls import url,include
  2. from django.contrib import admin
  3. from app01 import views
  4. urlpatterns = [
  5. url(r'^admin/', admin.site.urls),
  6. url(r'^cmdb/', include("app01.urls")), #调整到app01目录中的urls.py文件;注意include的是字符串形式的文件路径
  7. url(r'^monitor/', include("app02.urls")),
  8. url(r'^login', views.login),
  9. ]

#主程序下urls.py文件

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

#app01下的urls.py文件

  1. from django.shortcuts import HttpResponse
  2. from django.shortcuts import render
  3. from django.shortcuts import redirect
  4.  
  5. def login(request):
  6. # request 包含了用户提交的所有信息
  7. # print(request.method)
  8. error_msg=''
  9. if request.method == 'POST':
  10. user = request.POST.get('user',None)
  11. pwd = request.POST.get('pwd',None)
  12. if user == 'root' and pwd == '':
  13. #去跳转
  14. return redirect('http://www.baidu.com')
  15. else:
  16. error_msg = 'SB! it is wrong'
  17. return render(request,'login.html',{'error_msg':error_msg})

#app01下的views.py文件

  1. from django.shortcuts import render,HttpResponse
  2.  
  3. # Create your views here.
  4. def login(requst):
  5. return HttpResponse('app02 login')

#app02下的urls.py文件

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

#app02下的views.py文件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <link rel="stylesheet" href="/static/commons.css" />
  7. <style>
  8. label{
  9. width: 80px;
  10. text-align: right;
  11. display: inline-block;
  12. }
  13. </style>
  14. </head>
  15. <body>
  16. <form action="/login" method="post">
  17. <p>
  18. <label for="username">用户名:</label>
  19. <input id="username" name="user" type="text" />
  20. </p>
  21. <p>
  22. <label for="password">密码:</label>
  23. <input id="password" name="pwd" type="password" />
  24. <input type="submit" value="提交" />
  25. <span style="color: red;">{{ error_msg }}</span>
  26. </p>
  27. </form>
  28. <script src="/static/jquery.min.js"></script>
  29. </body>
  30. </html>

#login.html

7、默认值(添加额外的参数)

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

urls.py

  1. def index(request,name):
  2. print(name)
  3. return HttpResponse('OK')
  4.  
  5. #root

views.py

8、命名空间
在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。
配置url时为了解决url硬编码的问题,常常会使用命名空间来表示一个url。
命名空间:是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。#在include中通过namespace定义命名空间,用于反解析
#URL的反向解析
如果在视图、模板中使用硬编码的链接(href="/polls/{{ poll.id }}/"),在urlconf发生改变时,维护是一件非常麻烦的事情
解决:在做链接时,通过指向urlconf的名称,动态生成链接地址
视图:使用django.core.urlresolvers.reverse()函数
模板:使用url模板标签

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

#主程序urls.py文件

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

#cmdb下的urls.py文件

  1. from django.shortcuts import HttpResponse
  2. from django.shortcuts import reverse
  3.  
  4. def detail(request):
  5. url = reverse('author-polls:detail')
  6. print(url)
  7. return HttpResponse('OK')

#views.py

  1. {% url 'author-polls:detail' %}

#html模板中生成url(/a/index/ )

9、生成url路径(path_info+reverse)

  1. from.import models
  2. def article(request,*args,**kwargs):
  3.  
  4. # 第一种方式利用path_info,访问的url
  5. print(request.path_info)
  6. # /article/0-0.html/
  7.  
  8. # 第二种方式用reverse,自己生成
  9. # 需要配合urls.py文件 url(r'...',views.article ,name='article')
  10. from django.urls import reverse
  11. url = reverse('article',kwargs=kwargs)
  12. print(url)
  13. # /article/0-0.html/

四、视图函数 
定义:视图就是一个Python函数,被定义在views.py中。
配置:定义完成视图后,需要配置urlconf(正则表达式+视图)
作用:Django使用正则表达式匹配请求的URL,一旦匹配成功(只匹配路径部分,即除去域名、参数后的字符串),则调用相对应的视图。返回的响应可以是一张网页的HTML内容,一个重定向,一个404错误等等。

  1. 404 (page not found)
  2. defaults.page_not_found(request, template_name='404.html')
  3. 默认的404视图将传递一个变量给模板:request_path,它是导致错误的URL
  4. 如果Django在检测URLconf中的每个正则表达式后没有找到匹配的内容也将调用404视图
  5. 如果在settingsDEBUG设置为True,那么将永远不会调用404视图,而是显示URLconf 并带有一些调试信息
  6.  
  7. 500 (server error)
  8. defaults.server_error(request, template_name='500.html')
  9. 在视图代码中出现运行时错误
  10. 默认的500视图不会传递变量给500.html模板
  11. 如果在settingsDEBUG设置为True,那么将永远不会调用505视图,而是显示URLconf 并带有一些调试信息
  12.  
  13. 400 (bad request)
  14. defaults.bad_request(request, template_name='400.html')
  15. 错误来自客户端的操作
  16. 当用户进行的操作在安全方面可疑的时候,例如篡改会话cookie

#常见视图(404/500/400)

表单交互

1、获取表单提交类型做相应处理

#最终效果:当用户第一次访问时显示正常页面,输入用户名密码正确时调整到百度;错误时页面显示‘SB! it is wrong’

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <link rel="stylesheet" href="/static/commons.css" />
  7. <style>
  8. label{
  9. width: 80px;
  10. text-align: right;
  11. display: inline-block;
  12. }
  13. </style>
  14. </head>
  15. <body>
  16. <form action="/login" method="post">
  17. <p>
  18. <label for="username">用户名:</label>
  19. <input id="username" name="user" type="text" />
  20. </p>
  21. <p>
  22. <label for="password">密码:</label>
  23. <input id="password" name="pwd" type="password" />
  24. <input type="submit" value="提交" />
  25. <span style="color: red;">{{ error_msg }}</span>
  26. </p>
  27. </form>
  28. <script src="/static/jquery.min.js"></script>
  29. </body>
  30. </html>

login.html

  1. from django.shortcuts import HttpResponse
  2. from django.shortcuts import render
  3. from django.shortcuts import redirect
  4.  
  5. def login(request):
  6. # request 包含了用户提交的所有信息
  7. # print(request.method)
  8.  
  9. error_msg=''
  10. if request.method == 'POST':
  11. user = request.POST.get('user',None)
  12. pwd = request.POST.get('pwd',None)
  13. if user == 'root' and pwd == '':
  14. #去跳转
  15. return redirect('http://www.baidu.com')
  16. else:
  17. error_msg = 'SB! it is wrong'
  18.  
  19. return render(request,'login.html',{'error_msg':error_msg})

Views.py

  1. --commons.css
  2. --jquery_min.js

static目录

2、模拟数据库交互,循环列表渲染页面

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body style="margin: 0">
  8. <div style="height: 48px;background-color: #dddddd"></div>
  9. <div>
  10. <form action="/home" method="post">
  11. <input type="text" name="username" placeholder="用户名" />
  12. <input type="text" name="email" placeholder="邮箱"/>
  13. <input type="text" name="gender" placeholder="性别"/>
  14. <input type="submit" value="添加" />
  15. </form>
  16. </div>
  17. <div>
  18. <table>
  19. {% for row in user_list %}
  20. <tr>
  21. <td>{{ row.username }}</td>
  22. <td>{{ row.gender }}</td>
  23. <td>{{ row.email }}</td>
  24. </tr>
  25. {% endfor %}
  26.  
  27. </table>
  28. </div>
  29.  
  30. </body>
  31. </html>

home.html

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

urls.py

  1. from django.shortcuts import HttpResponse
  2. from django.shortcuts import render
  3. from django.shortcuts import redirect
  4.  
  5. USER_LIST = [
  6. {'id': 1, 'username': 'alex', 'email': '1109913149@qq.com', "gender": 'male'},
  7. {'id': 2, 'username': 'solo', 'email': '1109913149@qq.com', "gender": 'male'},
  8. {"id": 3,'username': 'seven', 'email': '1109913149@qq.com', "gender": 'male'},
  9. ]
  10.  
  11. def home(request):
  12. if request.method == "POST":
  13. # 获取用户提交的数据 POST请求中
  14. u = request.POST.get('username')
  15. e = request.POST.get('email')
  16. g = request.POST.get('gender')
  17. temp = {'username': u, 'email': e, "gender": g}
  18. USER_LIST.append(temp)
  19. return render(request, 'home.html', {'user_list': USER_LIST})

Views.py

3、表单交互,获取checkbox多个值

  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>

login.html

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

urls.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")

views.py

注:select多选时跟上面程序一样都用getlist进行获取

4、表单交互,上传文件file

  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>

login.html

  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")

views.py

Python学习笔记整理总结【Django】【MVC/MTV/路由分配系统(URL)/视图函数 (views)/表单交互】的更多相关文章

  1. python学习笔记整理——字典

    python学习笔记整理 数据结构--字典 无序的 {键:值} 对集合 用于查询的方法 len(d) Return the number of items in the dictionary d. 返 ...

  2. Python学习笔记整理总结【Django】:Form组件

     Form组件  Django的Form主要具有一下几大功能: --生成HTML标签 --验证用户数据(显示错误信息) --HTML Form提交保留上次提交数据 --初始化页面显示内容 1.内置字段 ...

  3. Python学习笔记整理总结【Django】:中间件、CSRF、缓存

     一.中间件  中间件是一类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法:在django项目的settings模块中,有一个 MIDDLEWARE 变量,其中每 ...

  4. Python学习笔记整理总结【Django】:Model操作(一)

    Model操作(一) 一.Django ORM基本配置 ORM:关系对象映射(Object Relational Mapping,简称ORM)db Frist:到目前为止,当我们的程序涉及到数据库相关 ...

  5. Python学习笔记整理总结【Django】Ajax

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

  6. Python学习笔记整理总结【Django】:模板语言、分页、Cookie、Session

    一.模板语言  1.在前段展示:对象/字典/元组 class Business(models.Model): # id #用默认的自增id列 即:Business中有3列数据(id, caption, ...

  7. python学习笔记整理——集合 set

    python学习整理笔记--集合 set 集合的用途:成员测试和消除重复的条目,进行集合运算 注意:花括号或set()函数可以用于创建集合. 注意:若要创建一个空的集合你必须使用set(),不能用{} ...

  8. python 学习笔记十五 django基础

    Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...

  9. python学习笔记整理——元组tuple

    Python 文档学习笔记2 数据结构--元组和序列 元组 元组在输出时总是有括号的 元组输入时可能没有括号 元组是不可变的 通过分拆(参阅本节后面的内容)或索引访问(如果是namedtuples,甚 ...

随机推荐

  1. Egret白鹭开发微信小游戏(使用皮肤搭建UI,代码调用组件功能)

    (1)新建皮肤,并命名如下 (2)根据实际情况自定义皮肤,例如: (3)修改名字为如下: (4)运行游戏会自动生成以下代码: (5)在default.thm.json中添加如下代码:(具体路径名字根据 ...

  2. unity编辑器扩展_08(创建自定义窗口)

    代码: using UnityEngine;using UnityEditor; public class MyWidow : EditorWindow{    [MenuItem("Win ...

  3. Java网络编程之URL和URI

    Java网络编程之URL与URI 一.URL与URI简介 URI = Universal Resource Identifier 统一资源标志符 URL = Universal Resource Lo ...

  4. Leetcode之深度优先搜索(DFS)专题-200. 岛屿数量(Number of Islands)

    Leetcode之深度优先搜索(DFS)专题-200. 岛屿数量(Number of Islands) 深度优先搜索的解题详细介绍,点击 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计 ...

  5. ZAO 换脸不安全?用 python 轻松实现 AI

    最近两天一款名为 「ZAO」 的 App 刷爆了朋友圈,它的主打功能是 AI 换脸,宣称「只需一张照片,就能出演天下好戏」 : 现实中不能实现当明星的梦,在这个 App 里你可以,想演谁演谁.新鲜.好 ...

  6. UML类图详解和示例

    ps:博客园markdown不能自动生成列表,更好的阅读体验可访问我的个人博客http://www.isspark.com/archives/UMLDescription UML类图概述 什么是UML ...

  7. ubuntu中rc.local不执行问题

    解决思路概括起来如下: 1.首先排除脚本自身问题,可以手动点杠执行下试试, 2.脚本确定没问题后,放到开机启动程序引用的路径下,办法如下 2.1.查看系统的运行级别 2.2.到对应运行的rcX.d的目 ...

  8. P2805 [NOI2009]植物大战僵尸 + 最大权闭合子图 X 拓扑排序

    传送门:https://www.luogu.org/problemnew/show/P2805 题意 有一个n * m的地图,你可以操纵僵尸从地图的右边向左边走,走的一些地方是有能量值的,有些地方会被 ...

  9. hdu 1269 迷宫城堡(trajan判环)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1269 题意:略 题解:trajan模版直接求强连通分量. #include <iostream& ...

  10. 模板汇总——AC自动机

    AC自动机 模板题 HDU-2222 Keywords Search #include<bits/stdc++.h> using namespace std; #define LL lon ...