Django web 基礎

1、Django概述javascript

Django大而全;css

建立Django工程:django-admin startproject sitenamehtml

建立django以後生成的目錄結構以下:前端

Project

    Project

        settings

        url

        wsgi

    web

        model

        views

        test

        admin

    administrator
Django工程目錄結構

D:\python_scripts\s11day17_Django>python manage.py startapp app01  #建立app;一個app是一個完整的軟件或者功能;java

app下面的文件:

    models:對數據庫操做的;

    views:函數放置的文件;

    test:作測,忽略;

    admin:Django的後臺管理平臺
app下面的文件

http://127.0.0.1:8000/admin      訪問Django的後臺管理平臺;python

能夠建立admin後臺管理的帳戶,帳戶默認存在於數據庫下,存放位置在settings中定義以下:mysql

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}

下面寫一個http請求,urls是路由系統:
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^home/',views.home),            #一個url對應一個函數,函數存在於app的views中
]
urls
views中的函數以下:
from django.shortcuts import render

# Create your views here.
from django.shortcuts import HttpResponse
def home(request):    #此處的request是必須的
    return HttpResponse('ok')
views

D:\python_scripts\s11day17_Django>python manage.py runserver 127.0.0.1:8009    #啓動Django程序;或者在Django工程的edit下面配置端口http://127.0.0.1:8009/home/    #訪問jquery

-----http請求完畢;


Django模板渲染
在app的views中添加的函數返回html文件內容,以下:
#!/usr/bin/env python
#coding:utf-8
from django.shortcuts import render

# Create your views here.
from django.shortcuts import HttpResponse
def home(request):
    #return HttpResponse('ok')
    '''render內部找到home.html,讀取html返回給用戶,render和跨站請求僞造相關'''
    return render(request,'home.html')
home.html

能夠看到默認到templates模塊下找該文件了;那麼程序如何知道html文件時在templates下面去找的呢?事實上,是在settings配置文件下面設置的啦;不一樣版本的Django配置有所不一樣;
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,

 

就OK拉~~~~~~~

Django內部也使用jinjia2模板:
views內容以下:
#!/usr/bin/env python
#coding:utf-8
# Create your views here.
from django.shortcuts import render
from django.shortcuts import HttpResponse,render_to_response
def home(request):
    #return HttpResponse
    #return render_to_response(request,'home.html')
    '''render內部找到home.html,讀取html返回給用戶'''
    dic ={'name':'Charles','age':18}
    return render(request,'home.html',dic)
views

 


home.html文件以下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>Home</h1>
    <h2>{{ name }}</h2>
    <h2>{{ age }}</h2>
</body>
</html>
home.html
模板渲染完畢



模板語言和自定義simple_tag
home.html模板語言:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>Home</h1>
    <h2>{{ name }}</h2>
    <h2>{{ age }}</h2>
    <ul>
    {% for item in user_list %}
        <li>{{ item }},{{ forloop.first }}</li>
    {% endfor %}
    </ul>
</body>
</html>
home.html
views內容以下:
#!/usr/bin/env python
#coding:utf-8
# Create your views here.
from django.shortcuts import render
from django.shortcuts import HttpResponse,render_to_response
def home(request):
    #return HttpResponse
    #return render_to_response(request,'home.html')
    '''render內部找到home.html,讀取html返回給用戶'''
    dic ={'name':'Charles','age':18,'user_list':{'Charles','wahaha','Rain'}}
    return render(request,'home.html',dic)
view

儘管模板語言能夠提供部分函數,實現一部分功能,可是有些須要咱們自定義區實現:
一、在app中建立templatetags和文件

二、

三、

Django之母版:
什麼叫作母版:紅色部分在其餘頁面走不回改變,那麼就沒有必要再任何頁面寫這些內容啦~~~,能夠建立母版實現啦,相似於類的繼承

那麼如何實現母版以及繼承母版:

master下的m1爲母版:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
    <style>
        .header{
            height: 48px;
            background-color: red;
        }
        .body{
            background-color: #dddddd;
        }
        .body .menu{
            background-color: green;
            float: left;
            width: 2%;
        }
        .body .content{
            background-color: darkgoldenrod;
            float: left;
            width: 70%;
        }
    </style>
</head>
<body>
    <div class="header">LOGO</div>
    <div class="body">
        <div class="menu">左側菜單</div>
        <div class="content">
            {% block content %}{% endblock %}
        </div>
    </div>
</body>
</html>
m1.html
son1繼承m1:
{% extends "master/m1.html" %}
{% block content %}
    <h1>666</h1>

    {% include "include/input_group.html" %}
    {% include "include/haha.html" %}
{% endblock %}

{% block title %}
    老男人
{% endblock %}
son1.html
son1一樣繼承include下的兩個html文件內容;include防止在子html的什麼位置,內容就顯示在什麼地方;

母版和include的應用場景:
母版:整體佈局使用;include在局部功能上須要別的頁面繼承的時候使用:

views的內容:
#!/usr/bin/env python
#coding:utf-8
# Create your views here.
from django.shortcuts import render
from django.shortcuts import HttpResponse,render_to_response

def son(request):
    return render(request,'son1.html')
def home(request):
    #return HttpResponse
    #return render_to_response(request,'home.html')
    '''render內部找到home.html,讀取html返回給用戶'''
    dic ={'name':'Charles','age':18,'user_list':{'Charles','wahaha','Rain'}}
    return render(request,'home.html',dic)
views
urls的內容:
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^home/',views.home),
    url(r'^son/',views.son),
]
urls

Django靜態文件的配置:
好比上面html母版中的CSs渲染的部分,須要放置到靜態文件夾中,而後在母版中導入便可;
建立static靜態文件夾

在settings中指明(須要一一對應)文件的路徑

這樣母版m1的內容就爲:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
    <link rel="stylesheet" href="/static/css/commons.css"/>
    {% block css %}{% endblock %}             #也能夠設置css文件的母版
</head>
<body>
    <div class="header">LOGO</div>
    <div class="body">
        <div class="menu">左側菜單</div>
        <div class="content">
            {% block content %}{% endblock %}
        </div>
    </div>
    <script type="text/javascript">

    </script>
    {% block js %}{% endblock %}    #設置js文件的母版
</body>
</html>


commons.ss的內容爲:
.clearfix:after{
    content: ".";
    visibility: hidden;
    display: block;
    height: 0;
    clear: both;
}
.header{
        height: 48px;
        background-color: red;
    }
    .body{
        background-color: #dddddd;
    }
    .body .menu{
        background-color: green;
        float: left;
        width: 2%;
    }
    .body .content{
        background-color: darkgoldenrod;
        float: left;
        width: 70%;
    }
m1.html
settings的內容以下:
STATIC_URL = '/static/'
STATICFILES_DIRS=(
os.path.join(BASE_DIR,'static'),
)

整個程序訪問流程以下:請求到url-->views-->templates中找html-->數據和html模板渲染-->獲得字符串返回給用戶


下面開發一個Django用戶登陸實例:
一、拷貝jQuery和bootstrap插件到靜態文件目錄下:

二、增長登陸模塊(html文件),增長表單的name

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
    <link rel="stylesheet" href="/static/css/commons.css"/>
    {% block css %}{% endblock %}             #也能夠設置css文件的母版
</head>
<body>
    <div class="header">LOGO</div>
    <div class="body">
        <div class="menu">左側菜單</div>
        <div class="content">
            {% block content %}{% endblock %}
        </div>
    </div>
    <script type="text/javascript">

    </script>
    {% block js %}{% endblock %}    #設置js文件的母版
</body>
</html>


commons.ss的內容爲:
.clearfix:after{
    content: ".";
    visibility: hidden;
    display: block;
    height: 0;
    clear: both;
}
.header{
        height: 48px;
        background-color: red;
    }
    .body{
        background-color: #dddddd;
    }
    .body .menu{
        background-color: green;
        float: left;
        width: 2%;
    }
    .body .content{
        background-color: darkgoldenrod;
        float: left;
        width: 70%;
    }
login.html
三、views增長login函數
def login(request):
    #若是是get請求,get請求表示請求頁面
    #若是是POST,檢驗用戶輸入;POST表示向頁面提交內容
    print request.method
    if request.method == 'POST':
        input_email=request.POST['email']
        input_pwd = request.POST['pwd']
        if input_email == 'Charles@qq.com' and input_pwd == "123":
            from django.shortcuts import redirect
            return redirect("https://www.baidu.com")        #跳轉到別的頁面,若是想要跳轉到別的函數,好比son,return redirect("/son/")
        else:
            return render(request,'login.html',{'status':'用戶名或密碼錯誤'})       #不然顯示錯誤
    return render(request,'login.html')
views

四、urls的內容
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^home/',views.home),
    url(r'^son/',views.son),
    url(r'^login/',views.login),
]
urls

model基本操做之增刪改查
Django提供了ORM,可使用類來建立數據庫表和字段:

命令python manage.py makemigations 和python manage.py migrate能夠建立數據表,生成0001.initial.py文件(注意都是在app01中操做的)
二、settings內容:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01', #註冊該app
]
三、urls內容
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^home/',views.home),
    url(r'^son/',views.son),
    url(r'^login/',views.login),
    url(r'^index/',views.index),
]
urls
四、views中定義index函數:
#!/usr/bin/env python
#coding:utf-8
# Create your views here.
from django.shortcuts import render
from django.shortcuts import HttpResponse,render_to_response

def son(request):
    return render(request,'son1.html')
def home(request):
    #return HttpResponse
    #return render_to_response(request,'home.html')
    '''render內部找到home.html,讀取html返回給用戶'''
    dic ={'name':'Charles','age':18,'user_list':{'Charles','wahaha','Rain'}}
    return render(request,'home.html',dic)

def login(request):
    #若是是get請求
    #若是是POST,檢驗用戶輸入
    print request.method
    if request.method == 'POST':
        input_email=request.POST['email']
        input_pwd = request.POST['pwd']
        if input_email == 'Charles@qq.com' and input_pwd == "123":
            from django.shortcuts import redirect
            return redirect("/index/")
        else:
            return render(request,'login.html',{'status':'用戶名或密碼錯誤'})
    return render(request,'login.html')

def index(request):
    #數據庫取數據
    #數據和HTML渲染
    from app01 import models
    if request.method =="POST":
        input_em = request.POST['em']
        input_pw = request.POST['pw']
        models.UserInfo.objects.create(email=input_em,pwd=input_pw)    #增長數據

        #models.UserInfo.objects.filter(email=input_em).delete()       #刪除數據
        #models.UserInfo.objects.filter(email=input_em).update(pwd=999)   #更新數據
    #獲取UserInfo表中的全部的數據
    user_info_list = models.UserInfo.objects.all()    #查收,在模板中循環
    #user_info_list列表,列表的元素爲一行;email,pwd;
    return render(request,'index.html',{'user_info_list':user_info_list})
views
四、模板index.html內容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/index/" method="post">
        <input type="text" name="em"/>
        <input type="text" name="pw"/>
        <input type="submit" name="添加"/>
    </form>
    <table border="1">
        <thead>
            <tr>
                <th>郵箱</th>
                <th>密碼</th>
            </tr>
        </thead>
        <tbody>
            {% for line in user_info_list %}
                <tr>
                    <td>{{ line.email }}</td>
                    <td>{{ line.pwd }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
</body>
</html>
index.html

 
--權限登陸管理系統
    1、登陸(裝飾器判斷用戶是否已經登陸--可選,用戶密碼MD5)
    2、註冊(檢測用戶是否已經存在,onblur+ajax光標跳出輸入框時)
    3、註銷(忽略)
    4、用戶管理(From表單)
        重置密碼
        建立用戶(單條,批量)
        修改用戶信息
    5、權限控制(可選)
        用戶是否能夠訪問URL
做業

 

內容:
1、URL路由系統
2、中間件
3、Model:數據庫的操做(重點)
一、建立表
二、操做表數據
4、Form(重點)
一、用戶提交數據驗證
二、生成html標籤
5、cookie和session
6、跨站請求僞造和跨站腳本攻擊
7、Ajax操做(重點)
8、Admin
9、緩存
10、自定義分頁(重點)


下面分開介紹:

Django請求生命週期


路由系統詳細介紹:

分頁的概念:

點擊是url發生變化;

那麼如何實現分頁:路由系統函數傳參

一、urls的內容:
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/', include("app01.urls")),
    url(r'^index/$', views.index),
    #url(r'^user_list/(\d+)$', views.user_list),             #django內部默認將url以/爲分割線將url分割,傳入參數,默認是按照順序傳入參數的
    #url(r'^user_list/(\d+)/(\d+)$', views.user_list),
    url(r'^user_list/(?P<v1>\d+)/(?P<v2>\d+)$', views.user_list),   #要靈活傳入參數,設置(?P<v1>\d+),v1表示key,傳入的參數爲value

    url(r'^$', views.index),          #放置到最後
]
urls
二、views的內容
from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
    return HttpResponse('OK')

def user_list(request,v2,v1):           #將key傳入
    print v1,v2
    return HttpResponse(v1+v2)
views

對於不一樣的app而言,如何實現輸入url爲app01的請求發送到app01上面:程序員

一、urls的內容
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/', include("app01.urls")),          #發送的對應app下的urls中
    url(r'^index/$', views.index),
    #url(r'^user_list/(\d+)$', views.user_list),
    #url(r'^user_list/(\d+)/(\d+)$', views.user_list),
    url(r'^user_list/(?P<v1>\d+)/(?P<v2>\d+)$', views.user_list),
    url(r'^$', views.index),          #放置到最後,爲路由系統的默認處理函數,相似於404
]
urls
二、在app01下新建urls文件

三、settings
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01'
]
訪問:

Django路由系統完畢!!!web

 

 基於反射的路由系統:多有的函數都放置在一個.py文件中;

 

中間件:

Django提供的中間件以下:

MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

 自定義中間件來解析中間件工做流程:

一、建立中間件文件夾以及文件

middle文件內容爲:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
class mmm(object):
    def process_view(self, request, callback, callback_args, callback_kwargs):
        print 'mmm.process_view'

    def process_response(self, request, response):
        print 'mmm.process_response'
        return response
class xxx(object):                     #類中的函數上面兩個方法是必需要有的,只能存在這四個方法
    def process_request(self,request):
        print 'xxx.process_request'
    def process_view(self, request, callback, callback_args, callback_kwargs):
        print 'xxx.process_view'

    def process_response(self, request, response):
        print 'xxx.process_response'
        return response
    def process_exception(self,request,exception):
        pass
middle.py

二、註冊中間件到settings文件中

MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'middleware.middle.mmm',
'middleware.middle.xxx',
]

三、views內容以下:
from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
print 'index'
return HttpResponse('OK')

def user_list(request,v2,v1):
print v1,v2
return HttpResponse(v1+v2)


四、訪問以下:

process_expection方法在views.index函數執行出錯的時候觸發;

總結:
一、客戶端發出請求
二、Django自動去settings中找MIDDLEWARE_CLASSES,列表或元組
process_request_list = []
process_view_list = []
process_response_list = []
process_exception_list = []
三、for 類 in MIDDLEWARE_CLASSES:
obj=類()
if obj 裏有process_request方法:

process_request_list.append(obj.process_request_list)
        if obj 裏有process_view方法:

         process_view_list.append(obj.process_request_list)
        views中的函數:
    if obj 裏有process_response方法:

         process_response_list .append(obj.process_request_list)
中間件是一個類,類中的方法名必須是固定的

一、 #process_request和process_view沒有返回值,是正常的執行過程(藍色部分)
class xxx(object):
def process_request(self,request):
print 'xxx.process_request'
def process_view(self, request, callback, callback_args, callback_kwargs):
print 'xxx.process_view'

def process_response(self, request, response):
print 'xxx.process_response'
return response
def process_exception(self,request,exception):
pass
二、request函數直接返回值,爲紅色部分
三、灰色部分表示函數執行出錯的時候的執行流程;

下面展現process_exception;
settings的內容:
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'middleware.middle.mmm',
'middleware.middle.xxx',
]

middle.py內容:
#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django.shortcuts import render,HttpResponse

class mmm(object):
def process_request(self,request):
print 'mmm.process_request'
def process_view(self, request, callback, callback_args, callback_kwargs):
print 'mmm.process_view'

def process_response(self, request, response):
print 'mmm.process_response'
return response
def process_exception(self,request,exception):
print 'View中出錯了返回'
return HttpResponse('View中出錯了,返回')
class xxx(object):
def process_request(self,request):
print 'xxx.process_request'
def process_view(self, request, callback, callback_args, callback_kwargs):
print 'xxx.process_view'

def process_response(self, request, response):
print 'xxx.process_response'
return response
def process_exception(self,request,exception):
print 'View中出錯了,可是不返回'
return HttpResponse('View中出錯了,不返回') #第二個函數返回,將不會執行第一個函數

直接返回

midele.py第二個函數沒有返回值:那麼兩個函數執行都會執行;
#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django.shortcuts import render,HttpResponse

class mmm(object):
def process_request(self,request):
print 'mmm.process_request'
def process_view(self, request, callback, callback_args, callback_kwargs):
print 'mmm.process_view'

def process_response(self, request, response):
print 'mmm.process_response'
return response
def process_exception(self,request,exception):
print 'View中出錯了返回'
return HttpResponse('View中出錯了,返回')
class xxx(object):
def process_request(self,request):
print 'xxx.process_request'
def process_view(self, request, callback, callback_args, callback_kwargs):
print 'xxx.process_view'

def process_response(self, request, response):
print 'xxx.process_response'
return response
def process_exception(self,request,exception):
print 'View中出錯了,可是不返回'

總結:process_exception函數根據setting的設置從下往上執行,若是有返回值,就不會執行後面的類中的process_exception函數;


緩存介紹:
將DB和templates中拿到的渲染後的字符串,放置到緩存中,緩存的介質能夠爲文件、memcached、redis、數據庫;


使用緩存步驟:
一、views中添加以下函數:
def cache_page(request):
current = str(time.time())
return HttpResponse(current)

app01\urls內容爲:
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^index/', views.index),
url(r'^cache/', views.cache_page),
]
每次post請求的時候,其內容都會從新渲染,顯示不一樣的字符串

三、在settings配置文件中添加以下內容:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': os.path.join(BASE_DIR, 'cache'), #緩存內容使用文件,存放在文件裏面
'TIMEOUT': 600,
'OPTIONS': {
'MAX_ENTRIES': 1000
}
}
}
四、給views中的函數增長裝飾器
from django.shortcuts import render,HttpResponse
import time
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) #表示每15分鐘緩存更新一次;
def cache_page(request):
current = str(time.time())
return HttpResponse(current)

 

 

下面介紹cookie和session:

一、cookie是一個字符串,保存於本地的電腦上;session保存於服務器

由於http是短鏈接,第一次訪問以後就會斷開,那麼第二次訪問的時候如何知道以前該用戶已經訪問過了;好比要訪問jd的頁面,第一次登錄以後,服務器端會向客戶端瀏覽器下發一個字符串,第二次用戶訪問的時候就能夠攜帶者這個字符串來訪問了,這樣服務器端就認爲已經登錄過了,就能夠容許用戶點擊購物車等其餘連接了;那麼問題來了,服務器如何根據字符串判斷用戶已經訪問過了?

上述步驟中1和2是web框架本身實現的,第3步中,對用戶的session設置對應的任意值是程序員本身設置的,好比,此處能夠設置爲是否登陸is_login;具體實現以下:
a、app01中views增長函數以下:
def login(request):
if request.method=='POST':
username = request.POST.get('username')
pwd = request.POST.get('pwd')
if username == 'Charles' and pwd=='123':
request.session['IS_LOGIN'] = True
return redirect('/app01/home/')

return render(request,'login.html')

def home(request):
'''
若是用戶已經登錄
'''
is_login = request.session.get('IS_LOGIN',False)
if is_login:
return HttpResponse('order')
else:
return redirect('/app01/login/')
b、app01\urls
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^index/$', views.index),
url(r'^cache/$', views.cache_page),
url(r'^login/$', views.login),
url(r'^home/$', views.home),
]
c、templates中定義login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form action="/app01/login/" method="post">
<input type="text" name="username"/>
<input type="password" name="pwd">
<input type="submit" value="submit"/>
</form>
</body>
</html>

注意:session是存在於數據庫中的,若是變化session內容(request.session['IS_LOGIN'] = True),那麼就須要從新同步數據庫:D:\python_scripts\s11day18_Django>python manage.py migrate
d、若是用戶名和密碼不正確,就會報403錯誤,須要禁止掉csrf
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
#'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'middleware.middle.mmm',
'middleware.middle.xxx',
]

注意:默認狀況下,Django的session存放在數據庫中;

 


這樣咱們能夠經過自定義session,來根據輸入的不一樣的用戶,顯示不一樣的值;
db = {
'Charles':'11111',
'eric':'22222',
}
def login(request):
if request.method=='POST':
username = request.POST.get('username')
pwd = request.POST.get('pwd')
if username == 'Charles' and pwd=='123':
request.session['IS_LOGIN'] = True
request.session['USERNAME']='Charles'
return redirect('/app01/home/')
elif username=='eric' and pwd =='123':
request.session['IS_LOGIN'] = True
request.session['USERNAME']='eric'
return redirect('/app01/home/')

return render(request,'login.html')

def home(request):
'''
若是用戶已經登錄
'''
is_login = request.session.get('IS_LOGIN',False)
if is_login:
username = request.session.get('USERNAME',False)
data = db[username]
return HttpResponse(data)
else:
return redirect('/app01/login/')

如何在右上角設置登陸和註銷的按鈕:在登陸以後,將用戶名和註銷的按鈕顯示在右上角
a、app01/views增長函數:
views
def login(request):
    if request.method=='POST':
        username = request.POST.get('username')
        pwd = request.POST.get('pwd')
        if username == 'Charles' and pwd=='123':
            request.session['IS_LOGIN'] = True
            request.session['USERNAME']='Charles'
            return redirect('/app01/home/')
        elif username=='eric' and pwd == '123':
            request.session['IS_LOGIN'] = True
            request.session['USERNAME']='eric'
            return redirect('/app01/home/')

    return render(request,'login.html')

def home(request):
    '''
    若是用戶已經登錄
    '''
    is_login = request.session.get('IS_LOGIN',False)
    if is_login:
        username = request.session.get('USERNAME',False)
        data = db[username]
        #return HttpResponse(data)
        return render(request,'home.html',{'username':username})
    else:
        return redirect('/app01/login/')

def logout(request):
    del request.session['IS_LOGIN']
    return redirect('/app01/login')

b、templates下增長html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .header{
            height: 48px;
        }
    </style>
</head>
<body>
    <div class="header">
        <div style="float: right">{{ username }}</div>
        <div style="float: right"><a href="/app01/logout/">註銷</a></div>
    </div>

</body>
</html>
home.html
c、app01/urls內容:
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
   url(r'^index/$', views.index),
    url(r'^cache/$', views.cache_page),
    url(r'^login/$', views.login),
    url(r'^home/$', views.home),
    url(r'^logout/$', views.logout),
   ]
urls

cookie但是設置超時時間,在settings文件中,增長字段:SESSION_COOKIE_AGE = 5,表示cookie超時時間爲5秒,也能夠設置關閉會話後,刪除cookie;上述頁面在cookie刪除以後會自動跳轉到登陸頁面(然而我測試沒有成功/(ㄒoㄒ)/~~)
cookie和session到此結束,O(∩_∩)O~;


下面介紹Django From;
做用:一、用戶提交數據驗證;二、生成html標籤;
爲何要使用From,看下面:
a、app01/views中定義函數:
def user_list(request):
   # host = request.POST.get('host')
   # port = request.POST.get('port')
    #email = request.POST.get('email')
    #mobile = request.POST.get('mobile')
    #'''上述字段是由用戶輸入的,程序員須要判斷:一、用戶的每一項輸入不能爲空;二、用戶輸入的字段是合法的字符按;這樣須要作大量的
    #工做纔可以實現'''
    #return render(request,'user_list.html')
views.py
b、定義html文件:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <form action="/user_list/" method="post">       {% comment %}此處的action必須是以/開頭和結尾{% endcomment %}
   {% comment %}     <input type="text" name="host"/>
        <input type="text" name="port"/>
        <input type="text" name="email"/>
        <input type="text" name="mobile"/>
        <input type="submit" value="submit" />{% endcomment %}
    </form>
</body>
</html>
user_list.html

上述例子中須要程序員須要解決兩個問題:一、嚴重用戶輸入的內容各項不能爲空;二、驗證用戶輸入的各項內容是否合法;這兩項工做都須要作大量的工做;而From不但能夠自動實現驗證功能,還能夠自動生成html標籤;  除此之外,前端js驗證若是js被客戶端瀏覽器禁用掉的話,沒法使用,全部最好前端和後臺驗證都各寫一套;

前端js實現驗證功能實例以下:

 

具體實現以下:

a、views的內容:

#!/usr/bin/env python
#coding:utf-8
from django.shortcuts import render

# Create your views here.

from django import forms

class UserInfo(forms.Form):
    #email = forms.EmailField(required=False)
    email = forms.EmailField()
    host = forms.CharField()
    port = forms.CharField()
    mobile=forms.CharField()

def user_list(request):
    obj = UserInfo()    
    if request.method=="POST":
        user_input_obj = UserInfo(request.POST)   #用戶輸入的各項字段的值
        #print user_input_obj.is_valid()
        if user_input_obj.is_valid():    #判斷各項輸入是否合法
            data = user_input_obj.clean()    #用戶輸入的各項的值,爲字典類型
            print data
        else:
            error_msg = user_input_obj.errors
            print error_msg
            return render(request,'user_list.html',{'obj':user_input_obj,'errors':error_msg})
    return render(request,'user_list.html',{'obj':obj})

   # host = request.POST.get('host')
   # port = request.POST.get('port')
    #email = request.POST.get('email')
    #mobile = request.POST.get('mobile')
    #'''上述字段是由用戶輸入的,程序員須要判斷:一、用戶的每一項輸入不能爲空;二、用戶輸入的字段是合法的字符按;這樣須要作大量的
    #工做纔可以實現'''
    #return render(request,'user_list.html')
app01/views

b、user_list.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <form action="/user_list/" method="post">       {% comment %}此處的action必須是以/開頭和結尾{% endcomment %}
       <p>主機: {{ obj.host }}<span>{{ errors.host }}   #若是輸入不合法,將錯誤信息顯示出來</span></p>
       <p>端口:  {{ obj.port }}<span>{{ errors.port }}</span></p>
       <p>郵箱:  {{ obj.email }}<span>{{ errors.email }}</span></p>
        <p>手機: {{ obj.mobile }}<span>{{ errors.mobile }}</span></p>
        <input type="submit" value="submit" />
   {% comment %}     <input type="text" name="host"/>
        <input type="text" name="port"/>
        <input type="text" name="email"/>
        <input type="text" name="mobile"/>
        <input type="submit" value="submit" />{% endcomment %}
    </form>
</body>
</html>
user_list.html

c、

MIDDLEWARE_CLASSES = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
   # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
禁止csrf功能
"""s11day18_form URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^user_list/', views.user_list),
]
urls

輸入合法與不合法顯示信息以下:


Django From定製化
在上面的例子中,咱們只是簡單實現了from自動生成html標籤和from表單驗證的功能,那麼對於一些個性化的表單驗證和錯誤信息的展現,該如何實現呢?
一、views的內容:
#!/usr/bin/env python
#coding:utf-8
from django.shortcuts import render

# Create your views here.

from django import forms
from django.core.exceptions import ValidationError
import re

def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')   #個性化定製驗證功能,是否符合手機號碼規則
    if not mobile_re.match(value):
        raise ValidationError('手機號碼格式錯誤')

class UserInfo(forms.Form):    #經過定義類。實現獲取用戶輸入表單的信息
    user_type_choice = (
        (0, u'普通用戶'),
        (1, u'高級用戶'),
    )
    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,       #實現select選擇功能
                                                                  attrs={'class': "form-control"}))

    #email = forms.EmailField(required=False)
    email = forms.EmailField(error_messages={'required': u'郵箱不能爲空'})
    host = forms.CharField(error_messages={'required': u'主機名不能爲空'})
    port = forms.CharField(error_messages={'required': u'端口不能爲空'})
    mobile=forms.CharField(validators=[mobile_validate, ],    #驗證手機號碼
                           error_messages={'required': u'手機不能爲空'},
                           widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手機號碼'}))
    memo = forms.CharField(required=False,
                           max_length=256,
                           widget=forms.Textarea(attrs={'class': "form-control",    #attrs表示想input中添加屬性
                                                                'placeholder': u'備註'}))

def user_list(request):
    obj = UserInfo()
    if request.method=="POST":
        user_input_obj = UserInfo(request.POST)
        #print user_input_obj.is_valid()
        if user_input_obj.is_valid():
            data = user_input_obj.clean()
            print data
        else:
            error_msg = user_input_obj.errors
            print error_msg
            return render(request,'user_list.html',{'obj':user_input_obj,'errors':error_msg})
    return render(request,'user_list.html',{'obj':obj})

   # host = request.POST.get('host')
   # port = request.POST.get('port')
    #email = request.POST.get('email')
    #mobile = request.POST.get('mobile')
    #'''上述字段是由用戶輸入的,程序員須要判斷:一、用戶的每一項輸入不能爲空;二、用戶輸入的字段是合法的字符按;這樣須要作大量的
    #工做纔可以實現'''
    #return render(request,'user_list.html')
views.py
二、html文件內容
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .form-control{    {% comment %}經過attr增長的屬性,能夠在html中加以利用,或者在這裏能夠本身定義屬性,實現渲染頁面渲染功能{% endcomment %}
            background-color: red;
        }
    </style>
</head>
<body>
    <form action="/user_list/" method="post">       {% comment %}此處的action必須是以/開頭和結尾{% endcomment %}
       <p>用戶類型: {{ obj.user_type }}<span>{{ errors.user_type }}</span></p>
       <p>主機: {{ obj.host }}<span>{{ errors.host }}</span></p>
       <p>端口:  {{ obj.port }}<span>{{ errors.port }}</span></p>
       <p>郵箱:  {{ obj.email }}<span>{{ errors.email }}</span></p>
        <p>手機: {{ obj.mobile }}<span>{{ errors.mobile }}</span></p>
        <p>備註: {{ obj.memo }}<span>{{ errors.mome }}</span></p>
        <input type="submit" value="submit" />

    </form>
</body>
</html>
user_list.html

總結:

1、建立類from.From
2、頁面根據類的對象自動建立html標籤
3、提交數據,request.POST
     封裝到一個類的對象裏  obj=UserInfo(request.POST)
4、用戶輸入是否合法
     obj.is_valid()
5、所有合法的話,獲得用戶輸入數據  obj.clean()
6、只要有一個不合法,產生不合法的錯誤提示信息 obj.errors

注意:自定義的UserInfo類中能夠寫入select插件,能夠經過attr添加屬性,能夠經過正則表達式這是輸入數據的格式;
總結

 

Form漂亮的顯示錯誤信息

form默認生成的html錯誤信息是ul,前面帶黑點;使用as_data()來說ul轉換爲原生的字符串;
def user_list(request):
    obj = UserInfo()
    if request.method=="POST":
        user_input_obj = UserInfo(request.POST)
        #print user_input_obj.is_valid()
        if user_input_obj.is_valid():
            data = user_input_obj.clean()
            print data
        else:
            error_msg = user_input_obj.errors.as_data()    #默認爲ul,前面加黑點,使用as_data()將其轉換爲原生的字符串顯示
            print error_msg
            return render(request,'user_list.html',{'obj':user_input_obj,'errors':error_msg})
    return render(request,'user_list.html',{'obj':obj}
views

上述錯誤信息是包含在字典當中,可是在模板語言中,沒法經過索引如host[0][0]來獲取到錯誤信息,這時候就須要藉助是、simple_tag來實現經過python的索引類獲取錯誤信息了;
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',
]
settings

#!/usr/bin/env python
# -*- coding:utf-8 -*-


from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError

register = template.Library()

from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError

register = template.Library()

@register.simple_tag
def error_message(arg):
    if arg:
        return arg[0][0]      #經過索引取值
    else:
        return ''
form_tag
{% load form_tag %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .form-control{    {% comment %}經過attr增長的屬性,能夠在html中加以利用,或者在這裏能夠本身定義屬性,實現渲染頁面渲染功能{% endcomment %}
            background-color: red;
        }
    </style>
</head>
<body>
    <form action="/user_list/" method="post">       {% comment %}此處的action必須是以/開頭和結尾{% endcomment %}
       <p>用戶類型: {{ obj.user_type }}
           <span>{% error_message errors.user_type %}</span>
       </p>
       <p>主機: {{ obj.host }}\
           {% comment %}{% errors.host[0][0] %}{% endcomment %}       {% comment %}  //模板語言不支持索引取值。因此須要構造simple_tag在python中來實現索引取值//{% endcomment %}
           <span>{% error_message errors.host %}</span>
       </p>
       <p>端口:  {{ obj.port }}<span>{{ errors.port }}</span></p>
       <p>郵箱:  {{ obj.email }}<span>{{ errors.email }}</span></p>
        <p>手機: {{ obj.mobile }}<span>{{ errors.mobile }}</span></p>
        <p>備註: {{ obj.memo }}<span>{{ errors.mome }}</span></p>
        <input type="submit" value="submit" />

    </form>
</body>
</html>
user_list.html

 

 

具體實現能夠參考:

 

ModelForm:

若是想要將數據庫中的數據到前端進行展現;也就是利用model作出相似於django admin相似效果的東西;

 

 

 

 

 

下面介紹Ajax:

Ajax發送簡單數據類型

能夠將數據保存以後發送到後臺,後臺更新就能夠了;

一、導入jQuery

{% load form_tag %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .form-control{    {% comment %}經過attr增長的屬性,能夠在html中加以利用,或者在這裏能夠本身定義屬性,實現渲染頁面渲染功能{% endcomment %}
            background-color: red;
        }
    </style>
</head>
<body>
    <form action="/user_list/" method="post">       {% comment %}此處的action必須是以/開頭和結尾{% endcomment %}
       <p>用戶類型: {{ obj.user_type }}
           <span>{% error_message errors.user_type %}</span>
       </p>
       <p>主機: {{ obj.host }}\
           {% comment %}{% errors.host[0][0] %}{% endcomment %}       {% comment %}  //模板語言不支持索引取值。因此須要構造simple_tag在python中來實現索引取值//{% endcomment %}
           <span>{% error_message errors.host %}</span>
       </p>
       <p>端口:  {{ obj.port }}<span>{{ errors.port }}</span></p>
       <p>郵箱:  {{ obj.email }}<span>{{ errors.email }}</span></p>
        <p>手機: {{ obj.mobile }}<span>{{ errors.mobile }}</span></p>
        <p>備註: {{ obj.memo }}<span>{{ errors.mome }}</span></p>
        <input type="submit" value="submit" />

    </form>
    <input type="button" onclick="AjaxSumbit();"  value="Ajax提交" />
    <table border="1">
        <thead>
            <tr>
                <th>主機名</th>
                <th>端口</th>
            </tr>
        </thead>
        <tbody id="tbd">
            <tr>
                <th>1.1.1.1</th>
                <th>9999</th>
            </tr>
            <tr>
                <th>1.1.1.1</th>
                <th>9998</th>
            </tr>
        </tbody>
    </table>
    <script src="/static/jquery-1.8.2.min.js"></script>
    <script>
        function AjaxSumbit(){
            var host='1.1.1.1';
            var port='9999';
            $.ajax({
                'url':"/ajax_data/",
                type:"POST",
                data:{h:host,p:port},
                success:function(arg){

                }
            })
        }
    </script>

</body>
</html>
user_list.html

二、views增長以下內容:

from django.shortcuts import HttpResponse
def ajax_data(request):
    print request.POST
    return HttpResponse("ok")
View Code

三、urls內容:

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^user_list/$', views.user_list),
    url(r'^ajax_data/$', views.ajax_data),
]
urls

提交的數據內容以下:爲字典類型

 

Ajax發送複雜數據類型(數組、字典)
一、user_list.html
{% load form_tag %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .form-control{    {% comment %}經過attr增長的屬性,能夠在html中加以利用,或者在這裏能夠本身定義屬性,實現渲染頁面渲染功能{% endcomment %}
            background-color: red;
        }
    </style>
</head>
<body>
    <form action="/user_list/" method="post">       {% comment %}此處的action必須是以/開頭和結尾{% endcomment %}
       <p>用戶類型: {{ obj.user_type }}
           <span>{% error_message errors.user_type %}</span>
       </p>
       <p>主機: {{ obj.host }}\
           {% comment %}{% errors.host[0][0] %}{% endcomment %}       {% comment %}  //模板語言不支持索引取值。因此須要構造simple_tag在python中來實現索引取值//{% endcomment %}
           <span>{% error_message errors.host %}</span>
       </p>
       <p>端口:  {{ obj.port }}<span>{{ errors.port }}</span></p>
       <p>郵箱:  {{ obj.email }}<span>{{ errors.email }}</span></p>
        <p>手機: {{ obj.mobile }}<span>{{ errors.mobile }}</span></p>
        <p>備註: {{ obj.memo }}<span>{{ errors.mome }}</span></p>
        <input type="submit" value="submit" />

    </form>
    <input type="button" onclick="AjaxSumbit();"  value="Ajax提交" />
    <input type="button" onclick="AjaxSubmitSet();"  value="Ajax提交集合" />
    <table border="1">
        <thead>
            <tr>
                <th>主機名</th>
                <th>端口</th>
            </tr>
        </thead>
        <tbody id="tbd">
            <tr>
                <th>1.1.1.1</th>
                <th>9999</th>
            </tr>
            <tr>
                <th>1.1.1.1</th>
                <th>9998</th>
            </tr>
        </tbody>
    </table>
    <script src="/static/jquery-1.8.2.min.js"></script>
    <script>
        function AjaxSumbit(){
            var host='1.1.1.1';
            var port='9999';
            $.ajax({
                'url':"/ajax_data/",
                type:"POST",
                data:{h:host,p:port},
                success:function(arg){

                }
            })
        }

        function AjaxSubmitSet(){    #傳送字典
            var array_users=[
                {'username':'alex','age':18},
                {'username':'Chales','age':17},
                {'username':'eric','age':16}
            ];
            $.ajax({
                url:"/ajax_data_set/",
                type:'POST',
                data:{data:array_users},
                success:function(arg){

                }
            })
        }
    </script>

</body>
</html>
View Code
二、views
def ajax_data_set(request):
    print request.POST
    return HttpResponse("ok")
views
三、urls
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^user_list/$', views.user_list),
    url(r'^ajax_data/$', views.ajax_data),
    url(r'^ajax_data_set/$', views.ajax_data_set),
]
urls

可是上述提交的內容,不是原生的字符串,不是咱們想要的,看下面:
在原來的基礎上添加內容:
        function AjaxSubmitSet(){
            var array_users=[
                {'username':'alex','age':18},
                {'username':'Chales','age':17},
                {'username':'eric','age':16}
            ];
            $.ajax({
                url:"/ajax_data_set/",
                type:'POST',
                tradition: true,
                data:{data:JSON.stringify(array_users)},   #將上面的字典轉換爲原生的字符串
                success:function(arg){
                }
            })
        }
user_list.html

好,ajax簡單數據和複雜數據的提交完成了,下面開始在後臺進行更新;
一、views
def ajax_data_set(request):
    ret = {'status':True,'error':""}   #將這個結果返回到前端,來查看操做是否正常
    try:
        print request.POST
    except Exception,e:
        ret['status'] = False
        ret['error'] = str(e)
    return HttpResponse(json.dumps(ret))   #成功的話,返回成功,失敗,返回錯誤信息
View Code
二、user_list.html
        function AjaxSubmitSet(){
            var array_users=[
                {'username':'alex','age':18},
                {'username':'Chales','age':17},
                {'username':'eric','age':16}
            ];
            $.ajax({
                url:"/ajax_data_set/",
                type:'POST',
                tradition: true,
                data:{data:JSON.stringify(array_users)},
                success:function(arg){
                    var callback_dict = $.parseJSON(arg);             //將字符串轉換爲對象,相似於json.loads
                    if (callback_dict.status){
                        alert('成功')
                    }else {
                        alert(callback_dict.error);
                    }
                }
            })
        }
user_list.html

 
做業:
    1、登陸頁面,Form驗證,session,登陸成功跳轉到index    redirect跳轉
    2、默認訪問index,點擊登陸跳回登陸頁面
    3、列表頁面
        內容經過model去數據庫中獲取
        model.assert.object.all()綁定到頁面上;
    4、添加頁面(From表單,須要顯示不合法的信息),添加以後,列表頁面增長一條數據;
    5、對列表頁面數據的修改;
        使用以前的進入編輯模式,退出編輯模式;
        具體實現以下:
        使用jQuery,循環全部的數據(表格),點擊保存的時候,自動退出編輯模式,將數據放到一個數組中;array_list = [{'hostname':xxx'},'hostname':xxx'];,
        使用$.ajax(),將每一條數據發送到後臺更新,ajax發送成功以後,表示後臺數據已經更新完成,使用window.location.href=window.location.href將頁面刷新一次,就OK啦;
做業

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django import forms
class LoginForm(forms.Form):
    username = forms.CharField(
        widget=forms.widgets.TextInput(attrs={'class': "form-control","placeholder":"用戶名"})
    )
    password = forms.CharField(
        widget=forms.widgets.PasswordInput(attrs={'class': "form-control","placeholder":"密碼"})
    )
forms

"""s11day18_homework URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url,include
from django.contrib import admin
from cmdb import views

urlpatterns = [
    url(r'^login/', views.login),
    url(r'^index/', views.index),
    url(r'^lists/', views.lists),
    url(r'^add/', views.add),
]
cmdb\urls
#!/usr/bin/env python
#coding:utf-8
from django.shortcuts import render
from cmdb import forms

# Create your views here.

def login(request):
    obj = forms.LoginForm()
    #若是登陸成功,寫入session,跳轉到index頁面(home)
    return render(request,'account/login.html',{'model':obj})

def index(request):
    return render(request,'home/index.html')

def lists(request):
    return render(request,'asset/lists.html')

def add(request):
    return render(request,'asset/import_single.html')
cmdb/views

主頁:

顯示列表:

添加頁面:




Django 獲取多個數據和上傳文件
通常在獲取後臺前端提交的數據的時候,可使用request.POST.get('xxx')來獲取數據,若是對於input標籤,若是是radio就能夠這樣搞了,可是對於checkbox、select(multiple)這樣能夠多選值,就只能獲取第一個值,
因此可使用request.POST.getlist('xxx')來獲取全部選中並提交的值;

若是input 的type爲file,那麼使用request.POST.get('xxxx')獲取的只有文件的名字,可是文件的內容沒有獲取;obj = request.FILES.get('xxx')能夠獲取到
import os
file_path = os.path.join('upload',obj.name)   #上傳到指定的目錄
f = open(file_path,mode="wb")
for i in obj.chunks():    #chunks()返回一個生成器
    f.write(i)
f.close()
須要注意的是,若是是上傳文件,那麼在form的屬性必須加 enctype="multiple/form-data"


Django的FBV和CBV

function base view #以前所有齊FBV
class base view

url.py
url(r'home/',views.Home.as_views()),


views.py
from django.views import View

class(View):
    #在父類Views中有方法dispatch,用於解析request.method,返回method,使用的反射實現的,能夠在子類中重寫該方法,用於咱們定製一些功能,至關於加了裝飾器
    def dispash(self,request)
        #調用父類中的dispatch
        print ('before')
        result = super(Home,self).dispatch(self,request)
        print ('after')
        return result     #返回get/post
    

    def get(self,request):
        pass

   def post(self,request):
       pass

 源碼:

class View(object):
    """
    Intentionally simple parent class for all views. Only implements
    dispatch-by-method and simple sanity checking.
    """

    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    def __init__(self, **kwargs):
        """
        Constructor. Called in the URLconf; can contain helpful extra
        keyword arguments, and other things.
        """
        # Go through keyword arguments, and either save their values to our
        # instance, or raise an error.
        for key, value in six.iteritems(kwargs):
            setattr(self, key, value)

    @classonlymethod
    def as_view(cls, **initkwargs):
        """
        Main entry point for a request-response process.
        """
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))

        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view

    def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)

  

django模板語言中循環字典
{% for k,row in user_dict.items %}
    <li>{{ k }}  {{row}}</li>
{% endfor %}

 

基於正則表達式的url

urls.py
url(r'detail-(\d+).html'.views.detail,name='index')


index.html
{% for k,row in user_dict.items %}
 <li><a target="_blank" href="/detail-{{ k }}.html"  {{row.name}} </a>></li>      //點擊查看詳情
{% endfor %}


views.py
def  details(request,nid):
    detail_info = USER_DICT[nid]
    return render(request,'detail.html' ,{'detail_info':detail_info})

 

Django 路由對應的名稱

url(r'detail-(?P<nid>\d+)-(?P<uid>\d+).html',views.detail,name='index1')

def detail(request,*args,**kwargs):
    pass

在views.py中獲取訪問路徑使用 request.path_info,也能夠在模本語言中使用{{ request.path_info }},不過通常使用name代替.

使用name在模板中傳參數{% url  'index' 1 3 %}/{% url 'index'   nid=1 uid 3% };

若是知道name,須要獲取url,也可使用reverse,from django.urls import reverse     v=reverse('index',args=(90,)),這裏的v就是實際的url; v=reverse('index',kwargs={'nid':99,'uid':88});

 

 

在python3 django中使用mysql,須要注意 

在python3中沒有使用mysqldb,須要安裝pymysql,而後在project同名文件夾下的__init__中,寫入  import pymysql    pymysql.install_as_MySQLdb()

 

django orm 字段參數含義

   db_index     索引

    unique        惟一索引

    unique_for_date

    unique_for_month

    unique_for_year

    auto_now           建立時,自動更新時間

    auth_now_add    更新時,自動更新當前時間

choices     django admin 中下拉框,避免連表查詢

blank    django admin 是否爲空

verbose_name   djano_admin 顯示爲中文

editable     django admin是否能夠被編輯

error_messages   錯誤信息

help_text     django admin 提示

validators    django form,字定義錯誤信息

 

視圖獲取用戶請求信息以及請求頭

在視圖中print request,能夠看到request的類,能夠看到請求的攜帶的變量,好比request.environ(所有是由這個環境變量攜帶進去的),可使用for k,v in request.environ.items():print k,v,能夠打印request的變量的結果,能夠看到有HTTP_USER_AGENT,用於顯示是那種agent請求的,能夠用於對於不一樣的終端顯示不一樣的內容;

request對於不經常使用的變量,沒有提供方法直接獲取(好比request.POST),可使用request.environ['HTTP_USER_AGENT']獲取信息;

 

自定義simple_tag和模板過濾

 

基於cookie實現用戶登陸

#設置cookie,關閉瀏覽器失效

response.set_cookie('key','value')   #設置cookie

response.set_cookie('key','value',max_age=10)   #設置失效時間

current_data = datatime.datetime.utcnow()+datatime.datetime.timedelta(seconds=5)

response.set_cookie('username','value',expires = current_date)

request.COOKIES.get('key')  #獲取cookie

response.set_cookie('key','value',max_age=10)   #設置10s後失效

 能夠設置7天內免登陸的按鈕了;

註銷就是把cookie清除了;

 

使用js獲取cookie,須要引入 juqery.cookie.js插件;

$.cookie('k1')


$(function(){
   var v = $.cookie('per_page_count',{'path':'/user_list/'});
   $("#ps").val(v);

});

function changePagesize(ths) {
    var v = $.(this).val();
    $.cookie("per_page_count",v,{'path':'/user_list/'})     //設置cookie的值爲當前select選擇的值,path表示cookie只有在這個url上才生效,當前頁面受影響;
 }



在views.py中使用:request.cookie.get('per_page_count',10)獲取用戶選擇的數字;

 

基於cookie實現定製顯示數據條數(分頁)

<select  onchange="changePage(this)">
$(function(){
    var v = $.cookie('per_page_count',{'path',"/user_list/"});   /*獲取cooike*/
    $('$ps').val(v);
})

function changePage(ths){   /*select的onchange事件*/
    var = $(ths).val();
    console.log(v);
    $.cookie('per_page_count',v,{'path',"/user_list/"});    /*設置cookie值*/
    location.reload();
}



views.py

def user_list(request):
    curent_page = request.GET.get('p',1)
    current_page = int(curent_page)
    val = request.COOKIES.get('per_page_count',10)
    page_obj = pagination.Page(current_page,len(LIST),val)

 

帶簽名的cookie

response.set_signed_cookie('username','aaaaa',salt='xxx')    #設置加密的cookie

request.get_signed_cookie('username',salt='xxx')   #獲取cookie值,salt加鹽的值,必須相同

 

 獲取表單數據的三種方式

每個對象就是一行數據,每個QuerySet就是一個對象;

 v = models.Business.objects.all().values('id','caption')  :獲取指定的列,也是QuerySet類型,每個元素字典;

 v=models.Business.objects.all().values_list('id','caption')   :獲取的每個元素是元祖;在模板語言中使用  {% for row in v %}   {{ row.0}} {{row.1}} {%endfor%} 來引用;

 

一對多跨表操做

class Host(models.Model):
    nid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32,db_index=True)
    ip=models.IPAddressField(protocol='ipv4',db_index=True)
    port = models.InterField()
    b = models.ForeignKey(tp='Business',to_field='id')

 row.b.id,row.b.caption;   #使用.跨表

v = models.Host.objects.filter(nid__gt=0).values('nid','hostname','b_id','b__caption')    #這裏使用使用'__'雙下劃線進行跨表,不能使用"."跨表了;

v = models.Host.objects.filter(nid__gt=0).values('nid','hostname','b_id','b__caption')    

#也就是從filter後面開始,跨表就只能使用'__'了;

在views.py中打印上面v的各個值: for row in v: print row['nid'],row['hostname'],row['b_id'],row['b_caption'];

                         for row in v2: print row[0],row[1]...

在前端模板中使用使用.了;

 

增長一對多數據

若是在前段使用for循環的時候,須要在表格中展現id,而且使用的是數據庫中表的主鍵,那麼該id有可能不是從1開始的。使用counter就能夠了,每循環一次,+1;

{% for row in v1 %}
    <tr hid="{{row.nid}}"  bid="{{row.b_id}}">
        <td> {{ forloop.counter}} <t/d>        //counter0從0開始
        <td>{{row.ip}} </td>
   </tr>
{%endfor%}

 

使用模態對話框添加數據

.hide {
  display: none 
}

.shade{
    position: fixed:
    top :0;
    right: 0;
    left: 0;
    bottom: 0;
    backgrand:   blank;
    opacity: 0.6:         /*透明度*/
    z-index 100;
}

.add-model{
    positon: fixed:
    height: 300px;
    width:  400px;
    top :100%;
    left:   50%
    z-index: 101;
    boder: 1px solid red;
    backgrand: white:
    margin-left: -200px;
}
<input    type="button"   id="add_host" name="添加">

<div class="shade"> form表單</div>     //背景層
<div class="add-model   hide"> </div>    //遮罩層



<sctipt> 
    $(function(){
       $('#add_host').click(function(){
        $('.shade',.add-model).removeclass('hide');
    
    })
    })    



</script>
    


views.py
def host(request):
    if request.method =='GET':
        pass
    elif: request.method == 'POST':
        h = request.POST.get('hostname')
        i = request.POST.get('ip')
        p = request.POST.get('port')
        b = request.POST.get('b_id')
              #model.HOST.objects.create(hostname=h,ip=i,port=p,b=model.Business.objects.get(id=b))
        model.HOST.objects.create(hostname=h,ip=i,port=p,b_id = b)
        return redirect('/host')     #get請求
  

 

 

Ajax基本內容整理

$.ajax   $.post    $.get     $.getJson   

後臺添加數據的時候,作異常處理;

ret = {'status':True,'error':None,'data':None}

return HttpResponse(json.dumps(ret))

 

success: function(data){
    var obj = JSON.parse(data);    //反序列化
    if obj.status {
         location.reload();
         }
    else {
        $('#error_msg').text(obj.error)
       }
}

 

在編輯刪除表格中的一行數據的時候,刪除數據時候,爲了避免刷新頁面,能夠將含有該行數據的id remove掉就能夠了;

 

data: $('edit_form').serialize();獲取真整個form的數據;

編輯的時候,應該在模態對話框中看到點擊的哪一行的數據,使用id獲取

  
#獲取編輯框的值
$('.edit').click(function(){
        $(.shade,.edit-model).renveclass('hide');
        var bid = $(this).parent().parent().attr('nid');
        var nid = $(this).parent().patent().attr('nid');
        $('#deit_form').find('select').val(bid);
        $('#edit'_form).find('input[name='nid']').val(nid);
       
        $.ajax({
        data: $('#edit-form').serialize();    //獲取表單的數據填寫的數據
        })

})

 

 

 

建立多對多示例

方式1、自定義關係表
class HostToApp(models.Model):
    hobj = models.ForeighKey(to='Host',to_field='nid')
    abj = modes.ForeignKey(to='Appication',to_field='id')

方式2、ManyToManyField

class Application(models.Model):
r = ManyToManyField('HOST')

 

def app(request):
    app_list = models.Application.objects.all()
    for row in app_list:
        print row.name,row.r.all()    #這裏的row.r.all()是一個Host的QuerySet;

 obj.r.add(1)    #增長
 obj.r.add(2)
  obj.r.add(2,3,4)
  obj.r.add(*[1,2,3,4])
  obj.r.remove(1)    相似add
   obj.r.clear()
  obj.r.set([3,5,7])

{% for app in app_list %}
    {{app.name}}
     {% for host in app.r.all %}
         {{ host.hostname}}
      {% endfor %}
{% endfor %}

   
  host_list = request.POST.getlist('host_list')
  obj = models.Application.objects.create(name=app_name)    #這裏的obj和get獲取的同樣
  obj.r.add(*host_list)    #這是針對m2m表host作的操做;



#使用ajax添加數據
def ajax_add_app(request):
    ret = {'status':True,'error':None,'data':None}
    print request.POST.get('user')
    print request.POST.getlist('host_list')
    return Httpresponse(json.dumps(ret))


$("#add_submit_ajax").click(function(){
    $.ajax({
    url: '/ajax_add_app',
    data: {'user':123,''host_list':[1,2,3,4]},
    type:POST,
    dataType: 'jSON',
    traditional: true,      /*若是須要post的數據中有列表,必定要加該參數;若是提交的數據包含在form中,也可使用  data: $('#data-form').serialize(),這樣就不用本身寫data了,提交的字典的name是click的input標籤的name*/
    success: function(obj){
        console.log(obj);
  },
    })
})

 

#編輯數據
$.('.edit').click(function(){
       $('.edit-model',.shaed).removeclass('hide');
          var hid_list = [];
       $(this).parent().prev().children().each(function(){
            var hid = $(this).attr(hid);
            hid_list.push(hid);
          }) 
       $('#edit-form').find('select').val(hid_list);
        //若是發送到後臺
    })    

數據發送到後臺:
    obj= models.Application.objects.get(id=1)
    obj.name = "new name"
    obj.save()
    obj.r.set([1,2,3,4])

 

Models操做(原聲SQL) 

models.TB.objects.create()
models.TB.objects.create(**{})
obj = models.TB(**)
obj.save()

models.TB.objects.all()[7:10]

models.TB.objects.all()
models.TB.objects.update(..)

models.TB.objects.filter(id__in=[1,2,3])

models.TB.objects.filter(單下劃線id)
models.TB.objects.filter(...).delete

models.TB.objects.filter.values()
models.TB.objects.values_list
models.TB.objects.get()
models.TB.objects.filter().update()
models.TB.objects.filter().first()
models.TB.objects.filter(**{})
models.TB.objects.filter(**{})count()
models.TB.objects.filter(雙下劃線跨表)

moels.TB.objects.all().order_by('')
models.TB.objects.distinct()

 

 

Session 

   基於cookie作用於驗證的時候,不要將敏感信息放置到cookie中;

   cookie的優勢:將存儲的壓力放到客戶端了;

    a、session的原理

       cookie是保存在用戶瀏覽器端的鍵值對;

       session是保存在服務器端的鍵值對;

 

session = {
    隨機字符串1: {
      'is_login':True,
      'user':'',
      'nid':
      }
}

發送到客戶端的只有隨機字符串,客戶端請求時只須要將隨機字符串帶着,拿着這個字符串,就能夠查看session的內容了;

 

#在views中設置session
def login(request): if request.method =='GET': return render elif request.method == 'POST': user ==... pwd ==... if user == 'root' and pwd == '123': #生成隨機字符串 #寫到用戶瀏覽器cookie #保存到session #在隨機字符串對應的字典中設置相關內容 request.session['username']=user request.session['is_login'] = True def index(request): #獲取當前用戶的隨機字符串 #根據隨機字符串獲取對應信息 if request.session['is_login']: #拿到隨機字符串,在數據庫中找到字典的對應信息; return Httpresponse(request.session['username']) else: .... 注意:若是要設置新的session,必定要注意新生成一下數據庫,python manage.py makemigrations ...

 

 CSRF

使用form提交,會在頁面生成一個隱藏的input標籤;   


#使用ajax提交,能夠在請求爲get的時候,不將csrftokn加載請求頭上;
{% csrf_token %}
  
    <input type="button" onclick="Do();"  value="Do it"/>
  
    <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
    <script src="/static/plugin/jquery/jquery.cookie.js"></script>
    <script type="text/javascript">
        var csrftoken = $.cookie('csrftoken');
  
        function csrfSafeMethod(method) {
            // these HTTP methods do not require CSRF protection
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));   /*.test表示判斷是否正則表達式*/
        }
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });
        function Do(){
  
            $.ajax({
                url:"/app01/test/",
                data:{id:1},
                type:'POST',
                success:function(data){
                    console.log(data);
                }
            });
  
        }

若是不講csrf的中間件註釋掉,那麼會在所有的接口生效;

全局:

  中間件 django.middleware.csrf.CsrfViewMiddleware

局部:

  • @csrf_protect,爲當前函數強制設置防跨站請求僞造功能,即使settings中沒有設置全局中間件。
  • @csrf_exempt,取消當前函數防跨站請求僞造功能,即使settings中設置了全局中間件。

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

 

緩存 

python的web框架,只有django有緩存;

Django中提供了6種緩存方式:

  • 開發調試
  • 內存
  • 文件
  • 數據庫
  • Memcache緩存(python-memcached模塊)
  • Memcache緩存(pylibmc模塊)
# 此緩存使用python-memcached模塊鏈接memcache

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': '127.0.0.1:11211',
        }
    }

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': 'unix:/tmp/memcached.sock',
        }
    }   

    CACHES = {
        'default': {
            'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
            'LOCATION': [
                ('172.19.26.240:11211,10'),    #加權重
                ('172.19.26.242:11211',11),
            ]
        }
    }

 

from django.views.decorators.cache import cache_page

@cache_page(10)     #10s生效
def cache(request):
    import time
    ctime = time.time()
    return render(request,'cache.html',{'ctime':ctime})


cache.html
   {% load cache %}     //對某一個值進行緩存必須load cache
   <h1>{{ ctime}}</h1>
    {% cache 10 k1%}    //k1是緩存的key,前綴
           <h1>{{ ctime }}</h1>
    {% endcache %}

  

#若是不想要在views中設置,能夠經過中間件進行全局設置; 

MIDDLEWARE = [
        'django.middleware.cache.UpdateCacheMiddleware',    #只有process response ,請求走的時候執行
        # 其餘中間件...
        'django.middleware.cache.FetchFromCacheMiddleware',    #只有process request ,請求來的時候執行
    ]


#在django中緩存有5種配置,3種應用:全局、視圖函數、模板;

若是中間件、views、模板都設置了緩存,那麼會先在全局生效,其次views、再次模板;

 

 信號

若是想在數據庫建立的時候,建立一條記錄(操做日誌);在數據保存以前或者保存以後,生成一條記錄;(咱們最早想到的就是裝飾器了,而後不只要看別人的代碼,還有可能修改源碼);

 

def single(request):
    from app01 import moels
    obj = models.TB(user='root')
    obj.save()

 

 

Django的所有信號

Model signals
    pre_init                    # django的modal執行其構造方法前,自動觸發
    post_init                   # django的modal執行其構造方法後,自動觸發
    pre_save                    # django的modal對象保存前,自動觸發
    post_save                   # django的modal對象保存後,自動觸發
    pre_delete                  # django的modal對象刪除前,自動觸發
    post_delete                 # django的modal對象刪除後,自動觸發
    m2m_changed                 # django的modal中使用m2m字段操做第三張表(add,remove,clear)先後,自動觸發
    class_prepared              # 程序啓動時,檢測已註冊的app中modal類,對於每個類,自動觸發
Management signals
    pre_migrate                 # 執行migrate命令前,自動觸發
    post_migrate                # 執行migrate命令後,自動觸發
Request/response signals
    request_started             # 請求到來前,自動觸發
    request_finished            # 請求結束後,自動觸發
    got_request_exception       # 請求異常後,自動觸發
Test signals
    setting_changed             # 使用test測試修改配置文件時,自動觸發
    template_rendered           # 使用test測試渲染模板時,自動觸發
Database Wrappers
    connection_created          # 建立數據庫鏈接時,自動觸發

 

要註冊信號,須要先導入

   
 # sg.py
    from django.core.signals import request_finished
    from django.core.signals import request_started
    from django.core.signals import got_request_exception

    from django.db.models.signals import class_prepared
    from django.db.models.signals import pre_init, post_init
    from django.db.models.signals import pre_save, post_save
    from django.db.models.signals import pre_delete, post_delete
    from django.db.models.signals import m2m_changed
    from django.db.models.signals import pre_migrate, post_migrate

    from django.test.signals import setting_changed
    from django.test.signals import template_rendered

    from django.db.backends.signals import connection_created
    def f1(sender, **kwargs):
        print("xxoo_callback")
        print(sender,kwargs)
    def f2(sender, **kwargs):
        print("xxoo_callback")
        print(sender,kwargs)
    pre_init.connect(f1)
    pre_init.connect(f2)
    # xxoo指上述導入的內容

須要將上述註冊的頁面導入到project的app下面的__init__.py(這裏也能夠加數據庫的連接)下面,在工程運行的時候,就執行了;

會在觸發views的single函數的建立數據的語句以前,執行上面的f一、f2函數;

 

除了上面內置的信號以外,還能夠自定義信號

sg.py
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

def callback(sender, **kwargs):
    print("callback")
    print(sender,kwargs)
 
pizza_done.connect(callback)

 

 

views.py

  from sg import piazza_done
  piazza_done.send(sender='aaaa',topping=123,size=456)   #自定義信號的觸發能夠由咱們本身決定;在運維的時候,能夠當某一個閾值超過某一個值的時候,觸發信號;

 

Form
http://www.cnblogs.com/wupeiqi/articles/6144178.html

form操做
from django.forms import forms
from django.forms import fields
from django.forms import widget
class FM(forms.Form):
    user = fields.Charfield(
        error_messages = {'required':"用戶名不能爲空"},
        widget = widget.Textarea(attrs = {'class':'c1'})
        )

    pwd = fields.CharField(
       max_length = 12,
        min_length = 6,
        error_messages = {'required':"密碼不能爲空",'min_length':'密碼長度不能小於6','min_length':'密碼長度不能大於12'},
       widget = widget.PasswordInput(attrs = {'class':'c2'})
      )

   email = fields.EmailField(error_messages = {'required':'郵箱不能爲空','invalid':'郵箱格式錯誤'})


fm.html
  <form action='/fm/' method='POST'> 
      {%  csrf_token %}
    <p>{{obj.user}} {{obj.error.user.0}} </p>
    <p>{{obj.pwd}} {{obj.error.pwd.0}} </p>
    <p>{{obj.email}} {{obj.error.email.0}} </p>
    <input type='submit' value='提交'>
  </form>
 

 

 
完成:
    -驗證用戶請求
    - 生成HTML
        (保留上一次提交的數據)
   
自定義:
    - 類
    - 字段(校驗)
    - 插件(生成HTML)


初始化操做:

def fm(request):
    if request.method == 'GET':
        dic = {
        "user":"r1",
        "pwd":"123123",
        "email":'123@123'
        "city1":1,
        "city":2
            }
        obj = FM(initial=dic)
        return render(request,'fm.html',{'obj':obj})
    elif request.method == 'POST':
        obj = FM(request.POST)
        r1 = obj.is_valid()
        if r1:
            models.UserInfo.objects.create(**obj.cleaned_data)
    else:
        return render(request,'fm.html',{'obj':obj})
    return render(request,'fm.html')        
 

  

一大波model操做
http://www.cnblogs.com/wupeiqi/articles/6216618.html #model操做
一、建立數據庫表
class User(models.Model):
    name = models.CharField(max_length=32,db_index=True)
    email = models.CharField(max_length=32,db_index=True)
    class Meta:
        db_table = "tb1"    #數據庫表名
        index_togeher = [('name','email')]    #聯合索引,只生產一個索引文件,能夠再也不上面的兩個字段加索引了,可是這樣是有代價的,緣由:最左前綴的模式
#select * from where name=xx
#select * from name='xx' and email='xx'
#select * from where email ='xx'  #沒法命中索引
        unique_together = (('name','email'))   #是索引,而且是聯合惟一的

       verbose_name = "hahah"   #admin中顯示hahahs
       verbose_name_plural = 'haha'    #admin中顯示haha


class UserType(modes.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    ...              ForeignKey(to="UserType",to_field = 'id',on_delete=CASCADE)   #刪除UserType的數據,將會把User中的關聯數據刪除
    #delete from user where id =1
    # delete from UserType where id =1  報錯
   #UserType.objects.filter(id=1).delete()    使用orm能夠刪除

存在Foreignkey的時候,關於正向操做和反向操做
class UserType(models.Model):
    name = models.CharField(max_length=32)

    def __str__(self):
        return self.name

class User(models.Model):
    user = models.CharField(max_length=32)
    pwd = models.CharField(max_length=64)
    ut = models.ForeignKey(to='UserType',
                           to_field='id',
                           related_name='b',
                           limit_choices_to={'id__gt':5})   #若是這裏是b,那麼item.user_set.all()就變成item.b.all()
    #ut = models.ForeignKey(to='UserType',to_field='id',related_query_name='a')   #若是這裏是b,那麼item.user_set.all()就變成item.a_set.all()


#正向查找
# v = User.objects.all()
# for item in v:
#     item.user
#     item.pwd
#
# User.objects.all().values('user','ut__name')
#

#反向查找
# v = UserType.objects.all()
# for item in v:
#     item.name
#     item.id
#     item.user_set.all()

# UserType.objects.all().values('name','user__pwd')

 

多對多

a.django 建立第三張表
  m2m.remove
  m2m.add
  m2m.set
  m2m.clear
  m2m.filter

b.自定義第三張表(無m2m字段)
   本身鏈表查詢

c.自定義第三張表,(有m2m字段)#推薦
  m2m.filter


class Bolg(models.Model):
    slte = models.CharField(max_length=10)
    m = models.ManyToManyField('Tag',through='B2T',through_fields=['b','t'])

class Tag(models.Model):
    name = models.CharField(max_length=32)

class B2T(models.Model):
    b = models.ForeignKey('Blog')
    t = models.ForeignKey('Tag')

  


二、操做數據庫表
django能夠配置多個數據庫,實現讀寫分離等一些操做,使用models.object.using(xxx)實現;

django 讀寫分離 dbrouter;

QuerySet方法詳細操做:
-返回QuerySet
-extra方法:
對於一些複雜的sql操做,orm沒有提供操做方法,可使用extra,構建子查詢
select 
    id,
    name,
    1,
    func(id),
    select name from tb2 where nid=id;
from 
   tb1;

Entry.objects.extra(select={'cid':"1"})
select 
    *
    1 as cid
from tb1

Entry.objects.extra(select={'new_id':"select col from sometable where othercol = '%s'"},select_params=(1,))
select 
    * (select name from tb2 where nid=id) as new_id
from
    tb1;
...
 

   -和性能相關的兩個:select_related和prefetch_related

def index(request):
    models.UserType.objects.all().values('name', 'user__pwd')
    users = models.User.objects.all()
    for row in users:
        print(row.user,row.pwd,row.ut_id)   #第一次sql請求
        print(row.ut.name)    #再次發起一次sql請求,
        #若是涉及到跨表,就會再次發起sql請求,若是想要僅僅發起一次sql請求,可使用values('user','pwd','ut__name')


    #select_related
        users = models.User.objects.all().select_related('ut')   #會將全部跨表關聯的數據進行一次查詢出來.能夠加多個參數,注意參數只能是關聯的字段,表示也會查詢與ut關聯的表的數據;
        #連表查詢查詢數據是快的,浪費存儲資源,可是查詢速度快了;數據庫範式:foreignkey,onetoone,m2m

    #prefetch_related
    users = models.User.objects.filter(id__gt=30).prefetch_related('ut')
    #select * from users where id>30    --->第一次
    #獲取上一步驟中全部的ut_id=[1,2....]
    #select * from user_type where id in [1,2]    -->第二次
    for row in users:
        print(row.user,row.pwd,row.ut_id)
        print(row.ut.name)

    return HttpResponse('index')

  --日期相關

    dates:獲取年、年月、年月日

    datetimes:

  --row:原生的sql語句       

obj = models.tb.objects.row('select * from tb')
obj = models.tb.objects.row('select nid as id,username as name,email as pwd from tb2')    #這樣就會把tb2的對象賦值給tb了;

或者:
dic = {'id':'nid','name':'username'}
obj = models.tb.objects.row('select nid ,username,email from tb2',dic)  
-aggregate
from django.db.models. import Count,Avg,Max,Min,Sum

result = models.UserInfo.objects.aggregate(n=Count('nid'))
#select count(nid) as n from userinfo
result = models.UserInfo.objects.aggregate(n=Count('nid',distinct=True))  #先去重再聚合


三、數據驗證(很是弱)
full_clean進行驗證
- 每一個字段正則
- clean 事件鉤子
def index(request):
    # models.UserInfo.objects.create(name='root',email='root')
    obj = models.UserInfo(name='charles',email='1111')
    obj.full_clean()   #這裏會作驗證(對全部的字段),若是失敗,直接報錯
    obj.save()
    
    return HttpResponse('index')


class UserInfo(models.Model):
    name = models.CharField(max_length=32)
    email = models.EmailField()
    
    def clean(self):
        from django.core.exceptions import ValidationError
        c = UserInfo.objects.filter(name=self.name).count()
        if c:
            raise ValidationError(message='用戶名已經存在')
 

 

ModelForm(耦合很是強)
一、數據庫驗證
二、數據驗證
對於都行的公司,數據庫操做和業務操做是分離的,直接經過接口或者RPC進行調用;若是數據庫操做和業務操做在一塊兒的時候,可使用modelForm,因此在小型項目或者django admin的時候會使用獲得modelForm;



Form操做
http://www.cnblogs.com/wupeiqi/articles/6144178.html #參考博客
一、數據驗證(強大)
from django.forms import fields
from django.forms import widgets
from django.forms import forms

class UserInfoForm(forms.Form):
    user = fields.CharField(
        required=False,
        widget=widgets.Textarea(attrs={'class':'c1'})
    )

    pwd = fields.CharField(
        max_length=12,
        widget=widgets.PasswordInput(attrs={'class':'c1'})
    )

form的做用:一、數據驗證;二、生成html(在新url,保留上一次提交的數據)

使用新URL操做,用form提交,那麼數據驗證和生成html都會使用;

若是使用Ajax提交,(能夠不使用生成html的功能,也可使用)

二、form操做動態select數據
若是form的類型是
ChoiceField的時候,若是select下拉框的選項比較簡單,不須要動態生成,那麼就能夠直接使用元組寫死就能夠了,若是下拉框的數據有可能變化,那麼就須要藉助數據操做.values('id','name')進行動態獲取數據了;
可是對於choice中的數據,是Form的類第一次實例化的時候就生成了,若是須要從新加載數據,就要重啓web服務了,這個在生成是不能忍受的。因此,解決方式有兩種:直接在form的類實例化的時候,再從新賦值實例化的對象中關於choice
的數據內容(爲最新的數據庫中的數據),或者將該賦值操做放置到Form的類的__init__方法下面,讓每一次刷新頁面,實例化類的時候,從新加載數據,這個是推薦的方式;
forms.py


from app01 import models
from django.forms import fields
from django.forms import widgets
from django.forms import forms

class UserInfoForm(forms.Form):
    user = fields.CharField(
        required=False,
        widget=widgets.Textarea(attrs={'class':'c1'})
    )

    pwd = fields.CharField(
        max_length=12,
        widget=widgets.PasswordInput(attrs={'class':'c1'})
    )

    user_type=fields.ChoiceField(
        # choices=[(1,'普通用戶'),(2,'超級用戶'),],
        # choices=models.UserType.objects.values_list('id','name'),
        choices=[],
        widget=widgets.Select,
    )

    user_type2 = fields.CharField(
        widget=widgets.Select(choices=[])
    )
    def __init__(self,*args,**kwargs):
        super(UserInfoForm,self).__init__(*args,**kwargs)
        self.fields['user_type'].choices = models.UserType.objects.values_list('id', 'name')
        self.fields['user_type2'].widget.choices = models.UserType.objects.values_list('id', 'name')



views.py
from django.shortcuts import render,HttpResponse
from app01 import models

def index(request):
    from app01.forms import UserInfoForm
    obj = UserInfoForm()    #每次刷新的時候,會執行這個操做,將所有的數據封裝在obj中
    return render(request,'index.html',{'obj':obj})

 

除了上面咱們能夠寫動態加載Select數據以外,還django還爲咱們實現了一種比較簡單的方式用於加載Select數據,這不過這種數據加載的時候,被加載的model必須實現__str__方法(這就是代價)

from django.forms.models import ModelChoiceField,ModelMultipleChoiceField
class UserInfoForm(forms.Form):
    user_type3 = ModelChoiceField(
        empty_label='請選擇用戶',
        queryset=models.UserType.objects.all(),
        to_field_name='name',
    )

Form內置鉤子(容許自定義form返回給model的數據)
form內置鉤子查找順序:is_valid()-->self.errors-->self.full_clean(能夠看到form鉤子)
在form數據提交以後,django form會先經過正則表達式驗證提交的數據,而後會執行每個字段對應的鉤子,最後執行總體的鉤子
from django.core.exceptions import ValidationError
class RegisterForm(forms.Form):
    user = fields.CharField()
    email = fields.EmailField()

    def clean_user(self):   #若是user的正則表達式經過以後,執行user_clean方法
        c = models.UserInfo.objects.filter(name=self.cleaned_data['user']).count()
        if not c:
            return self.cleaned_data['user']
        else:
            raise ValidationError('用戶名已經存在',code='xxxx')

    def clean_email(self):
        return self.cleaned_data['email']


class LoginForm(forms.Form):
    user = fields.CharField()
    pwd = fields.CharField(validators=[])

    def clean_user(self):  # 若是user的正則表達式經過以後,執行user_clean方法
        c = models.UserInfo.objects.filter(name=self.cleaned_data['user']).count()
        if not c:
            return self.cleaned_data['user']
        else:
            raise ValidationError('用戶名已經存在', code='xxxx')

    def clean_pwd(self):
        return self.cleaned_data['pwd']

    def clean(self):    #總體的鉤子,會聯合user和pwd另個字段進行鉤子驗證
        c = models.UserInfo.filter(name=self.cleaned_data['user'],pwd=self.cleaned_data['pwd']).count()
        if c:
            return self.cleaned_data
        else:
            raise ValidationError('用戶名或者密碼錯誤')

    def _post_clean(self):
        pass
 
對於錯誤信息:每個errors中保存的是每個字段的錯誤信息,格式以下:
 obj.errors = {
            '__all__':[],  #總體錯誤信息,也就是 clean方法返回的錯誤信息
            'user':[{'code':'required','message':'xxx'}],   #clean_user返回的錯誤信息
            'pwd':[{'code':'required','message':'xxxx'}],  #clean_pwd 返回的錯誤信息
        }


 form表單提交數據以後,執行的順序是:驗證每個form的正則表達式-->clean_user鉤子-->整鉤子clean-->總體鉤子__post_clean
def index(request):
    from app01.forms import UserInfoForm
    if request.method == 'GET':
        obj = UserInfoForm({'user':"charles"})    #每次刷新的時候,會執行這個操做,將所有的數據封裝在obj中;能夠加參數,用戶設置form的默認值;
        return render(request,'index.html',{'obj':obj})
    elif request.method == 'POST':
        obj = UserInfoForm(request.POST,request.FILES)
        obj.is_valid()

def register(request):
    from app01.forms import RegisterForm
    obj = RegisterForm(request.POST)
    if obj.is_valid():
        obj.cleaned_data
    else:
        obj.errors
       

Form內置序列化錯誤信息
對於form錯誤信息,使用form實例化對象的.errors方法獲取的,form的全部錯誤信息都會封裝在這個對象中,django提供了.errors()對象的兩個經常使用的序列化操做方法:as_json和as_data;
使用as_json: 缺點是在前端獲取.errors對象的元素,顯示在指定的位置,須要方序列化兩次
import json
from django.shortcuts import render,HttpResponse

from django.forms import fields
from django.forms import widgets
from django.forms import forms


class LoginForm(forms.Form):
    username = fields.CharField()
    password = fields.CharField(
        max_length=64,
        min_length=12,
    )


from django.core.exceptions import ValidationError
def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    elif request.method == "POST":
        ret = {'status':True,'error':None,'data':None}
        obj = LoginForm(request.POST)
        if obj.is_valid():
            print(obj.cleaned_data)
        else:
            print(type(obj.errors))   # <class'django.forms.utils.ErrorDict'>
            #from django.forms.utils import ErrorDict

            print(obj.errors.as_json())
            """
            在前端分序列化輸出結果:
            Object {data: null, error: "{"password": [{"message": "Ensure this value has                            a…characters (it has 10).", "code": "min_length"}]}", status: true}
            data
            :
            null
            error
            :
            "{"password": [{"message": "Ensure this value has at least 12 characters (it has 10).",               "code": "min_length"}]}"
            status
            :
            true
            __proto__
            :
            Object
            ret['error'] = obj.errors.as_json()   #在前端須要loads兩次
        return HttpResponse(json.dumps(ret))

使用as_data: password [ValidationError(['Ensure this value has at least 12 characters (it has 10).'])]  ValidationError沒法序列化的,須要單獨作處理(自定義encoder實現)

import json
from django.shortcuts import render,HttpResponse

from django.forms import fields
from django.forms import widgets
from django.forms import forms


class LoginForm(forms.Form):
    username = fields.CharField()
    password = fields.CharField(
        max_length=64,
        min_length=12,
    )


from django.core.exceptions import ValidationError
class JsonCustomEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o,ValidationError):
            return {'code':o.code,'messages':o.messages}   #能夠查看源碼
        else:
            return json.JSONEncoder.default(self,o)

def login(request):
    if request.method == 'GET':
        return render(request,'login.html')
    elif request.method == "POST":
        ret = {'status':True,'error':None,'data':None}
        obj = LoginForm(request.POST)
        if obj.is_valid():
            print(obj.cleaned_data)
        else:
            print(type(obj.errors.as_data()))    #<class 'dict'>
            for k,v in obj.errors.as_data().items():
                print(k,v)      #password [ValidationError(['Ensure this value has at least 12 characters (it has 10).'])]
            ret['error'] = obj.errors.as_data()
        result = json.dumps(ret,cls=JsonCustomEncoder)   #cls指定經過哪一個類進行序列化操做
        return HttpResponse(json.dumps(result))

 

前端代碼展現:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
login.html
<form id="fm">
    {% csrf_token %}
    <p><input type="text" name="username"></p>
    <p><input type="password" name="password"></p>
    <a id="submit">提交</a>
</form>

<script src="/static/jquery-3.2.1.min.js"></script>
<script>
    $(function () {
        $('#submit').click(function () {
            $.ajax({
                url: '/login.html',
                type:'POST',
                data:$('#fm').serialize(),
                success:function (arg) {
                    console.log(arg);
                    arg  =  JSON.parse(arg);
                    console.log(arg);
                }
            })
        })
    })
</script>
</body>
</html>

 

ValidationError代碼以下:
"""
Global Django exception and warning classes.
"""
from django.utils import six
from django.utils.encoding import force_text


class FieldDoesNotExist(Exception):
    """The requested model field does not exist"""
    pass


class DjangoRuntimeWarning(RuntimeWarning):
    pass


class AppRegistryNotReady(Exception):
    """The django.apps registry is not populated yet"""
    pass


class ObjectDoesNotExist(Exception):
    """The requested object does not exist"""
    silent_variable_failure = True


class MultipleObjectsReturned(Exception):
    """The query returned multiple objects when only one was expected."""
    pass


class SuspiciousOperation(Exception):
    """The user did something suspicious"""


class SuspiciousMultipartForm(SuspiciousOperation):
    """Suspect MIME request in multipart form data"""
    pass


class SuspiciousFileOperation(SuspiciousOperation):
    """A Suspicious filesystem operation was attempted"""
    pass


class DisallowedHost(SuspiciousOperation):
    """HTTP_HOST header contains invalid value"""
    pass


class DisallowedRedirect(SuspiciousOperation):
    """Redirect to scheme not in allowed list"""
    pass


class TooManyFieldsSent(SuspiciousOperation):
    """
    The number of fields in a POST request exceeded
    settings.DATA_UPLOAD_MAX_NUMBER_FIELDS.
    """
    pass


class RequestDataTooBig(SuspiciousOperation):
    """
    The size of the request (excluding any file uploads) exceeded
    settings.DATA_UPLOAD_MAX_MEMORY_SIZE.
    """
    pass


class PermissionDenied(Exception):
    """The user did not have permission to do that"""
    pass


class ViewDoesNotExist(Exception):
    """The requested view does not exist"""
    pass


class MiddlewareNotUsed(Exception):
    """This middleware is not used in this server configuration"""
    pass


class ImproperlyConfigured(Exception):
    """Django is somehow improperly configured"""
    pass


class FieldError(Exception):
    """Some kind of problem with a model field."""
    pass


NON_FIELD_ERRORS = '__all__'


class ValidationError(Exception):
    """An error while validating data."""
    def __init__(self, message, code=None, params=None):
        """
        The `message` argument can be a single error, a list of errors, or a
        dictionary that maps field names to lists of errors. What we define as
        an "error" can be either a simple string or an instance of
        ValidationError with its message attribute set, and what we define as
        list or dictionary can be an actual `list` or `dict` or an instance
        of ValidationError with its `error_list` or `error_dict` attribute set.
        """

        # PY2 can't pickle naive exception: http://bugs.python.org/issue1692335.
        super(ValidationError, self).__init__(message, code, params)

        if isinstance(message, ValidationError):
            if hasattr(message, 'error_dict'):
                message = message.error_dict
            # PY2 has a `message` property which is always there so we can't
            # duck-type on it. It was introduced in Python 2.5 and already
            # deprecated in Python 2.6.
            elif not hasattr(message, 'message' if six.PY3 else 'code'):
                message = message.error_list
            else:
                message, code, params = message.message, message.code, message.params

        if isinstance(message, dict):
            self.error_dict = {}
            for field, messages in message.items():
                if not isinstance(messages, ValidationError):
                    messages = ValidationError(messages)
                self.error_dict[field] = messages.error_list

        elif isinstance(message, list):
            self.error_list = []
            for message in message:
                # Normalize plain strings to instances of ValidationError.
                if not isinstance(message, ValidationError):
                    message = ValidationError(message)
                if hasattr(message, 'error_dict'):
                    self.error_list.extend(sum(message.error_dict.values(), []))
                else:
                    self.error_list.extend(message.error_list)

        else:
            self.message = message
            self.code = code
            self.params = params
            self.error_list = [self]

    @property
    def message_dict(self):
        # Trigger an AttributeError if this ValidationError
        # doesn't have an error_dict.
        getattr(self, 'error_dict')

        return dict(self)

    @property
    def messages(self):
        if hasattr(self, 'error_dict'):
            return sum(dict(self).values(), [])
        return list(self)

    def update_error_dict(self, error_dict):
        if hasattr(self, 'error_dict'):
            for field, error_list in self.error_dict.items():
                error_dict.setdefault(field, []).extend(error_list)
        else:
            error_dict.setdefault(NON_FIELD_ERRORS, []).extend(self.error_list)
        return error_dict

    def __iter__(self):
        if hasattr(self, 'error_dict'):
            for field, errors in self.error_dict.items():
                yield field, list(ValidationError(errors))
        else:
            for error in self.error_list:
                message = error.message
                if error.params:
                    message %= error.params
                yield force_text(message)

    def __str__(self):
        if hasattr(self, 'error_dict'):
            return repr(dict(self))
        return repr(list(self))

    def __repr__(self):
        return 'ValidationError(%s)' % self

 

Django序列化操做

 

#使用django內置的序列化工具
def register(request):
    from django.core import serializers
    v = models.UserType.objects.all()
    data = serializers.serialize("json",v)    #序列化成json的對象
    return HttpResponse(data)

#序列化的結果
"""
[{"model": "app01.usertype", "pk": 1, "fields": {"name": "\u666e\u901a\u7528\u6237"}}, {"model": "app01.usertype", "pk": 2, "fields": {"name": "\u8d85\u7ea7\u7528\u6237"}}, {"model": "app01.usertype", "pk": 3, "fields": {"name": "\u53ea\u8bfb"}}, {"model": "app01.usertype", "pk": 4, "fields": {"name": "\u6d4b\u8bd5"}}, {"model": "app01.usertype", "pk": 5, "fields": {"name": "\u54c7\u54c8"}}]
"""


#json.dumps
def register(request):
    import json
    v = models.UserType.objects.values('id','name')
    v = list(v)
    return HttpResponse(json.dumps(v))
#序列化結果
"""
[{"name": "\u666e\u901a\u7528\u6237", "id": 1}, {"name": "\u8d85\u7ea7\u7528\u6237", "id": 2}, {"name": "\u53ea\u8bfb", "id": 3}, {"name": "\u6d4b\u8bd5", "id": 4}, {"name": "\u54c7\u54c8", "id": 5}]
"""

 

小結:

ErrorDict
    - 自定義encoder
QuerySet
    第一種:
        from django.core import serializera
       v = models.tb.objects.all()
        data = serializera.serializera("json",v)
    第二種:
        import json
        from datetime import date
        from datetime import datetime
        
        class JsonCustomEncoder(json.JSONEncoder):
            pass

        v = models.TB.objects.values('id','name','ctime')
        v = list(v)
        v = json.dumps(v,cls=JsonCustomEncoder)

 

ModelForm

http://www.cnblogs.com/wupeiqi/articles/6229414.html   #modelForm參考博客

內容回顧:

 

Model
    - 數據庫操做
    - 驗證

Form
    - class LoginForm(Form)
        email = fields.EmailField()
    - is_valid ->每個字段正則(字段內置的正則)+clean_字段 -> clean(__all__) ->post_clean
    - cleand_data
    - errors

 

Model +Form=>驗證 + 數據庫操做

一、生成html標籤:class Meta: ...

二、生成默認值:mf = xxxModelForm(instance=Modelobj)

三、額外的標籤:is_rmb = Ffield.CharField(widget=Fwidgets.CheckboxInput())

四、各類驗證:is_valid() -->各類鉤子

五、mf.save()== instance = ms.save(False) instance.save() mf.save_m2m()

 

Ajax

http://www.cnblogs.com/wupeiqi/articles/5703697.html    #ajax全套參考博客

原聲生ajax:是由XMLhttpRequest對象建立的;

POST請求的時候須要加特殊的請求頭;

 

    <input type="text" />
    <input type="button" value="Ajax1" onclick="Ajax1();" />
    <script>
        function Ajax1() {
            var xhr = new XMLHttpRequest();
            //xhr.open('GET','/ajax_json/',true);     /*true表示是否異步*/
            xhr.open('POST','/ajax_json/',true);     /*true表示是否異步*/
            xhr.onreadystatechange = function () {
                if(xhr.readyState == 4){
                    //數據接收完畢
                    console.log(xhr.responseText);   //接收到的數據
                    var obj = JSON.parse(xhr.responseText);
                    console.log(obj);
                }
            };
            xhr.setRequestHeader('k1','v1');   //加任意的請求頭
            xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset-UTF-8');    //若是是POST請求,必須加這個加這個請求頭
            xhr.send("name=root;pwd=123");     /*發送的數據*/
        }
    </script>

 

 

僞造ajax請求:form+iframe實現

    <form action="/ajax_json/" method="POST" target="ifm1">
        <iframe name="ifm1"></iframe>
        <input type="text" name="username" />
        <input type="text" name="email" />
        <input type="submit" value="form提交" />
    </form>

 

時機:
    若是發送的是普通的數據-->jquery,xmlhttprequest,iframe

  

#iframe發送數據,而且獲取發送的數據

    <form action="/ajax_json/" method="POST" target="ifm1">
        <iframe  id="ifm1" name="ifm1"></iframe>
        <input type="text" name="username" />
        <input type="text" name="email" />
        <input type="submit" onclick="submitForm();"  value="form提交" />
    </form>

        function submitForm() {
            $('#ifm1').load(function () {
                var test = $('#ifm1').content().find('body').text();
                var obj = JSON.parse(test);
                console.log(obj);
            })
        }

 

偷偷發請求的三種方式:

一、jquery ajax
二、xmlhttprequest
二、form+iframe

 

ajax上傳文件的三種方式: 一、使用xhr提交;二、使用jquery提交(依賴FormData);三、使用iframe提交(優先); 

 

圖片預覽:

 

#圖片提交上傳以後,就能夠預覽到圖片內容   


<form id="fm1" action="/upload_file/" method="POST" enctype="multipart/form-data" target="ifm1">
        <iframe  id="ifm1" name="ifm1"  style="display: none;"></iframe>
        <input type="file" name="fa" onchange="changeUpload();"/>    //使用js提交
{#        <input type="submit" onclick="iframeSubmit();"  value="form提交" />#}   //使用form提交
    </form>
    <div id="preview"></div>


   function changeUpload() {
        $('#ifm1').load(function () {
        var test = $('#ifm1').content().find('body').text();
        var obj = JSON.parse(test);
        $('#preview').empty();
        var imgTag = document.createElement('img');
        imgTag.src = "/"+ obj.data;
        $("#preview").append(imgTag);
        });
        $('#fm1').submit();
    }
    
    function iframeSubmit() {
        $('#ifm1').load(function () {
            var test = $('#ifm1').content().find('body').text();
            var obj = JSON.parse(test);
            $('#preview').empty();
            var imgTag = document.createElement('img');
            imgTag.src = "/"+ obj.data;
            $("#preview").append(imgTag);
    })
    }

 

圖片驗證碼 

 - session

 - check_code.py (依賴:pillow,字體文件)

 - src屬性後面加? :用於從新發送請求,生成圖片

 

 

http://www.cnblogs.com/wupeiqi/articles/6307554.html   #kindEditor參看博客

http://kindeditor.net/docs/   #官網

 

組合搜索組件

     分爲:搜索類型存在數據庫和內存中兩種;

相關文章
相關標籤/搜索