Django其他篇
目录:
- 1.1 django初探
- 1.2 第一个django项目
- 1.3 django render/redirect/HttpResponse 和 request.GET request.POST
- 1.4 Django各种url写法
- 1.5 Django的CBV和FBV
- 1.6 前后端交互:提交数据
- 1.7 上传图片&预览功能
- 1.8 ajax登录 & 一些常用dom 和 jquery操作
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') #
return HttpResponse('无正则匹配url') # 方法2:基于(\d+)正则的url( http://127.0.0.1:8000/index2/1/ )
def index2(request, uid):
print( uid ) #
return HttpResponse('基于(\d+)正则的url') # 方法3:基于正则分组(?P<nid>\d+)( http://127.0.0.1:8000/index3/1/2/ )
def index3(request, nid, pid):
print(nid) #
print(pid) #
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、FBV(function 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="">
女:<input type="radio" name="gender" value="">
</p> {# 2、多选框、返回多条数据列表 #}
<p>
<span>爱好: </span>
篮球:<input type="checkbox" name="favor" value="">
排球:<input type="checkbox" name="favor" value="">
足球:<input type="checkbox" name="favor" value="">
</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 == '':
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("") # pbkdf2_sha25615000MAjic...
ret = check_password("","pbkdf2_sha25615000MAjic...") # True