Django的开始

一 浏览器相关知识

 http:只有依赖一回,属于短链接,不会报错客户端的信息。

 浏览器相当于一个客户端,客户端的链接

 服务端:socket服务端,起服务监听客户端的请求。

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

二 框架的介绍

 tornado:模版都是人家写好的,我们只管拿来使用。

 Django:服务端可以自己写,其他的模版都是别人写好的。

 flask:服务端和模版渲染都是自己写的,函数的功能都是别人写好了的。

 所有的web框架叫做web应用服务器。

三 django的安装和使用

 安装: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>

 

   

 

   

 

转载于:https://www.cnblogs.com/fangjie0410/p/7896589.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值