Part17 - Django

本节内容

  1. Web框架本质
  2. Django 基础
  3. Django 进阶

1、Web框架本质

对于全部的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。
WEB框架本质是一个socket
#########WEB框架(代码文件结构)
MVC
    Model        View        Controller
    数据库       模板文件    业务处理

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

############## WEB:MVC、MTV

一、本质

import socket

#WEB框架本质-->socket

def handle_request(client):
    buf = client.recv(1024)
    client.send(b"HTTP/1.1 200 OK\r\n\r\n")
    client.send(b"Hello, Seven")


def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost', 8000))
    sock.listen(5)

    while True:
        connection, address = sock.accept()
        handle_request(connection)
        connection.close()

if __name__ == '__main__':
    main()

二、自定义Web框架

WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的web app与web server之间接口格式,实现web app与web server间的解耦。 Python标准库提供的独立WSGI服务器称为wsgiref(封装好的socket)。
经过Python标准库提供的wsgiref模块开发一个本身的Web框架。
 1 from wsgiref.simple_server import make_server  2 from Controller import accout  3 
 4 URL_DICT = {  5         '/index': accout.handle_index,  6         '/data': accout.handle_data,  7     } #能够作正则匹配,匹配一类的请求内容
 8 
 9 def RunServer(environ, start_response): 10     # environ 客户端发来的全部数据
11     # start_response 封装要返回给用户的数据,响应头状态
12     start_response('200 OK', [('Content-Type', 'text/html')]) 13     current_url = environ['PATH_INFO'] 14 
15     # 返回的内容
16     func = None 17     if current_url in URL_DICT: 18         func = URL_DICT[current_url] 19         if func: 20             return func() 21         else: 22             return ['<h1>404</h1>'.encode('utf-8'), ] 23     else: 24         return ['<h1>404</h1>'.encode('utf-8'), ] 25 
26     # if current_url == '/index':
27     # return handle_index()
28     # elif current_url == '/data':
29     # return handle_data()
30     # else:
31     # return ['<h1>404</h1>'.encode('utf-8'), ]
32 
33     # return ['<h1>Hello, web!</h1>'.encode('utf-8'),]
34 
35 if __name__ == '__main__': 36     httpd = make_server('', 8000, RunServer) 37     print("Serving HTTP on port 8000...") 38     httpd.serve_forever()
WSGI

2、Django基础

Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其余WEB框架其优点为:大而全,框架自己集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。
Django生存周期:

 1 Django:用Python开发Web站点提供最齐全的Web框架,基于MTV的框架  2 
 3 pip3 install django  4 
 5 
 6 C:\Python35\Scripts  7 
 8 1、建立Django工程(可使用Pycharm建立)  9     django-admin startproject 【工程名称】        --> 会在当前目录下生成Django工程目录  10     如:django-admin startproject mysite  11  默认建立以下内容  12  mysite  13             - mysite # 对整个程序进行配置  14                 - init  15                 - settings # 配置文件  16                 - url # URL对应关系  17                 - wsgi      # 遵循WSIG规范,uwsgi + nginx(Django内部没有包含socket)  18                 
 19             - manage.py # 管理Django程序:  20                 - python manage.py  21                 - python manage.py startapp xx  22                 - python manage.py makemigrations  23                 - python manage.py migrate  24 
 25  PS: WSGI (Web Server Gateway Interface)  26  是一种规范,它定义了使用python编写的web app与web server之间接口格式,实现web app与web server间的解耦。python标准库提供的独立WSGI服务器称为wsgiref。  27     
 28     
 29 2、运行Django功能(可以使用Pycharm运行,添加Djangoserver)  30     python manage.py runserver 127.0.0.1:8001
 31 
 32     ------------------
 33  chouti  34         - chouti  35             - 配置  36         - 主站 app  37         - 后台管理 app  38     ------------------
 39 
 40 
 41 3、建立app(进入Django工程根目录,执行以下命令)  42  python manage.py startapp cmdb  43  python manage.py startapp openstack  44  python manage.py startapp xxoo....  45     
 46  业务处理代码放入app中(views)  47  app:  48  migrations 修改表结构记录  49  admin Django为咱们提供的后台管理  50  apps 配置当前app  51  models ORM,写指定的类 经过命令能够建立数据库结构  52  tests 单元测试  53  views 业务代码  54 
 55 4、配置(project.settings.py)  56 
 57  a、配置模板的路径  58     
 59         TEMPLATES = [  60  {  61                     'BACKEND': 'django.template.backends.django.DjangoTemplates',  62                     
 63                     'DIRS': [os.path.join(BASE_DIR, 'templates')],  64                     
 65                     'APP_DIRS': True,  66                     'OPTIONS': {  67                         'context_processors': [  68                             'django.template.context_processors.debug',  69                             'django.template.context_processors.request',  70                             'django.contrib.auth.context_processors.auth',  71                             'django.contrib.messages.context_processors.messages',  72  ],  73  },  74  },  75  ]  76             
 77  b、配置静态目录(不要忘记逗号)  78         static        --> 静态文件目录名字使用static  79     
 80         STATICFILES_DIRS = (  81             os.path.join(BASE_DIR, 'static'),  82  )  83 
 84         <link rel="stylesheet" href="/static/commons.css" />
 85         
 86         
 87  c、CSRF verification failed. Request aborted 报错解决(settings文件内注释csrf)  88     
 89         MIDDLEWARE = [  90         'django.middleware.security.SecurityMiddleware',  91         'django.contrib.sessions.middleware.SessionMiddleware',  92         'django.middleware.common.CommonMiddleware',  93         #'django.middleware.csrf.CsrfViewMiddleware',  94         'django.contrib.auth.middleware.AuthenticationMiddleware',  95         'django.contrib.messages.middleware.MessageMiddleware',  96         'django.middleware.clickjacking.XFrameOptionsMiddleware',  97  ]  98         
 99 5、定义路由规则 100  url.py 101     
102         "login" --> 函数名 103         
104         
105 6、定义视图函数 106  app下views.py 107         
108  def func(request): 109             # request.method   GET / POST        -- 用户提交方式 110             
111             # http://127.0.0.1:8009/home?nid=123&name=alex
112             # request.GET.get('',None) # 获取请求发来的而数据 113             
114             # request.POST.get('',None) 115                             
116             # return HttpResponse("字符串")        -- 返回字符串 117             # return render(request, "HTML模板的路径")    -- 返回给用户模板 118             # return redirect('/只能填URL')        -- 跳转,只能填'/URL'
119             
120 7、模板渲染 121  特殊的模板语言 122     
123  a、{{ 变量名 }} 124         
125  视图函数: 126  def func(request): 127             return render(request, "index.html", {'current_user': "alex"}) 128 
129             
130  模板:index.html 131         -----------
132         <html>
133  .. 134             <body>
135                 <div>{{current_user}}</div>
136             </body>
137         
138         </html>
139         
140         ====> 最后生成的字符串 141         
142         <html>
143  .. 144             <body>
145                 <div>alex</div>
146             </body>
147         
148         </html>
149         ------------
150         
151  b、For循环 152  def func(request): 153             return render(request, "index.html", {'current_user': "alex", 'user_list': ['alex','eric']}) 154 
155             
156  index.html 157         ------------
158         <html>
159  .. 160             <body>
161                 <div>{{current_user}}</div>
162                 
163                 <ul>
164                     {% for row in user_list %} 165                     
166                         {% if row == "alex" %} 167                             <li>{{ row }}</li>
168                         {% endif %} 169                         
170                     {% endfor %} 171                 </ul>
172                 
173             </body>
174         
175         </html>
176         ------------
177         
178         
179  c、索引################# 180  def func(request): 181             return render(request, "index.html", { 182                         'current_user': "alex", 183                         'user_list': ['alex','eric'], 184                         'user_dict': {'k1': 'v1', 'k2': 'v2'}}) 185 
186             
187  index.html 188         
189         <html>
190  .. 191             <body>
192                 <div>{{current_user}}</div>
193                 
194                 <a> {{ user_list.1 }} </a> #模板语言中根据索引获取列表内容 195                 <a> {{ user_dict.k1 }} </a> #模板语言中根据索引获取字典内容 196                 <a> {{ user_dict.k2 }} </a>
197                 
198             </body>
199         
200         </html>
201     
202     
203  d、条件 ################### 204     
205  def func(request): 206             return render(request, "index.html", { 207                         'current_user': "alex", 208                         "age": 18, 209                         'user_list': ['alex','eric'], 210                         'user_dict': {'k1': 'v1', 'k2': 'v2'}}) 211 
212             
213  index.html 214         
215         <html>
216  .. 217             <body>
218                 <div>{{current_user}}</div>
219                 
220                 <a> {{ user_list.1 }} </a>
221                 <a> {{ user_dict.k1 }} </a>
222                 <a> {{ user_dict.k2 }} </a>
223                 
224                 {% if age %} 225                     <a>有年龄</a>
226                     {% if age > 16 %} 227                         <a>老男人</a>
228                     {% else %} 229                         <a>小鲜肉</a>
230                     {% endif %} 231                 {% else %} 232                     <a>无年龄</a>
233                 {% endif %} 234             </body>
235         
236         </html>
Django笔记

一、建立Django工程

可使用Django在命令行中建立工程,也可使用Pycharm建立(本质上自动执行了建立命令)
 1 django-admin startproject 【工程名称】  2 如:django-admin startproject mysite  3  默认建立以下内容  4  - mysite # 工程  5         - mysite # 对整个程序进行配置  6             - __init__.py  7             - settings.py # 配置文件  8             - urls.py # URL对应关系  9             - wsgi.py # 遵循WSIG规范,wsgi + nginx(Django内部没有包含socket) 10             
11         - manage.py # 管理Django程序: 12             - python manage.py 13             - python manage.py startapp xx 14             - python manage.py makemigrations 15             - python manage.py migrate 16 
17 PS: WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的web app与web server之间接口格式,实现web app与web server间的解耦。python标准库提供的独立WSGI服务器称为wsgiref。
View Code

二、运行Django功能

能够在命令行中启动,也可使用Pycharm建立Django server来运行(在Pycharm中建立的Django工程默认添加了Django server)
 1 python manage.py runserver 127.0.0.1:8001
 2 
 3 ------------------
 4 chouti  5     - chouti  6         - 配置  7     - 主站 app  8     - 后台管理 app  9 ------------------
10 
11 PS:Python和Django要加环境变量
在命令行中启动

三、建立app

进入Django工程根目录,执行以下命令
 1 python manage.py startapp cmdb  2 python manage.py startapp openstack  3 python manage.py startapp xxoo....  4 
 5 业务处理代码放入app中(views)  6 app:  7  migrations 修改表结构记录  8  admin Django为咱们提供的后台管理  9  apps 配置当前app 10  models ORM,写指定的类 经过命令能够建立数据库结构 11  tests 单元测试 12     views          业务代码
View Code

四、配置文件

""" Django settings for s14django project. Generated by 'django-admin startproject' using Django 1.10.4. For more information on this file, see https://docs.djangoproject.com/en/1.10/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.10/ref/settings/ """

import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'hut(bs^o50n^opj8yneen_sh)m0uvu#sdzr%&eq1x)5p*(tqcz'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True ALLOWED_HOSTS = [] # Application definition
 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'cmdb', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', #'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 's14django.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 's14django.wsgi.application'


# Database # https://docs.djangoproject.com/en/1.10/ref/settings/#databases
 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Password validation # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
 AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/1.10/topics/i18n/
 LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.10/howto/static-files/
 STATIC_URL = '/static/'

# 配置好static静态文件目录,不配置用户访问页面静态文件访问不到
STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), ) # APPEND_SLASH=True
settings.py
1) 配置HTML模板的路径
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
View Code
2) 配置静态目录
static        --> 静态文件目录名字使用static STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), ) <link rel="stylesheet" href="/static/commons.css" />
CSS、JS、图片等静态文件目录
3) CSRF verification failed. Request aborted 报错解决
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', #'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
settings内注释csrf
4) 数据库配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } }
默认sqllite
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'dbname', 'USER': 'root', 'PASSWORD': 'xxx', 'HOST': '', 'PORT': '', } } # 注意: # 因为Django内部链接MySQL时使用的是MySQLdb模块,而Python3中还无此模块,因此须要使用pymysql模块来代替。
  
# 在project下与其同名文件夹下的 __init__.py文件中作以下设置
  
import pymysql pymysql.install_as_MySQLdb()
MySQL配置

五、路由规则

定义url与业务处理函数(视图函数)之间的映射关系。
 1 URL拼接传递参数有两种方式:  2     - 在url后加"?key=value"拼接,能够在视图函数中经过get()获取,如:  3  html文件  4             <a class="detail" href="/index?nid=1">详细信息</a> #id是内置方法,尽可能不要使用id作参数  5         ---
 6  urls.py文件  7             url(r'^index/', views.index), #一个url对应函数  8             url(r'^home/', views.Home.as_view()), #一个url对应类,根据method经过反射来执行对应方法  9         
10             
11     - 在url后加"分隔符value"拼接,在urls.py中经过正则进行匹配(经常使用方法),如: 12  html文件 13             <a class="detail" href="/detail-2-9.html">详细信息</a>
14         ---    
15  urls.py文件 16             a、一类url对应函数,"正则匹配"的数据(\d+)交给视图函数(视图函数参数有位置要求) 17                 url(r'^detail-(\d+)-(\d+).html', views.detail), 18             
19                 def func(request, nid, uid):    #nid即正则匹配的数据(\d+) 20  pass 21                 def func(request, *args): 22                     args = (2,9) 23                 def func(request, *args, **kwargs): 24                     args = (2,9) 25                     
26                     
27             b、"正则匹配"的数据"分组"(?P<nid>\d+)交给视图函数(视图函数参数没有位置要求) 28                 url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail) 29                 
30  def func(request, nid, uid): 31  pass 32                     
33                 def funct(request, **kwargs): 34                     kwargs = {'nid': 1, 'uid': 3} 35                     
36                 def func(request, *args, **kwargs): 37                     args = (2,9) 38    
39    
40     - PS: 41         def detail(request, *args,**kwargs): 42             pass
路由系统笔记
 1 """s14django URL Configuration  2 
 3 The `urlpatterns` list routes URLs to views. For more information please see:  4  https://docs.djangoproject.com/en/1.10/topics/http/urls/  5 Examples:  6 Function views  7  1. Add an import: from my_app import views  8  2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')  9 Class-based views 10  1. Add an import: from other_app.views import Home 11  2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 Including another URLconf 13  1. Import the include() function: from django.conf.urls import url, include 14  2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) 15 """
16 from django.conf.urls import url 17 from django.contrib import admin 18 from cmdb import views 19 
20 urlpatterns = [ 21     url(r'^admin/', admin.site.urls), 22     # url(r'^h.html/', views.home),
23     url(r'^login', views.login), 24     url(r'^home', views.home), 25 ]
urls.py
1) 单一路由对应
from django.conf.urls import url urlpatterns = [ url(r'^index/', views.index),    #一个url对应函数
    url(r'^home/', views.Home.as_view()),    #一个url对应类,根据method经过反射来执行对应方法
]
urls.py
from django.views import View class Home(View): #方法名必须小写,支持的方法见源码
    def dispatch(self, request, *args, **kwargs): # 调用父类中的dispatch,至关于装饰器功能
        print('before') result = super(Home,self).dispatch(request, *args, **kwargs) print('after') return result def get(self,request): print(request.method) return render(request, 'home.html') def post(self,request): print(request.method,'POST') return render(request, 'home.html')
views.py(一个url对应一个类)
2) 基于正则的路由
 1 html文件  2     <a class="detail" href="/detail-2-9.html">详细信息</a>
 3 ---    
 4 urls.py文件  5     a、一类url对应函数,"正则匹配"的数据(\d+)交给视图函数(视图函数参数有位置要求)  6         url(r'^detail-(\d+)-(\d+).html', views.detail),  7     
 8         def func(request, nid, uid):    #nid即正则匹配的数据(\d+)  9  pass 10         def func(request, *args): 11             args = (2,9) 12         def func(request, *args, **kwargs): 13             args = (2,9) 14             
15             
16     b、"正则匹配"的数据"分组"(?P<nid>\d+)交给视图函数(视图函数参数没有位置要求) 17         url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail) 18         
19  def func(request, nid, uid): 20  pass 21             
22         def funct(request, **kwargs): 23             kwargs = {'nid': 1, 'uid': 3} 24             
25         def func(request, *args, **kwargs): 26             args = (2,9)
View Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style> body{ margin: 0;
        } .menu{ display: block; padding: 5px;

        }
    </style>
</head>
<body>
    <div style="height: 48px;background-color: black;color: white"> 红红火火哈哈 </div>
    <div>
        <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: brown;">
            <a class="menu" href="/cmdb/user_info/">用户管理</a>
            <a class="menu" href="/cmdb/user_group/">用户组管理</a>
        </div>
        <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto">
            <h3>添加用户</h3>
            <form method="POST" action="/cmdb/user_info/">
                <input type="text" name="user" />
                <input type="text" name="pwd" />
                <select name="group_id"> {% for item in group_list %} <option value="{{ item.uid }}">{{ item.caption }}</option> {% endfor %} </select>
                <input type="submit" value="添加"/>
            </form>
            <h3>用户列表</h3>
            <ul> {% for row in user_list %} <li>
                        <a href="/cmdb/userdetail-{{ row.id }}/">{{ row.username }}</a> | <span> {{ row.user_group.caption }} </span>
                        <a href="/cmdb/userdel-{{ row.id }}/">删除</a> | <a href="/cmdb/useredit-{{ row.id }}/">编辑</a>
                    </li> {% endfor %} </ul>
        </div>
    </div>
</body>
</html>
示例HTML
3) 多级路由(include),根据app对路由规则进行分类
#project/urls.py
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ url(r'^cmdb/', include("app01.urls")), url(r'^monitor/', include("app02.urls")), ] #app01/urls.py
from django.conf.urls import url,include from django.contrib import admin from app01 import views urlpatterns = [ url(r'^login/', views.login), ] #app02/urls.py
from django.conf.urls import url,include from django.contrib import admin from app02 import views urlpatterns = [ url(r'^login/', views.login), ]
View Code
4) 默认值

 

5) 命名空间

 

六、视图函数

处理用户请求函数,app目录下的views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body> {#上传文件form作处理enctype="multipart/form-data"#} <form action="/login/" method="POST" enctype="multipart/form-data">
        <p>
            <input type="text" name="user" placeholder="用户名" />
        </p>
        <p>
            <input type="password" name="pwd" placeholder="密码" />
        </p>
        <p> 男:<input type="radio" name="gender" value="1"/> 女:<input type="radio" name="gender" value="2"/>
        </p>
        <p> 男:<input type="checkbox" name="favor" value="11"/> 女:<input type="checkbox" name="favor" value="22"/>
        </p>
        <p>
            <select name="city" multiple>
                <option value="sh">上海</option>
                <option value="bj">北京</option>
                <option value="tj">天津</option>
            </select>
        </p>
        <p>
            <input type="file" name="fafafa"/>
        </p>

        <input type="submit" value="提交"/>
    </form>
</body>
</html>
示例HTML
1) 基本用法(一个url对应一个函数,一个url对应类的参照5-1)
 1 app下views.py  2     
 3  def func(request):  4         # request.method   GET / POST        -- 用户提交方式  5         
 6         # http://127.0.0.1:8009/home?nid=123&name=alex
 7         # request.GET.get('',None) # 获取请求发来的而数据  8         
 9         # request.POST.get('',None) 10                         
11         # return HttpResponse("字符串")        -- 返回字符串 12         # return render(request, "HTML模板的路径")    -- 返回给用户模板 13         # return redirect('/只能填URL')        -- 跳转,只能填'/URL'
View Code
 1 from django.shortcuts import render  2 
 3 # Create your views here.
 4 from django.shortcuts import HttpResponse  5 from django.shortcuts import render  6 from django.shortcuts import redirect  7 
 8 def login(request):  9     # 包含用户提交的全部信息
10     # print(request.method) # 获取用户提交方法
11     error_msg = ""
12     #若是请求提交的方法是POST(用户提交的数据)
13     if request.method == "POST": 14         # 获取用户经过POST提交过来的数据(用户提交的数据相似于字典)
15         user = request.POST.get('user',None)    #get('user',None)获取user内容,默认为None
16         pwd = request.POST.get('pwd',None) 17         if user == 'root' and pwd == "123": 18             # 去跳转到
19             return redirect('/login')   #redirect重定向、跳转
20         else: 21             # 用户密码不配
22             error_msg = "用户名或密码错误"
23     #打开页面并返回给用户,settings文件中配置了html文件的路径TEMPLATES('DIRS': [os.path.join(BASE_DIR, 'templates')])
24     return render(request,'login.html', {'error_msg': error_msg})   #render找到模板返回给用户
25 
26 USER_LIST = [ 27     {'id': 1, 'username': 'alex', 'email': 'asdfasdf', "gender": ''}, 28     {'id': 2, 'username': 'eriuc', 'email': 'asdfasdf', "gender": ''}, 29     {"id": 3,'username': 'seven', 'email': 'asdfasdf', "gender": ''}, 30 ] 31 
32 def home(request): 33     print(request.GET.get('nid')) 34 
35     if request.method == "POST": 36         # 获取用户提交的数据 POST请求中
37         u = request.POST.get('username') 38         e = request.POST.get('email') 39         g = request.POST.get('gender') 40         temp = {'username': u, 'email': e, "gender": g} 41  USER_LIST.append(temp) 42     return render(request, 'test/home.html', {'user_list': USER_LIST}) 43 
44 
45 # def login(request):
46 # # string = """
47 # # <form>
48 # # <input type='text' />
49 # # </form>
50 # #
51 # # """
52 # # f = open('templates/login.html', 'r', encoding='utf-8')
53 # # data = f.read()
54 # # f.close()
55 # # return HttpResponse(data)
56 # return render(request,'login.html')
57 
58 # def home(request):
59 # return HttpResponse('<h1>CMDB</h1>')
60 
61 # 主机管理
62 # 防火墙
63 # 。。。
views.py
2) 获取用户请求数据
request.GET.get()
request.POST.get()
request.FILES.get()
PS:
    GET:http请求默认使用的method,获取数据                
    POST:能够与GET区分,用来提交数据
3) 获取多选的内容(checkbox等)
request.POST.getlist()
4) 上传文件
import os from django.shortcuts import render,redirect from django.core.files.uploadedfile import InMemoryUploadedFile def login(request): if request.method == "GET": return render(request, 'login.html') elif request.method == "POST": # 上传文件,form标签作特殊设置
        obj = request.FILES.get('fafafa') print(obj,type(obj),obj.name) #文件路径拼接
        file_path = os.path.join('upload', obj.name) # 打开文件
        f = open(file_path, mode="wb") # obj.chunks()上传文件的块数据
        for i in obj.chunks(): f.write(i) f.close() return render(request, 'login.html') else: # PUT,DELETE,HEAD,OPTION...
        return redirect('/index/') 
views.py
5) FBV&CBV
FBV --> function base view url.py /index/ -> 函数名 view.py def 函数(request): ... CBV --> class base view url.py /index/ -> 类 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^home/', views.Home.as_view()), #根据get或post提交方式在类中执行对应的方法 ] view.py from django.views import View class Home(View): def dispatch(self, request, *args, **kwargs): # 调用父类中的dispatch print('before') result = super(Home,self).dispatch(request, *args, **kwargs) print('after') return result def get(self,request): print(request.method) return render(request, 'home.html') def post(self,request): print(request.method,'POST') return render(request, 'home.html') PS:类的方法名必定要小写,源代码中定义好了方法名 ====》 建议:二者都用
View Code
6) 装饰器

 

七、模板

templates目录下html
1) 模板的执行
模版的建立过程,其实就是读取模版(其中嵌套着模版标签),而后将 Model 中获取的数据插入到模版中,最后将信息返回给用户。
2) 模板语言
变量:
        {{ item }}
For循环:
        {% for item in item_list %}  {{ item }}  {% endfor %}
            forloop.counter
            forloop.first
            forloop.last 
if语句:        
        {% if ordered_warranty %}  {% else %} {% endif %}
母板:
        {% block title %}{% endblock %}
子板:
        {% extends "base.html" %}
        {% block title %}{% endblock %}    
帮助方法:
        {{ item.event_start|date:"Y-m-d H:i:s"}}
        {{ bio|truncatewords:"30" }}
        {{ my_list|first|upper }}
        {{ name|lower }}
 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  {#提交数据给login#} 17     <form action="/login" method="post">
18         <p>
19  {#点击label后input内出现光标#} 20             <label for="username">用户名:</label>
21             <input id="username" name="user" type="text" />
22         </p>
23         <p>
24             <label for="password">密码:</label>
25             <input id="password" name="pwd" type="password" />
26             <input type="submit" value="提交" />
27  {# Django会特殊处理 {{ error_msg }} #} 28             <span style="color: red;">{{ error_msg }}</span>
29         </p>
30     </form>
31     <script src="/static/jquery.min.js"></script>
32 </body>
33 </html>
变量
 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  {# Django模板语言for循环 #} 20  {% for row in user_list %} 21                 <tr>
22                     <td>{{ row.username }}</td>
23                     <td>{{ row.gender }}</td>
24                     <td>{{ row.email }}</td>
25                     <td>
26                         <a href="/detail?nid={{ row.id }}">查看详细</a> | 27                         <a class="del" href="#" row-id="{{ row.id }}">删除</a>
28                     </td>
29                 </tr>
30  {% endfor %} 31 
32         </table>
33     </div>
34     <div>
35         <form action="/del_host" method="post">
36             <input style="display: none" id="nid" type="text" name="nid" />
37             <p>
38                 <input type="submit" />
39                 <input type="botton" />
40             </p>
41         </form>
42     </div>
43     <script>
44  $('.del').click(function(){ 45             var row_id = $(this).attr('row-id'); 46             //赋值
47  $('#nid').val(row_id); 48  }) 49     </script>
50 </body>
51 </html>
For循环
 1 def func(request):  2     return render(request, "index.html", {  3                 'current_user': "alex",  4                 'user_list': ['alex','eric'],  5                 'user_dict': {'k1': 'v1', 'k2': 'v2'}})  6 
 7     
 8 index.html  9 
10 <html>
11 .. 12     <body>
13         <div>{{current_user}}</div>
14         
15         <a> {{ user_list.1 }} </a> #模板语言中根据索引获取列表内容 16         <a> {{ user_dict.k1 }} </a> #模板语言中根据索引获取字典内容 17         <a> {{ user_dict.k2 }} </a>
18         
19     </body>
20 
21 </html>
数据索引
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body> {#根据索引(key)直接获取值#} {{ user_dict.k1 }} <ul> {#循环的key#} {% for k in user_dict.keys %} <li>{{ k }}</li> {% endfor %} </ul>
    <ul> {#循环的value#} {% for val in user_dict.values %} <li>{{ val }}</li> {% endfor %} </ul>
    <ul> {#循环的key和value#} {% for k,row in user_dict.items %} <li>{{ k }}-{{ row }}</li> {% endfor %} </ul>
</body>
</html>
循环字典
 1 def func(request):  2     return render(request, "index.html", {  3                 'current_user': "alex",  4                 "age": 18,  5                 'user_list': ['alex','eric'],  6                 'user_dict': {'k1': 'v1', 'k2': 'v2'}})  7 
 8     
 9 index.html 10 <html>
11 .. 12     <body>
13         <div>{{current_user}}</div>
14         
15         <a> {{ user_list.1 }} </a>
16         <a> {{ user_dict.k1 }} </a>
17         <a> {{ user_dict.k2 }} </a>
18         
19         {% if age %} 20             <a>有年龄</a>
21             {% if age > 16 %} 22                 <a>老男人</a>
23             {% else %} 24                 <a>小鲜肉</a>
25             {% endif %} 26         {% else %} 27             <a>无年龄</a>
28         {% endif %} 29     </body>
30 
31 </html>
if条件语句
3) 自定义simple_tag

 

八、中间件

 

九、admin

 

3、Django进阶

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

一、Model

django使用ORM方式处理数据库相关操做,ORM即,关系对象映射(Object Relational Mapping)。
  PHP:activerecord
  Java:Hibernate 
  C#:Entity Framework
django中遵循 Code Frist 的原则,即,根据代码中定义的类来自动生成数据库表。注意原生SQL与ORM的对应关系。
1) 建立表
*基本结构
a. 先写类 from django.db import models # app01_userinfo
    class UserInfo(models.Model): # id列,自增,主键
        # 用户名列,字符串类型,指定长度
        username = models.CharField(max_length=32) password = models.CharField(max_length=64) b. 注册APP INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01',    #settings中添加app名,Django才给app生成数据库
 ] c. 执行命令(同步结构改动到数据库) #记录对models.py的改动(表结构变化),并在migrations下生成记录文件
 python manage.py makemigrations #将改动应用到数据库
 python manage.py migrate 注意:缩小列长度要谨慎,超出长度数据会丢失 d. ********** 注意 *********** Django默认使用MySQLdb模块连接MySQL 主动修改成pymysql,在project同名文件夹下的__init__文件中添加以下代码便可: import pymysql pymysql.install_as_MySQLdb()
建立表基本过程
# Create your models here. # app01_userinfo

from django.db import models class UserGroup(models.Model): uid = models.AutoField(primary_key=True) caption = models.CharField(max_length=32,unique=True) ctime = models.DateTimeField(auto_now_add=True, null=True) uptime = models.DateTimeField(auto_now=True, null=True) class UserInfo(models.Model):   #必须继承models.Model
    # id列,自增,主键 (Djiango默认建立)
    # 用户名列,字符串类型CharField,指定长度max_length
    # 字符串、数字、时间、二进制
    username = models.CharField(max_length=32,blank=True,verbose_name='用户名') password = models.CharField(max_length=60, help_text='pwd') email = models.CharField(max_length=60) test = models.EmailField(max_length=19,null=True,error_messages={'invalid': '请输入密码'}) # user_group_id 数字
    user_group = models.ForeignKey("UserGroup",to_field='uid',on_delete=models.CASCADE) # (uid,catption,ctime,uptimew)
    user_type_choices = ( (1, '超级用户'), (2, '普通用户'), (3, '普普通用户'), ) user_type_id = models.IntegerField(choices=user_type_choices,default=1) #不一样的字符串类型(...Field),给Django的admin表单认证使用的
    # test = models.URLField(max_length=19,null=True)
    # test = models.GenericIPAddressField()
    # gender = models.CharField(max_length=60, null=True)
models.py
字符串******** 不一样的字符串类型,只是给Django的admin表单校验使用的(如自动校验EmailField是不是邮箱格式) CharField(Field) - 字符类型 - 必须提供max_length参数, max_length表示字符长度 TextField(Field) - 文本类型 EmailField(CharField): - 字符串类型,Django Admin以及ModelForm中提供验证机制 IPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制(新版本中废弃,使用GenericIPAddressField) GenericIPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 - 参数: protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6" unpack_ipv4, 若是指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,须要protocol="both" URLField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证 URL SlugField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、链接符(减号) CommaSeparatedIntegerField(CharField) - 字符串类型,格式必须为逗号分割的数字 UUIDField(Field) - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 FilePathField(Field) - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 - 参数: path, 文件夹路径 match=None, 正则匹配 recursive=False, 递归下面的文件夹 allow_files=True, 容许文件 allow_folders=False, 容许文件夹 FileField(Field) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage ImageField(FileField) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage width_field=None, 上传图片的高度保存的数据库字段名(字符串) height_field=None 上传图片的宽度保存的数据库字段名(字符串) 数字******** AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 primary_key=True 注:当model中若是没有自增列,则自动会建立一个列名为id的列 ---
        from django.db import models class UserInfo(models.Model): # 自动建立一个列名为id的且为自增的整数列
            username = models.CharField(max_length=32) class Group(models.Model): # 自定义自增列
            nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) SmallIntegerField(IntegerField): - 小整数 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正小整数 0 ~ 32767 IntegerField(Field) - 整数列(有符号的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正整数 0 ~ 2147483647 BigIntegerField(IntegerField): - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 自定义无符号整数字段 class UnsignedIntegerField(models.IntegerField): def db_type(self, connection): return 'integer UNSIGNED' PS: 返回值为字段在数据库中的属性,Django字段默认的值为: 'AutoField': 'integer AUTO_INCREMENT', 'BigAutoField': 'bigint AUTO_INCREMENT', 'BinaryField': 'longblob', 'BooleanField': 'bool', 'CharField': 'varchar(%(max_length)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 'DateField': 'date', 'DateTimeField': 'datetime', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 'DurationField': 'bigint', 'FileField': 'varchar(%(max_length)s)', 'FilePathField': 'varchar(%(max_length)s)', 'FloatField': 'double precision', 'IntegerField': 'integer', 'BigIntegerField': 'bigint', 'IPAddressField': 'char(15)', 'GenericIPAddressField': 'char(39)', 'NullBooleanField': 'bool', 'OneToOneField': 'integer', 'PositiveIntegerField': 'integer UNSIGNED', 'PositiveSmallIntegerField': 'smallint UNSIGNED', 'SlugField': 'varchar(%(max_length)s)', 'SmallIntegerField': 'smallint', 'TextField': 'longtext', 'TimeField': 'time', 'UUIDField': 'char(32)', BooleanField(Field) - 布尔值类型 NullBooleanField(Field): - 能够为空的布尔值 DurationField(Field) - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 FloatField(Field) - 浮点型 DecimalField(Field) - 10进制小数 - 参数: max_digits,小数总长度 decimal_places,小数位长度 二进制******** BinaryField(Field) - 二进制类型 日期、时间******** DateTimeField(DateField) - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field) - 日期格式      YYYY-MM-DD TimeField(DateTimeCheckMixin, Field) - 时间格式      HH:MM[:ss[.uuuuuu]]
字段类型
auto_now_add 建立时,自动生成时间 auto_now 更新时,自动更新为当前时间 # obj = UserGroup.objects.filter(id=1).update(caption='CEO') #自动时间更新不生效
    # obj = UserGroup.objects.filter(id=1).first() #生效
    # obj.caption = "CEO"
    # obj.save()
 default 数据库中字段的默认值 null 数据库中字段是否能够为空 db_column 数据库中字段的列名 db_tablespace primary_key 数据库中字段是否为主键 db_index 数据库中字段是否能够创建索引 unique 数据库中字段是否能够创建惟一索引 unique_for_date 数据库中字段【日期】部分是否能够创建惟一索引 unique_for_month 数据库中字段【月】部分是否能够创建惟一索引 unique_for_year 数据库中字段【年】部分是否能够创建惟一索引 verbose_name Admin中字段名显示自定义的名字 blank Admin中是否容许用户输入为空 editable Admin中是否能够编辑 help_text Admin中该字段的输入提示信息(显示在该行下边) choices Admin中显示选择框的内容,用不变更的数据放在内存中从而避免跨表操做 注:由于数据存在内存中,若是修改要重启程序才会生效 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息; 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 如:{'null': "不能为空.", 'invalid': '格式错误'} validators 自定义错误验证(列表类型),从而定制想要的验证规则 from django.core.validators import RegexValidator from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\ MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 如: test = models.CharField( max_length=32, error_messages={ 'c1': '优先错信息1', 'c2': '优先错信息2', 'c3': '优先错信息3', }, validators=[ RegexValidator(regex='root_\d+', message='错误了', code='c1'), RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'), EmailValidator(message='又错误了', code='c3'), ] )
字段的参数
class UserInfo(models.Model): nid = models.AutoField(primary_key=True) username = models.CharField(max_length=32) class Meta: # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
            db_table = "table_name"

            # 联合索引
            index_together = [ ("pub_date", "deadline"), ] # 联合惟一索引
            unique_together = (("driver", "restaurant"),) # admin中显示的表名称
 verbose_name # verbose_name加s
 verbose_name_plural #更多:https://docs.djangoproject.com/en/1.10/ref/models/options/
元信息(models.py)
1.触发Model中的验证和错误提示有两种方式: a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,若是都成功,才来检查Model的字段并显示指定错误信息 b. 调用Model对象的 clean_fields 方法,如: # models.py
            class UserInfo(models.Model): nid = models.AutoField(primary_key=True) username = models.CharField(max_length=32) email = models.EmailField(error_messages={'invalid': '格式错了.'}) # views.py
            def index(request): obj = models.UserInfo(username='11234', email='uu') try: print(obj.clean_fields()) except Exception as e: print(e) return HttpResponse('ok') # Model的clean方法是一个钩子,可用于定制操做,如:上述的异常处理。

    2.Admin中修改错误提示 # admin.py
        from django.contrib import admin from model_club import models from django import forms class UserInfoForm(forms.ModelForm): username = forms.CharField(error_messages={'required': '用户名不能为空.'}) email = forms.EmailField(error_messages={'invalid': '邮箱格式错误.'}) age = forms.IntegerField(initial=1, error_messages={'required': '请输入数值.', 'invalid': '年龄必须为数值.'}) class Meta: model = models.UserInfo # fields = ('username',)
                fields = "__all__"


        class UserInfoAdmin(admin.ModelAdmin): form = UserInfoForm admin.site.register(models.UserInfo, UserInfoAdmin)
拓展知识

 

*连表结构

 

2) 操做表
*基本操做
根据类对数据库表中的数据进行各类操做

    一对多:
    
        a. 建立外键(一个对象)
        
        b. 数据库中实际存储 --> 外键字段_id
        
        c.    根据"外键字段_id"添加数据
            models.tb.object.create(name='root', user_group_id=1)
            
        d.  显示用户组信息
            
            userlist = models.tb.object.all()
            for row in userlist:
                row.id
                row.user_group_id
                row.user_group.caption

 

*进阶操做

 

*其余操做

 

*连表操做

 

*扩展

 

二、Form

 

三、跨站请求伪造

 

四、Cookie

 

五、Session

 

六、分页

 

七、缓存

 

八、序列化

 

九、信号

 

参考:css

Web框架:http://www.cnblogs.com/wupeiqi/articles/5237672.html
Django【基础篇】:http://www.cnblogs.com/wupeiqi/articles/5237704.html
Django【进阶篇】:http://www.cnblogs.com/wupeiqi/articles/5246483.html
相关文章
相关标签/搜索