01:django基础篇
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
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), ]
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"}))
<!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>
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), ]
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, })
<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>
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路由分发 ]
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')
<!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>
#! /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'), ]
1.5 Django的CBV和FBV 返回顶部
1、FBV(function base view):在views.py文件中使用函数
def aaa(request): return HttpResponse('aaa')
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'), ]
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')
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'), ]
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')
<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>
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), ]
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})
{% 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>
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), ]
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))
<!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>
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'), ]
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}))
<!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>
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
作者:学无止境
出处:https://www.cnblogs.com/xiaonq
生活不只是眼前的苟且,还有诗和远方。