01:django基础篇

Django其他篇

目录:

1.1 django初探     返回顶部

  1、django、tornado、flask比较

      Django: 1个重武器,包含了web开发中常用的功能、组件的框架;(ORM、Session、Form、Admin、分页、中间件、信号、缓存、ContenType....);

      Tornado: 最大特性就是异步非阻塞、原生支持WebSocket协议;

      Flask:封装功能不及Django完善,性能不及Tornado,但是Flask的第三方开源组件比丰富;

      使用参考

        1. 小型web应用设计的功能点不多使用Flask;
        2. 大型web应用设计的功能点比较多使用的组件也会比较多,使用Django(自带功能多不用去找插件);
        3. 如果追求性能可以考虑Tornado;

  2、MVC和MVT比较

    MVC       Model(数据库 )        View(模板文件)       Controller(业务处理)

        M( Model):  主要封装对数据库层的访问,对数据库中的数据进行增、删、改、查操作。
        V( View):  用于封装结果,生成页面展示的html内容。
        C(Controller):  用于接收请求,处理业务逻辑,与Model和View交互,返回结果。

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

        M( Model):  与MVC中的M功能相同,负责和数据库交互,进行数据处理。
        V( View):  与MVC中的C功能相同,接收请求,进行业务处理,返回应答。
        T(Template):  与MVC中的V功能相同,负责封装构造要返回的html。

1.2 第一个django项目     返回顶部

  1、安装django

       pip3 install django==2.0.4

  2、创建django项目

C:\Users\tom>    d:                          # 进入d盘
D:\>    django-admin startproject mysite     # 创建django项目(可以看到c盘生成了mysite文件夹的django项目)
D:\>    cd mysite                            # 进入项目目录
D:\mysite>    python manage.py runserver 127.0.0.1:8000       # 运行mysite项目
# 浏览器访问:http://127.0.0.1:8000/

  3、创建子应用

      c:\mysite>python manage.py startapp app01

  4、django项目和子应用各文件作用

C:.
│  db.sqlite3               # sqlite数据库文件(settings.py中默认连接的数据库)
│  manage.py              # 项目管理脚本
│
├─app01 (子应用目录)
│  │  admin.py            # 配置django admin后台
│  │  apps.py
│  │  models.py            # 配置django表,负责和数据库交互,进行数据处理
│  │  tests.py
│  │  views.py             # 接收请求,进行业务处理,返回应答
│  │  __init__.py
│  │
│  └─migrations
│          __init__.py
│
└─mysite
    │  settings.py           # 项目配置文件
    │  urls.py              # 总路由
    │  wsgi.py
    │  __init__.py
django项目文件注释

  5、settings.py基本配置

      1)配置模板的路径(在项目根路径下创建文件夹  D:\mysite\templates

TEMPLATES = [
    {
       'DIRS': [os.path.join(BASE_DIR,'templates')],
    },
]
TEMPLATE_DIRS = (os.path.join(BASE_DIR,  'templates'),)

      2)配置静态目录(在项目根路径下创建文件夹 D:\mysite\static

#像ccs和js这些静态文件如果想要使用必须在这里配置路径
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,'static'),
)

      3)注释CSRF(如果以post方式提交请求可以先注释这里进行测试)

MIDDLEWARE = [
    # 'django.middleware.csrf.CsrfViewMiddleware',
]

      4) 修改settings.py中时区

#### 1、Django默认配置是:
TIME_ZONE = 'UTC'
LANGUAGE_CODE = 'en-us'

#### 2、Django1.9以前应设置为:
TIME_ZONE = 'Asia/Shanghai'
LANGUAGE_CODE = 'zh-cn'

####3、Django1.9以后至目前的2.1,应设置为:
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'

1.3 django render/redirect/HttpResponse 和 request.GET request.POST     返回顶部

  1、render/redirect/HttpResponse 函数用法

      render  :  返回html页面

      redirect  :  重定向到新的页面

      HttpResponse  :  返回字符串(一般为json字符串)

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
]
urls.py
from django.shortcuts import render,redirect,HttpResponse
import json

def index(request):
    return render(request, 'index.html', {'users':['zhangsan','lisi','wangwu']})
    # return redirect('https://www.baidu.com')
    # return HttpResponse(json.dumps({"name":"zhangsan"}))
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
    <h1>我是首页</h1>
    {{ users }}
</body>
</html>
index.html

  2、模板使用

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
]
urls.py
from django.shortcuts import render,redirect,HttpResponse

def index(request):
    return render(request, 'index.html',
                  {
                      'users':['zhangsan','lisi','wangwu'],
                      'data':{"name":"zhangsan","age":100,"sex":"人妖"},
                      'num': 12,
                   })
views.py
<body>
    <h1>1、users: 循环列表</h1>
    {% for u in users %}
        <p>{{ u }}</p>
    {% endfor %}

    <h1>2、data:循环字典</h1>
    {% for k,v in data.items %}
        <p>{{ k }} -- {{ v }}</p>
    {% endfor %}

    <h1>3、if判断</h1>
    {% if num > 16 %}
      <a>num大于16</a>
   {% else %}
      <a>num小于16</a>
   {% endif %}
</body>
index.html

1.4 Django各种url写法     返回顶部

  1、无正则匹配url  (http://127.0.0.1:8000/index/?nid=1&pid=2)

  2、基于(\d+)正则的url

  3、基于正则分组(?P<nid>\d+),可以不考虑接收参数顺序 (推荐)

  4、使用name构建自己想要的url

  5、Django路由分发    并使用name构建url路径

  re_path(r'app01/',include(('app01.urls','app01'),namespace='app01'))

from django.contrib import admin
from django.urls import path, re_path,include
from app01 import views


urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'index1/$', views.index1, name='indexname1'),          # 方法1:无正则匹配url
    re_path('index2/(\d+)/$', views.index2, name='indexname2'),     # 方法2:基于(\d+)正则的url
    re_path('index3/(?P<nid>\d+)/(?P<pid>\d+)/$', views.index3, name='indexname3'),        # 方法3:基于(\d+)正则的url
    re_path('index4/$', views.index4),                               # 方法4:使用name构建自己想要的url
    path('app01/', include('app01.urls', namespace='app01')),       # 方法5:Django路由分发
]
mysite/urls.py
from django.shortcuts import render,redirect,HttpResponse
import json
from django.urls import reverse


# 方法1:无正则匹配url( http://127.0.0.1:8000/index1/?uid=1 )
def index1(request):
    print( request.GET )             # {"uid": "1"}
    nid = request.GET.get('uid')    # 1
    return HttpResponse('无正则匹配url')


# 方法2:基于(\d+)正则的url(  http://127.0.0.1:8000/index2/1/  )
def index2(request, uid):
    print( uid )                    # 1
    return HttpResponse('基于(\d+)正则的url')


# 方法3:基于正则分组(?P<nid>\d+)(  http://127.0.0.1:8000/index3/1/2/  )
def index3(request, nid, pid):
    print(nid)                     # 1
    print(pid)                     # 2
    return HttpResponse('基于正则分组url')


# 方法4:使用name构建自己想要的url (http://127.0.0.1:8000/index4/)
def index4(request):
    url1 = reverse('indexname1')                                    # /index1/
    url2 = reverse('indexname2', args=(1,))                         # /index2/1/2/
    url3 = reverse('indexname3', kwargs={'pid': 1, "nid":2})       # /index3/1/2/
    return render(request, 'index.html')


# 方法5:Django路由分发 (http://127.0.0.1:8000/app01/aaa/)
def aaa(request):
    return HttpResponse('aaa')
app01/views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
    <p><a href="{% url 'indexname1' %}">  无正则匹配: http://127.0.0.1:8000/index/  </a></p>
    <p><a href="{% url 'indexname2' 1  %}"> 基于(\d+)正在匹配: http://127.0.0.1:8000/index2/1/  </a></p>
    <p><a href="{% url 'indexname3' 1 2 %}">  基于正则分组url: http://127.0.0.1:8000/index3/1/2/  </a></p>
</body>
</html>
index.html
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from django.urls import path,re_path
app_name='app01'
from app01 import views


urlpatterns = [
    re_path(r'aaa/$', views.aaa, name='aaa'),
]
app01/urls.py

1.5 Django的CBV和FBV     返回顶部

  1、FBVfunction  base  view:views.py文件中使用函数

def aaa(request):
    return HttpResponse('aaa')
FBV写法

  2、CBV(class  base  view):在views.py文件中使用类

      1、 dispatch是父类中用来反射的函数,找对应的函数(比对应函数先执行)

      2、 比如你发送post请求就可以通过dispatch找到对应的post函数进行处理,get就会找到get函数处理

#! /usr/bin/env python
# -*- coding: utf-8 -*-
from django.urls import path,re_path
app_name='app01'
from app01 import views


urlpatterns = [
    re_path(r'home/$', views.Home.as_view(), name='home'),
]
urls.py
from django.views import View
class Home(View):
    '''使用CBV时必须要继承view父类'''
    def dispatch(self, request, *args, **kwargs):
        # 调用父类中的dispatch
        result = super(Home,self).dispatch(request, *args, **kwargs)
        # 使用result主动继承view父类,然后return就可以重写父类的dispath方法
        return result

    # 在这里使用get发来请求就会调用get方法,使用post发来请求就会调用post方法
    def get(self,request):
        print(request.method)
        return HttpResponse('get')

    def post(self,request):
        print(request.method,'POST')
        return HttpResponse('post')
app01/views.py

1.6 前后端交互:提交数据     返回顶部

  1、获取请求数据

# 1、request.POST
# 2、request.GET
# 3、request.FILES
# 4、request.getlist
# 5、request.method
# 6、request.path_info                   #获取当前url

  2、举例

from django.contrib import admin
from django.urls import path, re_path
from app01 import views

urlpatterns = [
    re_path(r'login/$', views.login, name='login'),
]
urls.py
def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    elif request.method == 'POST':
        post_data = request.POST                      # {"user": "naiqiang.xiao", "gender": "1", "favor": "33", "city": "bj"}
        mul_list = request.POST.getlist('favor')     # ['11', '22', '33']
        return render(request, 'login.html')
app01/views.py
    <form action="/login/" method="post" enctype="multipart/form-data">
        <p>
            <span>input提交:</span>
            <input type="text" name="user" placeholder="用户名">
        </p>

        {# 1、单选框,返回单条数据的列表 #}
        <p>
            <span>性别: </span>
            男:<input type="radio" name="gender" value="1">
            女:<input type="radio" name="gender" value="2">
        </p>

        {# 2、多选框、返回多条数据列表 #}
        <p>
            <span>爱好: </span>
            篮球:<input type="checkbox" name="favor" value="11">
            排球:<input type="checkbox" name="favor" value="22">
            足球:<input type="checkbox" name="favor" value="33">
        </p>

        {# 3、多选,返回多条数据的列表 #}
        <p>
            <span>地址: </span>
            <select name="city">
                <option value="bj">北京</option>
                <option value="sh">上海</option>
                <option value="gz">广州</option>
            </select>
        </p>
        <input type="submit" value="提交">
    </form>
login.html

  3、form表单中三个参数作用

''' action="/login/" method="post" enctype="multipart/form-data"  '''
# 1、action="/login/"      # form表单数据提交的路径
# 2、method="post"         # 以什么方式提交form表单
# 3、enctype="multipart/form-data"      # 如果需要提交文件需要这个标注

1.7 上传图片&预览功能     返回顶部

  1、使用from表单上传图片 及 预览功能

      1) enctype就是encodetype就是编码类型的意思。
      2) 默认情况下,enctype的值是application/x-www-form-urlencoded,不能用于文件上传。
      3) multipart/form-data是指定将文件以二进制的形式上传,这样可以实现多种类型的文件上传。

from django.contrib import admin
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'upload/',views.upload),
]
urls.py
from django.shortcuts import render
import os

def upload(request):
    if request.method == 'GET':
        return render(request, 'upload.html')

    elif request.method == 'POST':
        obj = request.FILES.get('filename')  # 获取上传图片对象
        file_path = os.path.join('static','images', obj.name)  # static\images\aa.jpg
        f = open(file_path, mode='wb')
        for i in obj.chunks():
            f.write(i)
        f.close()
        imgpath = os.path.join('images',obj.name)  # images\aa.jpg
        return render(request, 'upload.html',{'imgpath': imgpath})
app01/views.py
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
    <form action="/upload/" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <p><input type="file" name="filename"></p>
        <input type="submit" value="提交">
    </form>
        <p>图片预览</p>
        <p><img src="{% static imgpath %}"></p>
</body>
</html>
upload.html

  2、使用jquery ajax上传图片

    1)JQuery AJAX说明

        1、jQuery其实就是一个JavaScript的类库,其将复杂的功能做了上层封装,使得开发者可以在其基础上写更少的代码实现更多的功能

        2、jQuery Ajax本质 XMLHttpRequest 或 ActiveXObject

    2) FormData对象

        1、FormData对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。

        2、 其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。

        3、比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件。

    3)contentType:(默认: "application/x-www-form-urlencoded")

        1、发送信息至服务器时内容编码类型(false标识不要对提交的数据)。

        2、如果你明确地传递了一个content-type给 $.ajax() 那么他必定会发送给服务器(即使没有数据要发送)

        3、设置false作用:告诉JQuery不要设置内容格式

    4)processData(默认: true)

        1、默认情况下,通过data选项传递进来的数据,都会处理转化成一个查询字符串

        2、如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。

        3、设置false作用:告诉JQuery不要特殊处理这个数据

from django.contrib import admin
from django.urls import path,re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'ajax/$',views.ajax_upload),
]
urls.py
from django.shortcuts import render,HttpResponse
import os
import json


def ajax_upload(request):
    if request.method == 'GET':
        return render(request, 'ajaxupload.html')
    elif request.method == 'POST':
        obj = request.FILES.get('fafafa')
        username = request.POST.get('username')  # root
        file_path = os.path.join('static','images', obj.name)  # static\images\aa.jpg
        with open(file_path,'wb') as f:
            for item in obj.chunks():
                f.write(item)
        ret = {'code':True,'data':'sucess'}
        return HttpResponse(json.dumps(ret))
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
    <div>
        <input type="file" id="fafafa" name="afafaf">
        <a class="upload">上传</a>
    </div>
    <input type="button" value="提交jQuery" onclick="fqSubmit();">

    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function fqSubmit(){
            var file_obj = document.getElementById('fafafa').files[0];

            var fd = new FormData();            // FormData对象可以传字符串,也可以传文件对象
            fd.append('username','root');
            fd.append('fafafa',file_obj);
            var xhr = new XMLHttpRequest();

            $.ajax({
                url:'/ajax/',
                type:'POST',
                data:fd,
                //jquery Ajax上传文件必须指定processData,contentType参数
                processData:false,              //告诉JQuery不要特殊处理这个数据
                contentType:false,              //告诉JQuery不要设置内容格式
                success:function(arg){
                    console.log(111,arg);       //后台返回的数据  {"code": true, "data": "sucess"}
                }
            })
        }
    </script>
</body>
</html>
ajaxupload.html

1.8 ajax登录 & 一些常用dom 和 jquery操作     返回顶部

  1、ajax登录

from django.contrib import admin
from django.urls import path, re_path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path(r'login/', views.login, name='login'),
]
urls.py
from django.shortcuts import render,HttpResponse
import os
import json


def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    elif request.method == 'POST':
        print(request.POST)
        username = request.POST.get('username')
        password = request.POST.get('password')
        print(username, password)
        if username == 'tom' and password == '123456':
            return HttpResponse(json.dumps({'status':True}))
        else:
            return HttpResponse(json.dumps({'status':False}))
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
    <h2>登录</h2>
    <div style="">
        <p>
            <input name="username" id="username">
        </p>
        <p>
            <input name="password" type="password" id="password">
        </p>
        <p>
            <input type="button" value="提交" onclick="ajaxSubmit()">
        </p>
        <p id="err-msg" style="color: red;"></p>
    </div>

    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function ajaxSubmit() {
            var username = document.getElementById('username').value;
            var password = document.getElementById('password').value;
            $.ajax({
                url: '/login/',  // 提交url
                data: {'username':username, 'password':password},  // 提交数据
                type: 'POST',  // 提交方式
                dataType: 'JSON',  // 将数据装换成json格式提交
                traditional: true,  // tradtional为true阻止深度序列化
                success: function (data) {
                    if(data.status == true){
                        alert('登录成功')
                        document.getElementById('err-msg').innerText = ''
                        location.href='http://www.baidu.com'
                    }else {
                        console.log('在页面显示错误信息')
                        document.getElementById('err-msg').innerText = '用户名或密码错误'
                    }
                }
            })
        }
    </script>
</body>
</html>
login.html

  2、前后端交互必学知识点

      1.  Dom操作   :   https://www.cnblogs.com/xiaonq/p/7953682.html

      2.  jquery使用整理  :  https://www.cnblogs.com/xiaonq/p/7954562.html

      3.  ajax最全整理  :  https://www.cnblogs.com/xiaonq/p/8013068.html 

  3、make_password & check_password

from django.contrib.auth.hashers import make_password, check_password

hkey = make_password("123456")  # pbkdf2_sha25615000MAjic...
ret = check_password("123456","pbkdf2_sha25615000MAjic...")  # True

 

posted @ 2019-05-31 08:59  不做大哥好多年  阅读(547)  评论(0编辑  收藏  举报