完成一个完整的网页服务,须要有如下:html
再次回顾一下Django 的完成开发流程:python
一些值的获取:mysql
对于性别,为互斥属性:sql
爱好则为多选:数据库
须要使用新的方法 getlist 来获取多个爱好:django
单选下拉框选择获取:app
多选下拉框也须要用到getlist 函数
对于上传文件的设置:post
1 首先form 表单要设置特殊属性:学习
2 文件上传使用新的方法:
使用chunks 来一点一点获取数据:
上传文件到指定目录:
总结一下经常使用的方法:
而后来实践一下,把上面的所有实现一下:
views:
from django.shortcuts import render,redirect,HttpResponse # Create your views here. def user(request): print('user') if request.method == 'GET': return render(request,'user.html') elif request.method == 'POST': #用户名 u = request.POST.get('user') #密码 p = request.POST.get('pwd') #性别 g = request.POST.get('gender') #城市 c = request.POST.get('city') #爱好 f = request.POST.getlist('favor') print(u,p,g,c,f) #文件是一个对象,能够查看对象,大小等 f_obj = request.FILES.get('up_head_img') #获取文件名 f_name = f_obj.name f_size = f_obj.size print(f_name,f_size) #真正接收并存到本地 import os file_path = os.path.join('upload',f_obj.name) block_size = 0 with open(file_path,mode='wb') as f: for block in f_obj.chunks(): #用这个来获取的当前已经上传了多少,能够给用户返回 block_size += len(block) print(block_size) f.write(block) print(f_obj.name,'传完了') return HttpResponse('200')
urls:
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user/" method="POST" enctype="multipart/form-data"> <div class="text"> <label>用户名</label> <input type="text" name="user"/> <label>密码</label> <input type="password" name="pwd"/> </div> <div class="chose"> <div> <label>性别</label> <input type="radio" name="gender" value="1"/>男 <input type="radio" name="gender" value="2"/>女 </div> <div> <label>城市</label> <select name="city"> <option value="sh">上海</option> <option value="bj">北京</option> <option value="tj">天津</option> <option value="sjz">石家庄</option> </select> </div> <div> <label>爱好</label> <input type="checkbox" name="favor" value="1"/>骑行 <input type="checkbox" name="favor" value="2"/>旅游 <input type="checkbox" name="favor" value="3"/>音乐 <input type="checkbox" name="favor" value="4"/>电影 <input type="checkbox" name="favor" value="5"/>把妹 <input type="checkbox" name="favor" value="6"/>吃吃吃 </div> </div> <div class="upload"> <label>上传头像</label> <input type="file" name="up_head_img"/> </div> <input type="submit" value="提交全部数据"/> </form> </body> </html>
效果:
Django 有两种方式:
1 FBV
function base view
function函数处理的方式
2 CBV
class base view
class类处理的方式
写一个类处理的方式:
1 先导入View 模块
2 定义类及里面的属性
3 定义url:
4 html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <form action="/home/" method="POST"> <h1>测试Class 处理方式 CBV</h1> <input type="submit" value="测试提交方法"/> </form> </div> </body> </html>
5 测试:
在这里咱们能够实现一个相似装饰器的功能,就是在类里的方法执行前或后添加一些其余功能:
使用dispatch 函数:
from django.views import View class Home(View): def dispatch(self, request, *args, **kwargs): #调用父类中的 print('访问前要执行的') result = super(Home,self).dispatch(request,*args,**kwargs) print('访问后要执行的') return result def get(self,request): print('使用方法:', request.method) return render(request,'home.html') def post(self,request): print('使用方法:',request.method) return render(request, 'home.html')
测试:
以上为经常使用的方法。
下面学习下模板语言:
1 在html 中如何循环得道的字典数据呢?
实践:
views:
USER_DICT = { 'k1': 'root1', 'k2': 'root2', 'k3': 'root3', 'k4': 'root4', 'k5': 'root5', } def moban(request): return render(request,'moban.html',{'USER_DICT':USER_DICT})
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <span>测试for 循环 只循环key</span> <ul> {% for k in USER_DICT.keys %} <li>{{ k }}</li> {% endfor %} </ul> </div> <div> <span>测试for 循环 只循环value</span> <ul> {% for v in USER_DICT.values %} <li>{{ v }}</li> {% endfor %} </ul> </div> <div> <span>测试for 循环 所有循环</span> <ul> <li>k -- v</li> {% for k,v in USER_DICT.items %} <li>{{ k }} -- {{ v }}</li> {% endfor %} </ul> </div> </body> </html>
urls:
from user import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^user/', views.user), url(r'^home/', views.Home.as_view()), url(r'^moban/', views.moban), ]
效果:
下面实现一个稍微复杂一点的:
1 列出字典的k及value里的一个值
views:
USER_INFO = { '1': {'name':'shenyang','age':25,'mail':'123@qq.com'}, '2': {'name':'wang','age':18,'mail':'456@qq.com'}, '3': {'name':'xiaoming','age':19,'mail':'789@qq.com'}, '4': {'name':'xiaohua','age':11,'mail':'101112@qq.com'}, } def list(request): return render(request,'list.html',{'USER_INFO':USER_INFO})
urls:
url(r'^list/', views.list),
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>用户列表</h1> <div> <ul> {% for k,v in USER_INFO.items %} <li><a target="_blank" href="/detail-{{ k }}.html">{{ k }} -- {{ v.name }}</a></li> {% endfor %} </ul> </div> </body> </html>
效果:
2 实现经过点击链接,进入新的网页并显示value里的全部值
用到的点有:
1 url的正则匹配
2 经过url的数据定位某一个数据
views:
USER_INFO = { '1': {'name':'shenyang','age':25,'mail':'123@qq.com'}, '2': {'name':'wang','age':18,'mail':'456@qq.com'}, '3': {'name':'xiaoming','age':19,'mail':'789@qq.com'}, '4': {'name':'xiaohua','age':11,'mail':'101112@qq.com'}, } def list(request): return render(request,'list.html',{'USER_INFO':USER_INFO}) def detail(request,nid): detail_info = USER_INFO[nid] return render(request,'details.html',{'detail_info':detail_info})
urls:
from user import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^user/', views.user), url(r'^home/', views.Home.as_view()), url(r'^moban/', views.moban), url(r'^list/', views.list), url(r'^detail-(?P<nid>\d+).html', views.detail), ]
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>详细信息</h2> <div> <h6>用户名:{{ detail_info.name }}</h6> <h6>年龄:{{ detail_info.age }}</h6> <h6>邮箱:{{ detail_info.mail }}</h6> </div> </body> </html>
效果:
咱们不只能够经过url 获取一个数据,还能获取多个数据:
匹配规则:
匹配相似于 detail-1-2.html 这种两个数字的:
函数获取数据:
可是这样有一个很差的就是当url中这两个数字换了之后代码里的函数获取的数据也就不正确了,因此须要给匹配到的指定一个变量,这样就再也不须要关心顺序了:
函数获取数据:
无论顺序,直接获取:
nid 就是nid uid 就是uid
这里很重要,总结一下:
路由系统,URL的三种方式:
1 直接匹配,不须要获取数据:
2 经过正则匹配,可是在函数获取数据时必须注意先后顺序:
3 经过正则匹配到后不须要关心顺序,可是url中须要指定变量名称:
url不只能够匹配数字,还能够经过各类匹配,函数还能够以字典方式和列表方式获取数据:
例如函数中以字典方式获取数据:
views:
def dic_test(request,**kwargs): print('This dic is: ',kwargs) nid = kwargs['nid'] uid = kwargs['uid'] all = 'This is ' + nid + ' and ' + uid return HttpResponse(all)
urls:
url(r'^dic_test-(?P<nid>\d+)-(?P<uid>\d+).html', views.dic_test),
html:
无
效果:
url 地址还能够给一个变量,用于在html 模板中跳转到指定变量的地址中:
固然若是想获取绝对的url地址,使用:
由于在模板渲染的时候响应函数已经把全部的request 传入,因此想获取哪一个数据,只要request中有,就必定能获取到,并渲染到模板中
另外一种方式本身跳转到自定义页面:
须要用到 reverse 模块:
例如:
把name 为 i2 的url 自定义一个url 经过列表形式转换为自定义url
urls:
viwes:
from django.urls import reverse def custom_url_i2(request,*args,**kwargs): print(request.path_info) url2 = reverse('i2',args=(8,12)) print(url2) return HttpResponse(url2)
效果:
把name 为 i3 的url 自定义一个url 经过字典形式转换为自定义url
urls:
viwes:
def custom_url_i3(request,*args,**kwargs): print(request.path_info) url3 = reverse('i3',kwargs={'uid':88,'nid':66}) print(url3) return HttpResponse(url3)
效果:
总结一下:
固然上面这些是只有Django 才有的方式
路由系统中另外一个强大的功能叫作路由分发系统:
详细来讲就是经过指定一个url 到另外一个url路由文件就能够实现多个项目与主路由的松耦合,这样开发者能够本身修改本身的项目的url地址而不会影响到其余项目:
实现:
项目主urls:
user模块urls:
user viwes:
host模块urls:
host viwes:
效果:
路由系统暂时到此。
开始ORM:
ORM分为两类:
Django中的为Codefirst
使用Django 建立一个用户表:
1 写类
from django.db import models # Create your models here. class User_info(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64)
2 修改setting 添加app
3 执行命令生成表
python manage.py makemigrations python manage.py migrate
4 检查
Django 建立表的时候表名为:
app名_表的类名
这里咱们在没有作修改以前默认用的是SQLite数据库,使用mysql 数据库:
完整使用mysql 数据库的步骤:
1 修改项目的__init__.py 添加pymysql
2 修改setting 使用mysql 链接
3 在app中写一个类:
4 修改setting 注册app
5 执行命令生成表
manage.py makemigrations manage.py migrate
6 查看表:
配置完后学一下增删改查:
1 增长:
a方式:
b方式:
以字典形式增长数据:
2 查:
查全部:
过滤(where)查询:
这里也是一个列表,由于用户名称等于root的可能有多个,因此要经过列表循环获取数据
组合查询(and条件):
虽然查到了一个可是查到的结果类型仍是一个列表,因此还要循环
3 删除:
过滤删除:
所有删除:
.all().delete()
4 更新:
所有更新:
过滤更新:
实践一下:
from host_manage import models def orm(request): # 增长 models.User_info.objects.create(username='root',password='123') # 查看 result = models.User_info.objects.all() for row in result: print(row.id,row.username,row.password) #删除 models.User_info.objects.filter(username='alex').delete() #更新 models.User_info.objects.filter(id=2).update(password='66666') return HttpResponse('orm')
实现查询的时候只拿取第一个,并返回一个对象:
first() 方法:
这样查找以后就会取过滤后的第一个对象,这里能够判断若是对象存在就说明有数据,若是为None 则数据不存在
也能够用下面的计数查询,若是大于0说明有数据,可是不能获取到多个信息,不经常使用:
还有一种获取对象的方式,可是不推荐,须要配合try来使用:
查看真实的sql 语句,就是在操做对象时执行的sql:
写一个列出和添加用户的小功能:
1 views
from user import models def user_info(request): if request.method == 'GET': user_list = models.UserInfo.objects.all() print(user_list) return render(request,'user_info.html',{'user_list':user_list}) elif request.method == 'POST': u = request.POST.get('user') p = request.POST.get('pwd') print(u,p) models.UserInfo.objects.create(username=u,password=p) return redirect('/user/user_info/')
2 models
from django.db import models # Create your models here. class UserInfo(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64)
3 urls
from django.conf.urls import url from user import views urlpatterns = [ url(r'^login/',views.login), url(r'^list/',views.list), url(r'^user_info/',views.user_info), ]
4 html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user/user_info/" method="POST"> <h2>用户列表</h2> <ul> {% for i in user_list %} <li>{{ i.username }}</li> {% endfor %} </ul> <input type="text" name="user" placeholder="用户名" /></div> <div><input type="password" name="pwd" placeholder="密码" /></div> <input type="submit" value="添加用户"/> </form> </body> </html>
5 效果
继续添加点击用户名能够查看详细信息功能:
使用url 的正则匹配形式:
1 views
from user import models def user_info(request): if request.method == 'GET': user_list = models.UserInfo.objects.all() print(user_list) return render(request,'user_info.html',{'user_list':user_list}) elif request.method == 'POST': u = request.POST.get('user') p = request.POST.get('pwd') print(u,p) models.UserInfo.objects.create(username=u,password=p) return redirect('/user/user_info/') def user_detail(request,nid): print(nid) user_info = models.UserInfo.objects.filter(id=nid).first() return render(request,'userdetail.html',{'user_info':user_info})
2 urls
from django.conf.urls import url from user import views urlpatterns = [ url(r'^login/',views.login), url(r'^list/',views.list), url(r'^user_info/',views.user_info), url(r'^userdetail-(?P<nid>\d+).html/',views.user_detail), ]
3 html
userinfo
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user/user_info/" method="POST"> <h2>用户列表</h2> <ul> {% for i in user_list %} <li>{{ i.username }} <a href="/user/userdetail-{{ i.id }}.html">详细</a></li> {% endfor %} </ul> <input type="text" name="user" placeholder="用户名" /></div> <div><input type="password" name="pwd" placeholder="密码" /></div> <input type="submit" value="添加用户"/> </form> </body> </html>
userdetail
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> <li>{{ user_info.username }} -- {{ user_info.password }}</li> </ul> </body> </html>
4 效果
最后添加删除和编辑功能:
1 删除:
最简单,根据id直接操做数据库而后返回到用户列表页便可
2 修改:
返回指定id的数据到input 框,当修改后根据id提交
views:
from user import models def user_info(request): if request.method == 'GET': user_list = models.UserInfo.objects.all() print(user_list) return render(request,'user_info.html',{'user_list':user_list}) elif request.method == 'POST': u = request.POST.get('user') p = request.POST.get('pwd') print(u,p) models.UserInfo.objects.create(username=u,password=p) return redirect('/user/user_info/') def user_detail(request,nid): print(nid) user_info = models.UserInfo.objects.filter(id=nid).first() return render(request,'userdetail.html',{'user_info':user_info}) def user_del(request,nid): print(nid) models.UserInfo.objects.filter(id=nid).delete() return redirect('/user/user_info/') def user_edit(request,nid): print(nid) if request.method =='GET': user = models.UserInfo.objects.filter(id=nid).first() return render(request,'useredit.html',{'user':user}) elif request.method == 'POST': u = request.POST.get('username') p = request.POST.get('password') print(u,p) models.UserInfo.objects.filter(id=nid).update(username=u,password=p) return redirect('/user/user_info/')
urls:
from django.conf.urls import url from user import views urlpatterns = [ url(r'^login/',views.login), url(r'^list/',views.list), url(r'^user_info/',views.user_info), url(r'^userdetail-(?P<nid>\d+).html/',views.user_detail), url(r'^userdel-(?P<nid>\d+).html/',views.user_del), url(r'^useredit-(?P<nid>\d+).html/',views.user_edit), ]
html:
userinfo:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user/user_info/" method="POST"> <h2>用户列表</h2> <ul> {% for i in user_list %} <li>{{ i.username }} <a href="/user/userdetail-{{ i.id }}.html">详细|</a><a href="/user/userdel-{{ i.id }}.html">删除|</a><a href="/user/useredit-{{ i.id }}.html">编辑</a></li> {% endfor %} </ul> <input type="text" name="user" placeholder="用户名" /></div> <div><input type="password" name="pwd" placeholder="密码" /></div> <input type="submit" value="添加用户"/> </form> </body> </html>
useredit:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>修改用户信息</h2> <form action="/user/useredit-{{ user.id }}.html/" method="POST"> <input type="text" name="nid" value="{{ user.id }}" style="display: none"/> <input type="text" name="username" value="{{ user.username }}"/> <input type="text" name="password" value="{{ user.password }}"/> <input type="submit" value="提交修改"/> </form> </body> </html>
效果:
基本的增删改查就到这里,下面说一下增长列和删除列:
经过Django 的ORM 操做数据库其实很简单:
增长列:
1直接在class中增长一个属性就行
2 执行命令,生成表结构:
删除列:
1 直接注释掉须要删除的列
2 执行命令删除
Django 中的ORM 有不少的数据类型,可是其本质也就是数据库那几种类型,只是Django 会帮你作一层验证:
数据表的一些其余操做:
指定列名:
创建索引:
创建惟一索引:
注册时间,建立时间,但是使用这个:
下面这种才会更新:
建立一个choices 类型的表:
Django 的admin 会自动看成选项:
存入数据库的仍是数字,避免了连表查询
总结一下字段的参数:
Django admin 显示字段中文:
自定义帮助信息,在旁边坐一个小的提示:
admin 的其余一些方法:
实际上在数据库中会生成 user_group_id 这个表
经过这个关联键 获取数据:
建立一个值:
直接写入本地数据库而不是跨表写入
动态的下拉框:
实践:
添加一个在建立用户的时候指定组的功能,下拉框中的数据来自另外一个表的数据,存储的时候直接存储到本表。
先实现展现的功能:
models:
建立关联的外键:
from django.db import models # Create your models here. class UserGroup(models.Model): uid = models.AutoField(primary_key=True) caption = models.CharField(max_length=32,unique=True) ctime = models.DateTimeField(auto_now_add=True,null=True) uptime = models.DateTimeField(auto_now=True,null=True) class UserInfo(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64) user_group = models.ForeignKey('UserGroup',to_field='uid')
插入几条数据,从新刷新一下数据库,发现 userinfo表里增长了一个 user_group_uid 的列,而不是user_group,这是由于外键关联的是一个对象,而不是真正的列
views:
处理数据,在获取组的时候使用外键的方式:
from user import models def user_info(request): if request.method == 'GET': user_list = models.UserInfo.objects.all() group_list = models.UserGroup.objects.all() print(user_list) return render(request,'user_info.html',{'user_list':user_list,'group_list':group_list}) elif request.method == 'POST': u = request.POST.get('user') p = request.POST.get('pwd') g = request.POST.get('group') print(u,p,g) models.UserInfo.objects.create(username=u,password=p,user_group_id=g) return redirect('/user/user_info/') def user_detail(request,nid): print(nid) user_info = models.UserInfo.objects.filter(id=nid).first() return render(request,'userdetail.html',{'user_info':user_info})
html:
info:
以点的方式继续操做另外一张表
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/user/user_info/" method="POST"> <h2>用户列表</h2> <ul> <li> 用户名 -- 组</li> {% for i in user_list %} <li>{{ i.username }} -- {{ i.user_group.caption }} <a href="/user/userdetail-{{ i.id }}.html">详细|</a><a href="/user/userdel-{{ i.id }}.html">删除|</a><a href="/user/useredit-{{ i.id }}.html">编辑</a></li> {% endfor %} </ul> <input type="text" name="user" placeholder="用户名" /></div> <div><input type="password" name="pwd" placeholder="密码" /></div> <div><select name="group" > {% for g in group_list %} <option value="{{ g.uid }}">{{ g.caption }}</option> {% endfor %} </select> </div> <input type="submit" value="添加用户"/> </form> </body> </html>
detail:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> <li> 用户名 -- 密码 -- 组</li> <li>{{ user_info.username }} -- {{ user_info.password }} -- {{ user_info.user_group.caption }}</li> </ul> </body> </html>
效果: