Django的開始

一 瀏覽器相關知識css

 http:只有依賴一回,屬於短連接,不會報錯客戶端的信息。html

 瀏覽器至關於一個客戶端,客戶端的連接前端

 服務端:socket服務端,起服務監聽客戶端的請求。python

import socket
sk=socket.socket()
sk.bind(('192.168.11.38',8888))
sk.listen(5)

def index():
    with open('輪播網頁.html',encoding='utf-8')as f:
        ret=f.read()
        return ret
def login():
    with open('login.html',encoding='utf-8')as f:
        ret=f.read()
    import pymysql
    conn=pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        passwd='0410',
        db='day46'
    )
    cursor=conn.cursor()
    cursor.execute('select * from user')
    user_list=cursor.fetchall()
    cursor.close()
    conn.close()
    res=''
    for i in user_list:
        res += '''
        <tr>
            <td>{}</td>
            <td>{}</td>
            <td>{}</td>
        </tr>
        '''.format(i[0], i[1], i[2])
    tables= ret.replace('@@xx@@',res)
    return tables




def info():
    return "這是我的信息"

info_index=[
    ('/login/',login),
    ('/index/',index),
    ('/info/',info)
]
while True:
    conn,addr=sk.accept()
    print(addr)
    data=conn.recv(8096)
    data3=str(data,encoding='utf-8')
    data1=data3.split('\r\n\r\n')[0]
    print('*'*50)
    print(data1)
    data2=data1.split('\r\n')[0].split(' ')[1]
    print(data2)
    ingo_name=None
    for i in info_index:
        if data2==i[0]:
            ingo_name=i[1]
            break
    if ingo_name:
        response=ingo_name()
    else:
        response='404'

    conn.send(b'HTTP/1.1 200 0k\r\nContent-Type:text/html;charset=utf-8\r\n\r\n')
    conn.send(response.encode('utf-8'))
    conn.close()
View Code

二 框架的介紹mysql

 tornado:模版都是人家寫好的,咱們只管拿來使用。jquery

 Django:服務端能夠本身寫,其餘的模版都是別人寫好的。web

 flask:服務端和模版渲染都是本身寫的,函數的功能都是別人寫好了的。ajax

 全部的web框架叫作web應用服務器。正則表達式

三 django的安裝和使用sql

 安裝:pip install django。

 建立項目:django-admin startproject 項目名

 手動建立:

 查看參數:django-admin。

 開啓項目:python manage.py runserver

 使用命令建立app:atsrtapp app名

  配置文件的INSTALLED_APPS添加'rbac.apps.RbacConfig',

 響應格式:

  {

  "接收到的想要":回覆

。。。。。

  }

 相關文件夾:

  manage.py:全部django命令,全部的django項目相關的都是基於manage這個文件實現的。

  settings.py:配置文件,客戶端能夠直接訪問這裏面的一些文件

  urls.py:函數功能,url內部給函數自動傳入了一個參數,就是request參數。

   若是想要獲取到url裏面的內容,使用正則表達式裏面的分組,將要獲取的內容括起來,而後會被看成實參傳入到函數功能裏面去。

url配置:
	   注意:url:匹配的是url的路徑部分
       import re
       re.findall("^articls/2004/$","articls/2004/asdsa")
	   
	無名分組:
       # url(r'^articls/(\d{4})/(\d{2})$', views.archive3,),  # archive2(request,2000,11)	     
	
    有名分組:
      # url(r'^articls/(?P<y>\d{4})/(?P<m>\d{2})$', views.archive4,), # archive2(request,y=2000,m=11) 

   blog分發:將一個大的urls文件進行分組,分紅多個小的urls文件,而後再在大的urls文件裏面調用這些小的urls文件。

小urls文件
from django.conf.urls import url, include
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^articls/2004/$', views.archive, ),  # 徹底匹配 #  archive(request)
    url(r'^articls/(?P<y>\d{4})/(?P<m>\d{2})$', views.archive4, ),  # archive2(request,y=2000,m=11)
]


大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'^index/', views.index),
    url(r'^login.html/', views.login,name="laogou"), # login(request)
    url(r'^foo/', views.foo), # login(request)

    ##############路由分發####################

    url(r'^app01/', include('app01.urls')) ,  # /app01/articls/2004


]
View Code

  wsgi.py :socketserver相關,wsgi文件和django結合使用的,django是沒有服務端的,而wsgi文件爲django提供了一個服務端。

   wsgi文件是一種協議,是web網關接口,分別有兩種:wsgiref和uwsgi。

    wsgiref是能夠實現基本的,大多數用來調試的。

    uwsgi是用於企業的。

    wsgi導入的文件是:

from django.core.wsgi import get_wsgi_application

  app文件:project  :主要用於業務的分類,是整個項目下的一個程序

   主站,app:專門處理相關的業務,啓動app的web命令:

python manage.py startapp web

   後臺管理 app:啓動app的backend命令:

python manage.py startapp backend

  models文件:主要是寫web應用相關的內容。

四 使用

 views視圖分爲兩大塊:一個是請求對象,另外一個是響應對象。

  請求對象request:表明全部請求的內容

   request.method:獲取請求,請求的方法具體是什麼

   request.POST.get('***'):以什麼途徑發送的請求

   request.GET.get(‘***’):從url中獲取具體的什麼數據或者內容,在後端函數裏面須要使用GET

   request.POST.getlist:同時能夠獲取多個值,全部的值都是在一個列表裏面

   request.encoding:請求的格式

   request.path 和request.info:請求路徑的內容,沒有數據內容

   request.get_full_path:請求路徑的內容,還有數據的內容

def archive(request):
    print(request.path)  # /app01/articls/2004/
    print(request.path_info)  # /app01/articls/2004/
    print(request.get_full_path())  # /app01/articls/2004/?a=1

   request.is_ajax:判斷此次的請求是否是ajax請求

   還有request.COOKICS;request.session;request.path等

    GET:
			
		URL: 127.0.0.1:8000/class_list/?name=alex&age=18
		
		request.GET.get("name")			
		request.GET.get("age")	
		
	
	POST:
		
		<form class="form-horizontal" action="/add_class/" method="post">
			<div class="form-group">
				<label for="inputclassname" class="col-sm-2 control-label">班級名稱</label>
				<div class="col-sm-10">
					<input name="class_name" type="text" class="form-control" id="inputclassname" placeholder="班級名稱">
				</div>
			</div>
			<div class="form-group">
				<div class="col-sm-offset-2 col-sm-10">
					<button type="submit" class="btn btn-default">提交</button>
				</div>
			</div>
		</form>

 request.body:全部的請求數據都會在這裏面。

from django.shortcuts import render,HttpResponse

# Create your views here.


def login(request):
    if request.is_ajax():
        print(request.body) # b'{"user":"alex","pwd":"123"}'
        # b'user=alex&pwd=123&csrfmiddlewaretoken=PCLE4jNWOmLcmd5LiY1qrwTWQZLpZdSktwwwPswNKg7DhblKO6X1fBDkB05yoNMm'
        print(request.POST) # {'user': ['alex'], 'pwd': ['123'], 'csrfmiddlewaretoken': ['PCLE4jNWOmLcmd5LiY1qrwTWQZLpZdSktwwwPswNKg7DhblKO6X1fBDkB05yoNMm']}
        print(request.GET)  # {}

        # user=request.POST.get("user")
        # pwd=request.POST.get("pwd")
        #
        # print(user,pwd)
        # print("=======")
        # import json
        # s=request.body.decode("utf8")
        # d=json.loads(s)
        # print(d.get("user"))
        # print(d.get("pwd"))
        return HttpResponse("OK")


    return render(request,"index.html")



def reg(request):
    if request.is_ajax():
        print(request.POST,"=======")

        return HttpResponse("OK")

    return render(request,"reg.html")
View Code

 request.FILES:文件上傳的地方接收到的是一個文件對象,也就是一個文件句柄,直接.name就是文件名字。

from django.shortcuts import render,HttpResponse

# Create your views here.



def index(request):

    # #print(request.body)
    # print(request.POST) # <QueryDict: {'csrfmiddlewaretoken': ['2Fq1vmv59yRSUxDwlkym3qmk5bNpfdHLGzbTgveW5sdjPvTvRsuXRv6IQc7yENBN'], 'user': ['yuan'], 'cFile': ['day76.txt']}>
    # print(request.FILES)
    #
    # file_obj=request.FILES.get("cFile")
    # name=file_obj.name
    # print(name)  # day76.txt
    # import os
    #
    # from filePut import settings
    # path=os.path.join(settings.BASE_DIR,"app01","static",name)
    # with open(path,"wb") as f_write:
    #     for line in file_obj:
    #         f_write.write(line)





    return render(request,"index.html")



def indexAjax(request):
    print(request.body)
    print(request.POST)
    print(request.GET)

    # print(request.POST)
    # print(request.FILES)
    # file_obj=request.FILES.get("cFile")
    # name=file_obj.name
    # print(name)  # day76.txt
    # import os
    #
    # from filePut import settings
    # path=os.path.join(settings.BASE_DIR,"app01","static",name)
    # with open(path,"wb") as f_write:
    #     for line in file_obj:
    #         f_write.write(line)

    return HttpResponse("123421")
View Code

 新手三件套:

  導入:from django.shortcuts import

   HttpResponse:http的響應,裏面只可以方字符串

   render:渲染,一次請求一次響應。每請求一次就會被渲染。

    render(request, 'html文件')

    render(request,"html文件",{"替換的內容":值})

    render(request,"html文件",locals())   :局部的變量均可以在HTML文件裏面使用

   redirect:跳轉頁面,重定向這一次請求,重定向時,須要多發送一次請求。

			以登陸爲例:
			    第一次請求:
			        請求url: http://127.0.0.1:8000/login.html/      GET     無請求數據
					login.html/-------> views.login------>login()
					響應到一個login.html頁面
					
				第二次請求:
                     請求url: http://127.0.0.1:8000/login.html/     POST    有請求數據  {"user":"alex","pwd":"123"}
  					 login.html/-------> views.login------>login()
					 響應的return redirect("/index/")到瀏覽器,通知瀏覽器再發送請求:"/index/"
					 
					 請求url: http://127.0.0.1:8000/index/       get請求   沒有數據
					 index/ --->url(r'^index/', views.index),---->index()
					 
					 響應一個index.html
from django.conf.urls import url
from django.contrib import admin
from django.shortcuts import render,redirect



def mysql():
    import pymysql
    user_dic = {}
    conn=pymysql.connect(host="127.0.0.1", port=3306, user="root", passwd="0410", db="day43", charset="utf8")
    cursor=conn.cursor()
    cursor.execute('select name,password from user')
    user_list = cursor.fetchall()
    cursor.close()
    conn.close()
    for user in user_list:
        user_dic[user[0]]=user[1]
    return user_dic


def login(request):
    if request.method=='GET':
        return render(request,'登錄界面.html')
    else:
        user_dic=mysql()
        for user in user_dic:
            if request.POST.get('user')==user and request.POST.get('passwd')==user_dic[user] and request.POST.get('pwd')==user_dic[user]:
                return redirect('http://www.xiaohuar.com/hua/')
            elif request.POST.get('user')==user and request.POST.get('passwd')==user_dic[user] and request.POST.get('pwd')!=user_dic[user]:
                return render(request, '登錄界面.html', {'error_msg': '密碼輸入不一致'})
        else:
            return render(request,'登錄界面.html',{'error_msg':'用戶名和密碼錯誤'})

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/',login)
]
View Code

 http就是基於一次請求一次響應的。

 模版語言:

  格式1:

   {% for i in **%}

    {{x}}

   {% endfor %}

  格式2:

   {{ 變量名 }}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .c1 {
            width: 100%;
            height: 50px;
            background-color:#DDDDDD;
            opacity: 0.3;
        }

        .c4{
            width:80%;
            height:50px;
            background-color:#DDDDDD;
            margin-left: 10%;
        }

        .c7{
            width: 100px;
            height: 50px;
            float:left;
        }

        .c8{
            width: 80px;
            height: 50px;
            float:right;
        }

        .c9{
            width: 120px;
            height: 50px;
            float:right;
        }

        .c10{
            width: 80px;
            height: 50px;
            float:right;
        }

        .c11{
            width: 80px;
            height: 50px;
            float:right;
        }

         .c12{
             width: 50px;
             height: 50px;
             float:right;
        }

        .s1{
            line-height:50px;
            text-align: center;
            color:#1F1E1E;
        }

        .c2{
            width:100%;
            height: 60px;
            background-color: #ffffff;
            margin-top: 20px;
        }

        .c5{
            width: 80%;
            height: 60px;
            background-color: #FFFFFF;
            margin-left: 10%;
        }
        .c3{
            width:100%;
            height:auto;

        }

        .c6{
            width: 80%;
            height: auto;
            margin-left: 10%;
        }

        .d1{
            width: 500px;
            height: 400px;
            float: left;
            margin-top: 50px;
        }

        .d3{
            width: 500px;
            height: 50px;
            margin-top:60px;
        }

        .s2{
            font-weight:600;
            font-size:30px;
            color: #2e2e2e;
            line-height:50px;
            margin-left: 70px;

        }

        .p1{
            margin-left: 120px;
        }

        .p2{
            margin-left: 104px;
        }


        .i2{
            margin-left: 15px;
        }

        .s3{
            color:red;
        }

        .p4{
            margin-left: 150px;
        }

        .s4{
            color:#0000CC;
        }

        .i3{
            font-size: 14px;
        }


        .p5{
            margin-left: 200px;
        }

        .i5{
            font-size: 10px;
             background-color:red;
        }

        .d2{
            width: 314px;
            height:400px;
            float: right;
            margin-top: 50px;
        }

        .p6{
            margin-left:30px;
        }


        .p7{
            margin-top: 50px;
        }

    </style>
</head>
<body>

<div class="c1">
    <div class="c4">
        <div class="c7"><span class="s1">*收藏網址</span></div>
        <div class="c8"><span class="s1">客戶服務</span></div>
        <div class="c9"><span class="s1">VIP會員俱樂部</span></div>
        <div class="c10"><span class="s1">個人訂單</span></div>
        <div class="c11"><span class="s1">免費註冊</span></div>
        <div class="c12"><span class="s1">登錄</span></div>
    </div>
</div>
<div class="c2">
    <div class="c5"><img src="111.png" alt="悟空"></div>
</div>
<div class="c3">
    <div class="c6">
        <div class="d1">
            <div class="d3"><span class="s2">註冊新用戶</span></div>
            <form action="/login/" method="post">
                <p class="p1"><span class="s3">*</span>用戶名:<input type="text" name="user" class="i2"></p>
                <p class="p1"><span class="s3">*</span>手機號:<input type="text" name="phone" class="i2"></p>
                <p class="p2"><span class="s3">*</span>登錄密碼:<input type="password" name="passwd" class="i2"></p>
                <p class="p2"><span class="s3">*</span>確認密碼:<input type="password" name="pwd" class="i2"></p>
                <p class="p4"><input type="checkbox" name="ppp"><span class="i3">我已閱讀並贊成</span><span class="s4 i3">《用戶註冊協議》</span> </p>
                <p class="p5"><input type="submit" value="開始登陸" class="i5"></p>
                {{ error_msg }}
            </form>
        </div>
        <div class="d2">
            <p class="p6 p7"><img src="222.png" alt="悟天" width='250px' height="200px"></p>
        </div>
    </div>
</div>
</body>
</html>
View Code

 empty:for循環爲空的時候須要執行的任務

        {% for teacher in  teacher_list %}
		要作的事兒
	{% empty %}
		要作的事兒
	{% endfor %}        

 if判斷語句:

  {% if 條件語句 %}

    執行語句

  {% else  %}

    執行語句

  {% endif %}

      {% if student.class_id == class.id %}
           <option selected value="{{ class.id }}">{{ class.cname }}</option>
      {% else %}
           <option value="{{ class.id }}">{{ class.cname }}</option>
      {% endif %}   

 識別標籤:{{ 變量名|safe}}

{{ page_html|safe }}

 {% csrf_token %}:中間件

 {% url  '別名'  %}:調用別名,在urls文件中,name的值就是別名。

url(r'^login.html/', views.login,name="Login"), # login(request)
    in template:
        action="{% url 'Login' %}" 		
	<a href='{% url 'Login' %}'>click</a>

  with模板:將深查找賦值一個變量

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

  csrf_token:若是是post的請求須要處理,防跨域。

  在form標籤裏面使用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>


<form action="/login.html/" method="post">
    {% csrf_token %}
    <p>姓名:<input type="text" name="user"></p>
    <p>密碼:<input type="password" name="pwd"></p>
    <input type="submit">
</form>

</body>
</html>
View Code

  在ajax裏面使用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
</head>
<body>

{% csrf_token %}
<p>姓名:<input type="text" id="user"></p>
<p>密碼:<input type="password" id="pwd"></p>
<button>click</button><span class="error"></span>
<script>
     $("button").on("click",function () {

         $.ajax({
             url:"/foo/",
             type:"POST",
             data:{
                 user:$("#user").val(),
                 pwd:$("#pwd").val(),
                 csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()
             },
             success:function (data) {
                 console.log(data);
                 console.log(typeof data);
                 console.log(JSON.parse(data));
                 var data=JSON.parse(data);
                 if (data.user){
                     location.href="/index/"  // 跳轉到首頁
                 }
                 else {
                     $(".error").html(data.error_msg).css("color","red");
                     setTimeout(function () {
                         $(".error").html("")
                     },2000)

                 }

             }
         })
     })
</script>
</body>
</html>
View Code

 slock.super:在block模板內部使用,添加新的內容,並不會覆蓋原來的內容。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% block con1 %}
 <p>con11111</p>
{% endblock %}

{% block con_li%}
    <ul>
    <li>111</li>
    <li>222</li>
    <li>333</li>
    </ul>
{% endblock %}

</body>
</html>
View Code
{% extends 'app01/base.html' %}

{% block con_li %}
   {{ block.super }}

{% endblock %}
View Code

  注意:若是在子文件中不使用slock.super模板,就會將父文件中的文本覆蓋。

 settings文件的配置:

  添加路徑:

			TEMPLATES = [
				{
					'BACKEND': 'django.template.backends.django.DjangoTemplates',
					'DIRS': [],   # 在這裏進行設置
					'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',
						],
					},
				},
			]
			

   註釋內容:

			2. 中間件須要註釋一個
			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',
		]

   靜態文件設置:

			STATIC_URL = '/static/'
			STATICFILES_DIRS = (
				os.path.join(BASE_DIR, "ss"),  # 靜態文件存放位置
				
			)
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.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '#vofy$6d=w^aoa0kk#8jhtc3mno9o)eil^8-a^u=)cana=9zq^'

# 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',
]

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 = 'bigJob.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 = 'bigJob.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.11/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.11/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.11/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.11/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS=(os.path.join(BASE_DIR,'css'),)
IEMPLATE_DIRS=(os.path.join(BASE_DIR,'templates'),)
View Code

 提交數據格式相似於:

		{
			「class_name」: 」全棧7期「
		}
		
		request.POST.get("「class_name」:")

  select默認選中
  在對應的option上加selected

 檢驗數據有效性:form組件(django自帶),自動判斷輸入的是否爲空

 模態框版form提交:由於模態框裏面的提交按鈕是放在form表單外面的,須要使用JS代碼去創建關聯
  $("#modal-submit").on("click", function () {
    $("#myModal form").submit();
  });

 檢驗狀態顯示顏色:has-error,若是檢驗出來就會是紅色

$('#setclassname+span').text(dataobj.status).parent().parent().addClass('has-error')
$(document).ready(function () {
    $('.my-menu-item').on('click', 'a', function () {
            $(this).toggleClass('active');
            var $spanEle = $(this).find('span');
            if ($spanEle.removeClass('glyphicon-menu-left')) {
                $spanEle.removeClass('glyphicon-menu-left').addClass('glyphicon-menu-down');
            } else {
                $spanEle.removeClass('glyphicon-menu-down').addClass('glyphicon-menu-left');
            }
        });
        $('#modal-submit').on('click', function () {
            // {#            $('#mymodal from').submit();#}
            var className = $('#inputclassname2').val();
            $.ajax({
                url: '/modal_add_class/',
                type: 'post',
                data: {'classname': className},
                success: function (data) {
                    if (data === 'OK') {
                        // {#                        if (data.length!=0 ){#}
                        // {#                            var classData=JOSN.parse(data);#}
                        // {#                            var newTr=document.cueateElement('tr');#}
                        // {#                            $(newTr).append('<td>'+classData['id']+'</id>');#}
                        // {#                            $(newTr).append('<td>'+classData['name']+'</id>');#}
                        // {#                            $('td:last').clone().appendTo($(newTr));#}
                        // {#                            $(newTr).appendTo('tbody');#}
                        location.href = '/class_list/';
                    } else {
                        $('#error-msg').text(data).parent().parent().addClass('has-error')
                    }
                }
            })
        })


    $('table').on('click','.set_class_list',function () {
        $('#set_mymodal').modal('show');
        var $td=$(this).parent().parent().children();
        var class_id=$($td[0]).text();
        var class_name=$($td[1]).text();

        $('#setclassid').val(class_id);
        $('#setclassname').val(class_name)
    });
    $('#set-modal-submit').on('click',function () {
        var classid=$('#setclassid').val();
        var classname=$('#setclassname').val();
        $.ajax({
            url:"/modal_set_class/",
            type:'post',
            data:{'classid':classid, 'classname':classname},
            success:function(data){
                var dataobj=JSON.parse(data);
                console.log(dataobj.status);
                if (dataobj.status==='OK'){
                    location.reload()
                }else{
                    $('#setclassname+span').text(dataobj.status).parent().parent().addClass('has-error')
                }
            }
        });
    })
});
View Code

五 AJAX(Async JavaScript and XML)

 url:發送的路由路徑

 type:以什麼接口的方式

 data:發送的數據

 success:接收數據成功後執行

 error:介紹數據結束後執行

 contentType:標識的事讓服務器直到此次請求的格式。

  x-www-form-urlencode:將數據拼接成字符串發送過去,這個是默認的

  json:將數據轉成js字符串發送過去,告訴服務器是以一個json格式發送的。

 headers:請求頭,須要引用jquery裏面的cookie.js文件

 cookie("鍵"):在ajax中獲取cookie的值

 serinlize:將某個表單中的value值一塊兒拼接好了一塊發送給服務器端。是一種序列化方法。

 post:ajax封裝的一個API,以post接口方式發送,若是是get,就以get方式請求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js "></script>
    <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script>
</head>
<body>


<form id="myForm" action="/reg/" method="post">
    {% csrf_token %}
    <input name="uid" type="hidden" value="1" />
    <input id=user name="username" type="text" value="張三" />
    <input name="password" type="text" value="123456" />
    <select name="grade" id="grade">
        <option value="1">一年級</option>
        <option value="2">二年級</option>
        <option value="3" selected="selected">三年級</option>
        <option value="4">四年級</option>
        <option value="5">五年級</option>
        <option value="6">六年級</option>
    </select>
    <input name="sex" type="radio" checked="checked" value="1" /><input name="sex" type="radio" value="0" /><input name="hobby" type="checkbox" checked="checked" value="1" />游泳
    <input name="hobby" type="checkbox" checked="checked" value="2" />跑步
    <input name="hobby" type="checkbox" value="3" />羽毛球
    <input name="btn" id="btn" type="button" value="點擊" />

</form>


<script>
    $("#btn").click(function () {

        $.ajax({
            url:"/reg/",
            type:"POST",
            //data:$("#myForm").serialize(),
            data:$(":checkbox,:radio,#user,[name='csrfmiddlewaretoken']").serialize(),
            success:function (data) {
                console.log(data)
            }

        })
        
      
    })
</script>
<script>
{#    $(":button").click(function () {#}
{##}
{#        $.ajax({#}
{#            url:"/login/",#}
{#            type:"POST",#}
{#            data:JSON.stringify({#}
{#                user:$("#user").val(),#}
{#                pwd:$("#pwd").val()#}
{#                //csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()#}
{#            })#}
{#            ,  // 'user=alex&pwd=123'#}
{#            //contentType:"application/x-www-form-urlencoded",  // (默認)#}
{#            //headers:{"X-CSRFToken":$("[name='csrfmiddlewaretoken']").val()},#}
{#            headers:{"X-CSRFToken":$.cookie("csrftoken")},#}
{#            contentType:"application/json",#}
{#            success:function (data) {#}
{#                 console.log(data)#}
{#            },#}
{##}
{#        })#}
{#    })#}
</script>
</body>
</html>
View Code

 ajax能夠在不用刷新頁面的狀況下也能夠提交數據。AJAX是jquery封裝好了的。

 頁面刷新:location.reload()

location.reload()

 頁面跳轉:location.href='要跳轉的頁面'

location.href = '/class_list/';

  模態框使用ajax提交,有返回值,在頁面能夠直接加載數據。

模態框使用ajax提交,返回值
    在頁面直接添加數據
    
    在後端:
    
        - HttpResponse("只能放字符串")
           我有一個Python的字典,要返回給前端:
           要把它轉換成字符串:
           json.dumps()
           
    在前端:
        - JSON.parse()      --> 把字符串轉換回JS對象
        - JSON.stringify()  --> 把JS對象轉換成字符串
    
        
        var className = {"items": [1, 2, 3, 4]}
        $.ajax({
              url: "/modal_add_class/",
              type: "post",
              data: {"classname": className},
              success: function (data) {
                 console.log(data);
              }
        }
        
        $.ajax({
              url: "/modal_add_class/",
              type: "post",
              data: json.stringify({"classname": className}),
              success: function (data) {
                console.log(data);
              }
        }
View Code

 項目目錄結構:

        - 目錄結構
		-mysite
			-mysite
				-urls.py  配置對應關係 URL-->函數
				-settings.py 配置文件
				-wsgi.py  socketserver
				-views.py 本身寫的函數統一放到這裏
				__init__.py
			-templates  存放模板文件的(html文件)
				-index.html
				-class_list.html
			-static
				-bootstrap
					-css
						-bootstrap.min.css
					-fonts
					-js
				-jQuery.3.2.1.min.js
			-manage.py   管理你Django項目的(有不少命令)
						 python manage.py runserver IP:PORT    

  cursor.lastrowoid:pymysql下面的一種方法,操做數據庫時,返回他們的ID。

    def run_list(self,sql,args=None):
        self.cursor.executemany(sql, args)
        self.conn.commit()
        ret=self.cursor.lastrowid
        return ret
View Code

 AJAX發送數據:

 data:{「name」: "alex", "habit": ["抽菸", "喝酒「, "燙頭"]}  這樣不行
 data:{「name」: "alex", "habit": JSON.stringify(["抽菸", "喝酒「, "燙頭"])} 這樣能夠

 補充:FormData:組裝數據,存放要存放的全部鍵值對

    form標籤下面的enctype:修改請求的格式,

      multipart/form-data:上傳文件的二進制數據格式,同時支持表單的數據上傳。

    ProcessData:讓數據是否編碼成相對應的編碼格式,若是爲true,使用contentType進行編碼格式,若是爲false,就不進行contentType編碼處理。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js "></script>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js "></script>
</head>
<body>

<form action="/index/" method="post" enctype="multipart/form-data">
     {% csrf_token %}
    <p>姓名: <input type="text" name="user"></p>
    <p>文件: <input type="file" name="cFile"></p>
    <input type="submit">
</form>


<hr>

    {% csrf_token %}
    <p>姓名: <input type="text" id="user"></p>
    <p>文件: <input type="file" id="cFile"></p>
    <input type="button" value="submit">


<script>
    $(":button").click(function () {
        var $formData=new FormData() ;
        $formData.append("user",$("#user").val());
        $formData.append("cFile",$("#cFile")[0].files[0]);



        $.ajax({
            url:"/indexAjax/",
            type:"post",
            data:{
                cf:$("#cFile")[0].files[0]
            },
            contentType:false,
            processData:false,    // 不對數據作預處理,不進行任何編髮
            headers:{"X-CSRFToken":$('[name="csrfmiddlewaretoken"]').val()},
            success:function (data) {
                console.log(data)
            }
        })

    })
</script>
</body>
</html>
View Code

 django的一些特殊操做:

  母板的繼承:{% extends 'base.html' %}

在母板裏面定義block
    - 頁面佈局的block
    - pasge-css
    - page-js

   引用小組件:{% include 'nav.html' %}

 django詳細信息:http://www.cnblogs.com/liwenzhou/p/7931828.html

六登錄驗證

 cookic定義:保存在瀏覽器的鍵值對;服務端能夠在瀏覽器上面寫cookic,響應頭裏面會有set-cookic;瀏覽器每次發送請求都會攜帶cookic。下次訪問時判斷cookie狀態

 cookic的應用:使用在用戶登錄和保存用戶登錄的。

 跳轉回登錄以前的哪一個頁面:在url上面加上一個跳轉url的裝飾器。

 request的其餘方法:

  request.get_full_path:獲取請求的url

  request.COOKIC.get:獲取具體的cookic值

  request.set_cookic:設置cookic的值

  request.delete_cookic:刪除cookic值

 sookic的一些參數:

  key:鍵是什麼

  value:值是多少

  max_age:保存時間,以秒爲單位

  expires:保存到一個具體的時間

  domain:域名

  secure=False:加密用的Https

  httponly-False:js的代碼不可以讀取cookic,只可以瀏覽器發請求時攜帶cookic 

response.set_signed_cookie("login2", "1", max_age=10, salt="PythonFullstackS7")

 設置加鹽的cookic:set_signed_cookic,下面的salt後面加上本身要加的哪一個鹽

response.set_signed_cookie("login2", "1", max_age=10, salt="PythonFullstackS7")

 獲取加鹽的cookic:get_signed_cookic,下面的salt後嗎加上本身要獲取的那個cookic鹽值。

request.get_signed_cookie("login2", salt="PythonFullstackS7", default=None)

 七 js補充

 JSON.stringify:將js對象轉成字符串類型

 JSON.parse:將字符串類型轉成js對象

data:{'teacher_name':teacherName,'teacher_class_id':JSON.stringify(teacherClassID)},
var dataobj=JSON.parse(data);

八 分頁

 建議:每一個頁面最多顯示11個頁碼

 而django內置的分頁只有上一頁和下一頁:

 1 from django.shortcuts import render
 2 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
 3 
 4 L = []
 5 for i in range(999):
 6     L.append(i)
 7 
 8 def index(request):
 9     current_page = request.GET.get('p')
10 
11     paginator = Paginator(L, 10)
12     # per_page: 每頁顯示條目數量
13     # count:    數據總個數
14     # num_pages:總頁數
15     # page_range:總頁數的索引範圍,如: (1,10),(1,200)
16     # page:     page對象
17     try:
18         posts = paginator.page(current_page)
19         # has_next              是否有下一頁
20         # next_page_number      下一頁頁碼
21         # has_previous          是否有上一頁
22         # previous_page_number  上一頁頁碼
23         # object_list           分頁以後的數據列表
24         # number                當前頁
25         # paginator             paginator對象
26     except PageNotAnInteger:
27         posts = paginator.page(1)
28     except EmptyPage:
29         posts = paginator.page(paginator.num_pages)
30     return render(request, 'index.html', {'posts': posts})
View Code

 分頁的準備:

  1. 封裝:將一些重用的方法封裝到一個類裏面去,隨時均可以調用

  2.app程序準備

"""
分頁組件使用示例:

    obj = Pagination(request.GET.get('page',1),len(USER_LIST),request.path_info)
    page_user_list = USER_LIST[obj.start:obj.end]
    page_html = obj.page_html()

    return render(request,'index.html',{'users':page_user_list,'page_html':page_html})


"""


class Pagination(object):
    def __init__(self,current_page,all_count,base_url,per_page_num=10,pager_count=11):
        """
        封裝分頁相關數據
        :param current_page: 當前頁
        :param all_count:    數據庫中的數據總條數
        :param per_page_num: 每頁顯示的數據條數
        :param base_url: 分頁中顯示的URL前綴
        :param pager_count:  最多顯示的頁碼個數
        """

        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1
        if current_page <1:
            current_page = 1

        self.current_page = current_page

        self.all_count = all_count
        self.per_page_num = per_page_num

        self.base_url = base_url

        # 總頁碼
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager


        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num

    def page_html(self):
        # 若是總頁碼 < 11個:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 總頁碼  > 11
        else:
            # 當前頁若是<=頁面上最多顯示11/2個頁碼
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # 當前頁大於5
            else:
                # 頁碼翻到最後
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []

        first_page = '<li><a href="%s?page=%s">首頁</a></li>' % (self.base_url,1,)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li><a href="#">上一頁</a></li>'
        else:
            prev_page = '<li><a href="%s?page=%s">上一頁</a></li>' % (self.base_url,self.current_page - 1,)

        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="%s?page=%s">%s</a></li>' % (self.base_url,i, i,)
            else:
                temp = '<li><a href="%s?page=%s">%s</a></li>' % (self.base_url,i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li><a href="#">下一頁</a></li>'
        else:
            next_page = '<li><a href="%s?page=%s">下一頁</a></li>' % (self.base_url,self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="%s?page=%s">尾頁</a></li>' % (self.base_url,self.all_pager,)
        page_html_list.append(last_page)

        return ''.join(page_html_list)
View Code

  3 實現分頁:數據切片獲取;顯示出實現的頁碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap/css/bootstrap.min.css">
</head>
<body>
<div class="container">
    <h1>歡迎登錄:{{ user }}   <a href="/logout/">註銷</a></h1>


    <table class="table table-bordered">
        <thead>
        <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>操做</th>
        </tr>
        </thead>
        <tbody>
        {% for item in users %}
            <tr>
                <td>{{ item.id }}</td>
                <td>{{ item.name }}</td>
                <td><a href="/edit/{{ item.id }}/?">編輯</a></td>
            </tr>
        {% endfor %}
        </tbody>
    </table>

    <div style="text-align: center">
        <ul class="pagination">
            {{ page_html|safe }}

        </ul>
    </div>
</div>
</body>
</html>
View Code

九 session的介紹

 session的原理:輸入用戶名後回隨機返回給瀏覽器一個字符串,而後服務端本身頁保留同樣的字符串,當瀏覽器在次訪問時,服務端回拿着瀏覽器發過來的字符串和本身保存的字符串進行比較,若是不一致會提示;若是一致,找到相對應的信息,根據用戶需求是否返回相對應的內容。

 session就至關於保存在服務端的鍵值對,而cookic就至關於保存在瀏覽器上面的鍵值對。而session是依賴於cookic的。

 操做: 

  設置值:直接調用session

request.session['username']='用戶名'

   內部操做:

1 設置set_cookie,返回一組字符串給瀏覽器。

2 本身報保存同樣的字符串,做爲鍵值對的鍵,而後將相關信息做爲值保存爲鍵值對的值。
        sessionkey                  sessiondate
        字符串                          上傳保存的記錄
View Code

  取值:獲取瀏覽器的用戶字符串

request.session.get()

   內部操做:

'''
         uuid=request.COOKIE.get("sessionID") # 2134shdc329cbk398asdbk2
         django的session表中作過濾:  
         session_user=session.objects.filter(session-key="2134shdc329cbk398asdbk2").first()
         ret=session_user.session_data.get("Is_login") #  {"Is_login":True,"user":"alex"}   
        
    '''
View Code

  刪除:刪除具體某一個值

del request.session['想要刪除的哪一個key']

     刪除整條記錄:獲取瀏覽器的隨機字符串,在根據字符串去服務端比較並刪除對應的記錄。

request.session.delect()

  建立和保存session的命令:主要是對數據庫的遷移

python manage.py makemigrations
python manage.py migrate

  建立好的session能夠存放着任何位置,默認存放在數據庫:

# ###################### session 配置信息 ##########################
SESSION_ENGINE = 'django.contrib.sessions.backends.db'  # 引擎(默認)
# SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎  存放在緩存裏面
# SESSION_CACHE_ALIAS = 'default' # 表示那臺機器?

# SESSION_ENGINE = 'django.contrib.sessions.backends.file'  # 引擎   存放在文件裏面
# SESSION_FILE_PATH = None  # 緩存文件路徑,若是爲None,則使用tempfile模塊獲取一個臨時地址tempfile.gettempdir()                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T

# SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎  數據庫加緩存

# SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎  加密cookic和Session

SESSION_COOKIE_NAME = "sessionid"  # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認)
SESSION_COOKIE_PATH = "/"  # Session的cookie保存的路徑(默認)
SESSION_COOKIE_DOMAIN = None  # Session的cookie保存的域名(默認)
SESSION_COOKIE_SECURE = False  # 是否Https傳輸cookie(默認)
SESSION_COOKIE_HTTPONLY = True  # 是否Session的cookie只支持http傳輸(默認)
SESSION_COOKIE_AGE = 1209600  # Session的cookie失效日期(2周)(默認)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False  # 是否關閉瀏覽器使得Session過時(默認)

# SESSION_SAVE_EVERY_REQUEST = False  # 是否每次請求都保存Session,默認修改以後才保存(默認)
SESSION_SAVE_EVERY_REQUEST = True  # 是否每次請求都保存Session,默認修改以後才保存(默認)    
View Code

  使用了session之後,用戶於用戶之間是不會混淆的。

 db.sqlite文件:直接連接到數據庫的,將用戶的記錄能夠直接保存

 session和cookic的區別是:

  session執行的速度慢一些,可是安全性高

  cookic執行的速度快一些,可是安全性低

 Template:模板對象,實例化處理的就是一個模板對象

  將頁面的設計和Python的代碼分離開會更乾淨簡潔更容易維護。 咱們可使用 Django的 模板系統 (Template System)來實現這種模式

def current_time(req):
    # ================================原始的視圖函數
    # import datetime
    # now=datetime.datetime.now()
    # html="<html><body>如今時刻:<h1>%s.</h1></body></html>" %now


    # ================================django模板修改的視圖函數
    # from django.template import Template,Context
    # now=datetime.datetime.now()
    # t=Template('<html><body>如今時刻是:<h1>{{current_date}}</h1></body></html>')
    # #t=get_template('current_datetime.html')
    # c=Context({'current_date':str(now)})
    # html=t.render(c)
    #
    # return HttpResponse(html)


    #另外一種寫法(推薦)
    import datetime
    now=datetime.datetime.now()
    return render(req, 'current_datetime.html', {'current_date':str(now)[:19]})
View Code

 在調用這些 屬性時用大的就是點,若是點方法,內能點沒有參數的方法

def index(request):

    import time
    c=time.time()
    '''
      render方法的過渡應用:
      t=Template("<html><body>如今時刻是:<h1>{{current_date}}</h1></body></html>")
      c=Context({"current_date":c})
      html=t.render(c)
      return HttpResponse(html)
    '''

    l=[111,222,333]
    d = {"name": "alex"}
    class Person():
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def dream(self):
            return ("dream.....")

    alex=Person(name="alex",age=34)
    egon=Person(name="egon",age=9000)
    nacha=Person(name="nacha",age=3)

    person_list=[alex,egon,nacha]

    return render(request,"app01/index.html",{"l":l,"d":d,"person_list":person_list})
View Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>Current time {{ c }}</h1>

<hr>
<p>{{ l.2 }}</p>
<p>{{ d.name}}</p>
<p>{{ person_list.1.name }}</p>
<p>{{ person_list.1.age }}</p>

<hr>
{% for person in person_list %}
       <p>{{ person.name }},{{ person.age }}</p>
{% endfor %}
<hr>
{{ person_list.1.dream }}
</body>
</html>
View Code

 Context:上下文對象,實例化出來的是一個上下文對象

十 模板過濾器

 練習:datetime.datetime.now():當前時,返回的是一個時間對象,每個時間對象均可以點方法取出對應的值

def index(request):

    import time
    c=time.time()
    '''
      render方法的過渡應用:
      t=Template("<html><body>如今時刻是:<h1>{{current_date}}</h1></body></html>")
      c=Context({"current_date":c})
      html=t.render(c)
      return HttpResponse(html)
    '''
    i=10
    l=[111,222,333]
    d = {"name": "alex"}
    class Person():
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def dream(self):
            return ("dream.....")

    alex=Person(name="alex",age=34)
    egon=Person(name="egon",age=9000)
    nacha=Person(name="nacha",age=3)
    person_list=[alex,egon,nacha]

    import datetime

    t=datetime.datetime.now()
    l2=[]
    fileSize=12341234
    s="hello world"
    content="hello world hello world hello world hello world"
    a="<a href=''>click</a>"
    #return render(request,"app01/index.html",{"l":l,"d":d,"person_list":person_list})
    return render(request,"app01/index.html",locals())

def login(request):
    if request.method=="POST":
        user=request.POST.get("user")
        pwd=request.POST.get("pwd")

        if user=="alex" and pwd=="123":
            return redirect("/index/")

    return render(request,"app01/login.html")

def archive(request):
    print(request.path)  # /app01/articls/2004/
    print(request.path_info)  # /app01/articls/2004/
    print(request.get_full_path())  # /app01/articls/2004/?a=1
    # select * from Article where year=2004

    return HttpResponse("2004")

def archive2(request,year):

    return HttpResponse(year)
View Code

  add:假髮過濾器,將變量的數值加上後面的數字

<p>{{ i|add:5 }}</p>

  date:日期過濾器

<p>{{ t|date:"Y-m-d H:i" }}</p>

  length:長度過濾器

 default:提示用戶信息

<p>{{ l2|default:"沒有符合要求的內容" }}</p>

  filesizeformat:文件大小過濾器

<p> 文件大小:{{ fileSize|filesizeformat }}</p>

  slice:切片過濾器

<p>{{ s|slice:"2:" }}</p>

  truncatechars:按照字符截斷

 truncatwords:按照單詞截斷

<p>{{ content|truncatechars:9 }}</p>
<p>{{ content|truncatewords:3 }}</p>
相關文章
相關標籤/搜索