第1章 Django ORM相关操做
1.1 在一个py文件中使用django项目
1.2 返回QuerySet对象的方法有
1.2.1 特殊的QuerySet
1.3 返回具体对象的
1.4 返回布尔值的方法有:
1.5 返回数字的方法有
1.6 表单查询-双下划线
1.6.1 id__lt
1.6.2 id__in
1.6.3 name__contains
1.6.4 icontains
1.6.5 id__range
1.6.6 其它
第2章 ForeignKey操做(重点)
2.1 例:
2.1.1 设置model.py给多的添加外键
2.1.2 配置urls.py
2.1.3 编写views.py
2.1.4 service_list.html
2.1.5 server_add.html
第3章 下载文件从存储驱动
第4章 pycharm中的快捷键
4.1 部署配置static
第5章 路由系统进阶
5.1 基本格式
5.2 参数说明
5.3 url正则说明
5.3.1 注意事项
5.3.2 APPEND_SLASH=True
5.4 分组命名匹配
5.4.1 位置参数
5.4.2 关键字参数(命名分组)
5.4.3 视图分组(分页写法)
5.4.4 规范url路由分发
5.4.5 给视图参数传递额外的参数
5.5 url命名和反向解析(重)
5.5.1 静态传参
5.5.2 动态传参
5.6 命名空间
5.6.1 namespace
第6章 djaango--视图
6.1 视图函数FBV
6.2 视图类CBV
6.2.1 View模块
6.2.2 .as_view()方法
6.3 装饰器
6.3.1 FBV装饰器
6.3.2 CBV装饰器
6.3.3 介绍
6.3.4 method_decorator模块
6.3.5 扩展
6.3.6 CBV装饰器的三种方法
6.3.7 方法一:直接加载方法上面
6.3.8 方法二:加在dispatch方法上面
6.3.9 方法三:加在类上
6.4 request相关参数
6.4.1 path_info
6.4.2 method
6.4.3 GET
6.4.4 POST
6.4.5 body
6.5 属性
6.5.1 HttpRequest.scheme
6.5.2 HttpRequest.body
6.5.3 HttpRequest.path
6.5.4 HttpRequest.method
6.5.5 HttpRequest.encoding
6.5.6 HttpRequest.GET
6.5.7 6.HttpRequest.POST
6.5.8 HttpRequest.COOKIES
6.5.9 HttpRequest.FILES
6.5.10 HttpRequest.META
6.5.11 HttpRequest.user
6.5.12 HttpRequest.session
6.6 上传文件
6.7 response
6.7.1 介绍
6.7.2 使用方法
6.7.3 JsonResponse
6.7.4 render()
6.7.5 redirect()
6.7.6 设定json
第7章 模板引擎
7.1 经常使用语法
7.2 变量
7.2.1 例
7.3 Filters
7.3.1 default
7.3.2 filesizeformat
7.3.3 add
7.3.4 lower
7.3.5 title
7.3.6 length
7.3.7 slice
7.3.8 first
7.3.9 last
7.3.10 join
7.3.11 truncatechars
7.3.12 date
7.3.13 safe
7.3.14 自定义filter
7.3.15 for
7.3.16 with
7.3.17 注释
7.3.18 注意事项
7.4 模板继承
7.4.1 块(block)
7.4.2 组件
7.4.3 自定义simpletag
7.4.4 templatetags/my_inclusion.py
7.4.5 templates/result.html
7.4.6 templates/index.html
7.5 bootstrip没有数据优化 css
操做html |
查询结果前端 |
all():python |
查询全部结果正则表达式 |
filter(**kwargs):数据库 |
它包含了与所给筛选条件相匹配的对象django |
get(**kwargs):json |
返回与所给筛选条件相匹配的对象,返回结果有且只有一个,若是符合筛选条件的对象超过一个或者没有都会抛出错误。bootstrap |
exclude(**kwargs):浏览器 |
它包含了与所给筛选条件不匹配的对象 |
values(*field): |
返回一个ValueQuerySet——一个特殊的QuerySet,运行后获得的并非一系列model的实例化对象,而是一个可迭代的字典序列 |
values_list(*field): |
它与values()很是类似,它返回的是一个元组序列,values返回的是一个字典序列 |
order_by(*field): |
对查询结果排序 |
reverse(): |
对查询结果反向排序,请注意reverse()一般只能在具备已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。 |
distinct(): |
从返回结果中剔除重复纪录(若是你查询跨越多个表,可能在计算QuerySet时获得重复的结果。此时可使用distinct(),注意只有在PostgreSQL中支持按字段去重。) |
count(): |
返回数据库中匹配查询(QuerySet)的对象数量。 |
first(): |
返回第一条记录 |
last(): |
返回最后一条记录 |
exists(): |
若是QuerySet包含数据,就返回True,不然返回False |
import os
if __name__=='__main__':
os.environ.setdefaul("DJANGO_SETTINGS_MODULE","mysite.setting")
import django
django.setup()
from app01 import models
ret = models.Person.objects.filer(age=18)
l all()
l filter()
l exclude()
l order_by()
l reverse()
l distinct()
l values() 返回一个可迭代的字典序列
l values_list() 返回一个可迭代的元祖序列
l get()
l first()
l last()
l exists()
l count()
获取id大于1 且 小于10的值
models.Tb1.objects.filter(id__lt=10, id__gt=1)
获取id等于十一、2二、33的数据
models.Tb1.objects.filter(id__in=[11, 22, 33])
not in
models.Tb1.objects.exclude(id__in=[11, 22, 33])
获取name字段包含"ven"的
models.Tb1.objects.filter(name__contains="ven")
大小写不敏感
models.Tb1.objects.filter(name__icontains="ven")
id范围是1到3的,等价于SQL的bettwen and
models.Tb1.objects.filter(id__range=[1, 3])
相似的还有:
startswith,istartswith, endswith, iendswith
date字段还能够:
models.Class.objects.filter(first_day__year=2017)
class Publisher(models.Model):
name = models.CharField(max_length=12)
class Book(models.Model):
title = models.CharField(max_length=32)
publisher_id = models.ForeignKey(to="Publisher",on_delete=CASCADE)
注意:on_delete=CASCADE 在Django2.0中要添加,表示级联删除之意
解释:在出版社Publosher删除后BOOk也随之级联的操做,1.1默认是级联删除
django rest framwork
设置primary外键
方法一:
class Publisher(models.Model):
id = models.AutoField(primary_key=True)
name =models.CharField(max_length=32)
class Book(models.Model):
title = models.CharField(max_length=32)
publisher = models.ForeignKey(Publisher)
方法二:字符串表示调用的类(不用考虑顺序)
class Publisher(models.Model):
id = models.AutoField(primary_key=True)
name =models.CharField(max_length=32)
class Book(models.Model):
title = models.CharField(max_length=32)
publisher = models.ForeignKey('Publisher')#django自动加_id
mtmy/urls.py
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'app01',include('app01.urls'))
]
app01/urls.py
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'index/$', views.index,),
# service url
url(r'service_list/$', views.service_list, name='service_list'),
url(r'service_list/service_add/$', views.service_add,name='service_add'),
url(r'service_list/service_del/(?P<pk>\d+)/$', views.service_del,name='service_del'),
#server url
url(r'server_list/$',views.server_list,name='server_list'),
url(r'server_list/server_add/$', views.AddServer.as_view(),name='server_add'),
url(r'service_list/server_del/(?P<pk>\d+)/$', views.server_del,name='server_del'),
#manage url
url(r'manage_list/$',views.manage_list,name='manage_list'),
url(r'manage_list/manage_add/$', views.manage_add,name='manage_add'),
url(r'manage_list/manage_del/(?P<pk>\d+)/$', views.manage_del,name='manage_del'),
]
from django.shortcuts import render,redirect,reverse,HttpResponse
from app01 import models
from django.views import View
# Create your views here.
def index(request):
return render(request, 'index.html')
def service_list(request):
services = models.ServiceList.objects.all()
#render 返回一个渲染的模板能够传入参数
return render(request,'service_list.html',{'services': services})
def service_add(request):
err_msg = ''
if request.method == 'POST':
service_name = request.POST.get('service_name')
if service_name:
service_list = models.ServiceList.objects.filter(service_name=service_name)
if service_list:
err_msg = '服务名称已经存在'
else:
service_obj = models.ServiceList.objects.create(service_name=service_name)
print(service_obj)
#redirect 接收一个url,表示跳转到指定的url
return redirect(reverse('service_list'))
else:
err_msg = '用户名不能为空'
return render(request,'service_add.html',{'error_msg':err_msg})
def service_del(request,pk):
serv_list = models.ServiceList.objects.filter(id=pk)
print(serv_list)
if serv_list:
serv_list[0].delete()
return redirect(reverse('service_list'))
else:
return HttpResponse('删除数据不存在')
def server_list(request):
server = models.HostsList.objects.all()
#render 返回一个渲染的模板能够传入参数
return render(request,'server_list.html',{ 'server':server })
def server_del(request,pk):
# service_id = request.GET.get(pk)
# print(pk)
serv_list = models.HostsList.objects.filter(id=pk)
print(serv_list)
if serv_list:
serv_list[0].delete()
return redirect(reverse('server_list'))
else:
return HttpResponse('删除数据不存在')
class AddServer(View):
def get(self,request):
services = models.ServiceList.objects.all()
manages = models.ManageList.objects.all()
return render(request,'server_add.html',{ 'service':services,'manage':manages})
def post(self,request):
new_name = self.request.POST.get('server_ip')
password = self.request.POST.get('password')
service_id = self.request.POST.get('service')
manage_id = self.request.POST.get('manage')
models.HostsList.objects.create(ipaddr=new_name,password=password,service=models.ServiceList.objects.get(id=service_id),manage=models.ManageList.objects.get(id=manage_id))
return redirect(reverse(server_list))
def manage_list(request):
#获取数据库全部数据
manage_list = models.ManageList.objects.all()
#render 返回一个渲染的模板能够传入参数server表示html中的for 中的server
return render(request,'manage_list.html',{ 'server':manage_list })
def manage_add(request):
err_msg = ''
if request.method == 'POST':
manage_id = request.POST.get('id')
manage_name = request.POST.get('name')
manage_pwd = request.POST.get('password')
if manage_id:
manage_list = models.ManageList.objects.filter(id=manage_id)
if manage_list:
err_msg = '服务器已经存在'
else:
manage_obj = models.ManageList.objects.create(id=manage_id,password=manage_pwd,name=manage_name)
# print(service_obj)
#redirect 接收一个url,表示跳转到指定的url
return redirect(reverse('manage_list'))
else:
err_msg = '用户名不能为空'
return render(request,'manage_add.html',{'error_msg':err_msg})
def manage_del(request,pk):
# service_id = request.GET.get(pk)
# print(pk)
serv_list = models.ManageList.objects.filter(id=pk)
print(serv_list)
if serv_list:
serv_list[0].delete()
return redirect(reverse('manage_list'))
else:
return HttpResponse('删除数据不存在')
{% extends 'base.html' %}
{% block content %}
<h2 class="sub-header">服务管理列表</h2>
<a class="btn btn-success" href="{% url 'service_add' %}">添加</a>
<div class="table-responsive">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>序号</th>
<th>ID</th>
<th>服务名称</th>
<th>操做</th>
</tr>
</thead>
<tbody>
{% for service in services %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ service.id }}</td>
<td>{{ service.service_name }}</td>
<td>
<a class="btn btn-success btn-sm"
href="">编辑</a>
<a class="btn btn-danger btn-sm" href="{% url 'service_del' pk=service.id %}">删除</a>
</td>
</tr>
{% empty %}
<tr>
<td colspan="4" style="text-align: center">没有数据</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.css">
</head>
<body>
{% include 'nav.html' %}
<div class="container" style="margin-top: 70px">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<form class="form-horizontal" action="" method="post" novalidate>
{% csrf_token %}
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">IPAddr</label>
<div class="col-sm-10">
<input type="text" name="server_ip" class="form-control" id="inputEmail3" placeholder="请添加服务IP">
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input type="text" name="password" class="form-control" id="inputEmail3" placeholder="请添加服务器密码">
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Service_ID</label>
<div class="col-sm-10 ">
<select name="service" class="form-control" >
{% for service in service %}
<option value="{{ service.id }}">{{ service.service_name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Manage_ID</label>
<div class="col-sm-10 ">
<select name="manage" class="form-control" >
{% for manage in manage %}
<option value="{{ manage.id }}">{{ manage.name }}</option>
{% endfor %}
</select>
</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>
</div>
</div>
</div>
</body>
</html>
l Ctrl +d 复制
l CTrl + shilft + - 合起全部
l for +Tab html for 循环
l div. +table
https://docs.djangoproject.com/en/1.11/howto/static-files/deployment/
Django1.15写法:
from django.conf.urls import url
urlpatterns = [
url(正则表达式, views视图函数,参数,别名),
]
Django2.0写法
from django.urls import path
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]
l 正则表达式:一个正则表达式字符串
l views视图函数:一个可调用对象,一般为一个视图函数或一个指定视图函数路径的字符串
l 参数:可选的要传递给视图函数的默认参数(字典形式)
l 别名:一个可选的name参数
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
l urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则再也不继续。
l 若要从URL中捕获一个值,只须要在它周围放置一对圆括号(分组匹配)。
l 不须要添加一个前导的反斜杠,由于每一个URL 都有。例如,应该是^articles 而不是 ^/articles。
l 每一个正则表达式前面的'r' 是可选的可是建议加上
解释:
Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其做用就是自动在网址结尾加'/'。
补充说明
是否开启URL访问地址后面不为/跳转至带有/的路径的配置项
APPEND_SLASH=True
例:
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r'^blog/$', views.blog),
]
语法:
(?P<name>pattern)
name是组的名称
pattern是要匹配的模式。
例:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
#0到9数字中匹配4个数字
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
这个实现与前面的示例彻底相同,只有一个细微的差异:捕获的值做为关键字参数而不是位置参数传递给视图函数。
例如,针对url /articles/2017/12/至关于按如下方式调用视图函数:
views.month_archive(request, year="2017", month="12")
urls.py
url(r'edit_publisher/(\d+)/$',views.edit_publisher),
html
<p>
id号:
<input type="text" name="nid" value="{{ pub_obj.nid }}" >
</p>
<p>
姓名:
<input type="text" name="publisher_name" value="{{ pub_obj.name}}">
</p>
views.py
def edit_publisher(request,nid):
# nid = request.POST.get('nid')
# 获取编辑的对象
if request.method == 'POST':
publisher_name = request.POST.get('publisher_name')
pub_obj = models.Publisher.objects.get(nid=nid)
pub_obj.name = publisher_name
# 向数据库提交
pub_obj.save()
return redirect('/publisher_list/')
# nid = request.GET.get('id')
pub_obj = models.Publisher.objects.get(nid=nid)
return render(request, 'edit_publisher.html', {'pub_obj': pub_obj})
页面访问:
urls.py
url(r'edit_publisher/(?P<pk>\d+)/$',views.edit_publisher),
views.py
def edit_publisher(request,pk):
# nid = request.POST.get('nid')
# 获取编辑的对象
if request.method == 'POST':
publisher_name = request.POST.get('publisher_name')
pub_obj = models.Publisher.objects.get(nid=pk)
pub_obj.name = publisher_name
# 向数据库提交
pub_obj.save()
return redirect('/publisher_list/')
# nid = request.GET.get('id')
pub_obj = models.Publisher.objects.get(nid=pk)
return render(request, 'edit_publisher.html', {'pub_obj': pub_obj})
浏览器访问:
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/$,views.page),
url(r'^blog/page(?P<num>[0-9]+)/$',views.page)
]
views.py中能够为num指定默认值
#
def page(request,num="10"):
pass
解释:协同开发的做用,定义项目url保持编写规范
APP01项目目录中创建urls.py
#将原有项目的url移至app01.urls下
app01.urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
# 定义URL和函数的对应关系
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/home', views.home),
url(r'^index/$',views.index),
url(r'^login/$',views.login),
# url(r'^index/(?P<pk>\d+)/$',views.publisher_list),
url(r'^publisher_list/$',views.publisher_list),
url(r'add_publisher',views.add_publisher),
url(r'del_publisher',views.del_publisher),
url(r'edit_publisher/(?P<pk>\d+)/$',views.edit_publisher),
# url(r'edit_publisher',views.edit_publisher),
]
#主urls.py
from django.conf.urls import url,include
from django.contrib import admin
# 定义URL和函数的对应关系
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'app01', include('app01.urls')),
]
浏览器访问:
URLconfs 具备一个钩子,让你传递一个Python 字典做为额外的参数传递给视图函数。
django.conf.urls.url() 能够接收一个可选的第三个参数,它是一个字典,表示想要传递给视图函数的额外关键字参数。
例如:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]
在这个例子中,对于/blog/2005/请求,Django 将调用views.year_archive(request, year='2005', foo='bar')。
当传递额外参数的字典中的参数和URL中捕获值的命名关键字参数同名时,函数调用时将使用的是字典中的参数,而不是URL中捕获的参数。
解释:给url起了一个名字,用的时候能够直接解析到地址
语法:
1)定义url : name= 'add'
urlpatterns = [
url(r'index/home',views.home),
url(r'index/$',views.index),
url(r'login/$',views.login),
url(r'publisher_list/$',views.publisher_list,name='publisher'),
url(r'publisher_list/add_publisher/$',views.add_publisher,name='add'),
url(r'publisher_list/del_publisher/$',views.del_publisher),
url(r'publisher_list/edit_publisher/$',views.edit_publisher),
]
2)更改模板变量 {% url 'add' %}
<thead>
<tr class="active text-center" id="tr">
<td>用户顺序</td>
<td>用户_ID</td>
<td>用户名</td>
<td>密码</td>
<td>操做管理</td>
</tr>
</thead>
<tbody class="text-center" >
#原始调用
#<a type="button" class="btn btn-success " href="/add_publisher/">增长新成员</a>
<a type="button" class="btn btn-success " href="{% url 'add' %}">增长新成员</a>
{% for i in pub %}
<tr >
<td class="info" >{{ forloop.counter }}</td>
<td class="success">{{ i.nid }}</td>
<td class="warning">{{ i.name}}</td>
<td class="warning">{{ i.password}}</td>
<td><a type="button" class="btn btn-danger bg-primary text-primary" href="/del_publisher/?id={{ i.nid }}"><button>删除</button></a>
<a type="button" class="btn btn-warning text-primary bg-primary " href=" /edit_publisher/?id={{ i.nid }}"><button>编辑</button></a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
3)修改views.py : reverse('别名')
from diango.import reverse
def add_publisher(request):
err_msg = ''
if request.method == 'POST':
publisher_name = request.POST.get('publisher_name')
publisher_password = md5(publisher_name,request.POST.get('publisher_password'))
if publisher_name:
pub_list = models.Publisher.objects.filter(name=publisher_name)
print(pub_list)
if pub_list:
err_msg = '用户名已存在'
else:
pub_obj = models.Publisher.objects.create(name=publisher_name,password=publisher_password)
print(pub_obj)
# return redirect('/publisher_list/')
return redirect(reverse('publisher'))
else:
err_msg = '用户名不能为空'
return render(request, 'add_publisher.html', {'err_msg': err_msg})
解释:针对参数值为动态多个值时
1)urls.py (?P<pk>\d+)/$ 动态传参
语法:
url(r'publisher_list/edit_publisher/(?P<pk>\d+)/$',views.edit_publisher,name='edd'),
]
2)views.edit_publisher()
def edit_publisher(request,pk):
#位置传参
# nid = request.POST.get('nid')
# 获取编辑的对象
if request.method == 'POST':
publisher_name = request.POST.get('publisher_name')
pub_obj = models.Publisher.objects.get(nid=pk)
pub_obj.name = publisher_name
# 向数据库提交
pub_obj.save()
return redirect(reverse('publisher'))
# nid = request.GET.get('nid')
pub_obj = models.Publisher.objects.get(nid=pk)
return render(request, 'edit_publisher.html', {'pub_obj': pub_obj})
3)修改publisher_list.html
语法:
{% url 'edd' pk=i.nid %}"
<thead>
<tr class="active text-center" id="tr">
<td>用户顺序</td>
<td>用户_ID</td>
<td>用户名</td>
<td>密码</td>
<td>操做管理</td>
</tr>
</thead>
<tbody class="text-center" >
<a type="button" class="btn btn-success " href="{% url 'add' %}">增长新成员</a>
{% for i in pub %}
<tr >
<td class="info" >{{ forloop.counter }}</td>
<td class="success">{{ i.nid }}</td>
<td class="warning">{{ i.name}}</td>
<td class="warning">{{ i.password}}</td>
<td><a type="button" class="btn btn-danger bg-primary text-primary" href="/del_publisher/?id={{ i.nid }}"><button>删除</button></a>
<a type="button" class="btn btn-warning text-primary bg-primary " href="{% url 'edd' pk=i.nid %}"><button>编辑</button></a></td>
</tr>
{% endfor %}
页面访问:
解释:不一样业务定义url规范,避免不一样项目之间调用冲突
project中的urls.py
from django.conf.urls import url, include
urlpatterns = [
url(r'^app01/', include('app01.urls', namespace='app01')),
url(r'^app02/', include('app02.urls', namespace='app02')),
]
appo1中的urls.py
from django.conf.urls import url
from app01 import views
app_name = 'app01'
urlpatterns = [
url(r'^(?P<pk>\d+)/$', views.detail, name='detail')
]
此时,当两个app中的 url名称重复了,我反转URL的时候就能够经过命名空间的名称获得我当前的url.
语法:
'命名空间名称:URL名称'
模板中使用:
{% url 'app01:detail' pk=12 pp=99 %}
views中的函数中使用
v = reverse('app01:detail', kwargs={'pk':11})
这样即便app中URL的命名相同,我也能够反转获得正确的URL了。
基于view函数的视图为FBV视图:
# FBV版添加班级
def add_class(request):
if request.method == "POST":
class_name = request.POST.get("class_name")
models.Classes.objects.create(name=class_name)
return redirect("/class_list/")
return render(request, "add_class.html")
语法:
基于类的视图为CBV视图:
# CBV版添加班级
from django.views import View
class AddClass(View):
def get(self, request):
return render(request, "add_class.html")
def post(self, request):
class_name = request.POST.get("class_name")
models.Classes.objects.create(name=class_name)
return redirect("/class_list/")
注意:
使用CBV时,urls.py中也作对应的修改:
# urls.py中
url(r'^add_class/$', views.AddClass.as_view()),
写类以前pytho提供了一个类的模块View
解释:与FBV不一样的是,CBV定义urls.py的方法以下:
# urls.py中
url(r'^add_class/$', views.AddClass.as_view()),
def wrapper(func):
def inner(*args, **kwargs):
start_time = time.time()
ret = func(*args, **kwargs)
end_time = time.time()
print("used:", end_time-start_time)
return ret
return inner
# FBV版添加班级
@wrapper
def add_class(request):
if request.method == "POST":
class_name = request.POST.get("class_name")
models.Classes.objects.create(name=class_name)
return redirect("/class_list/")
return render(request, "add_class.html")
类中的方法与独立函数不彻底相同,所以不能直接将函数装饰器应用于类中的方法 ,咱们须要先将其转换为方法装饰器。
Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。
# CBV版添加班级
from django.views import View
from django.utils.decorators import method_decorator
class AddClass(View):
@method_decorator(wrapper)
def get(self, request):
return render(request, "add_class.html")
def post(self, request):
class_name = request.POST.get("class_name")
models.Classes.objects.create(name=class_name)
return redirect("/class_list/")
# 使用CBV时要注意,请求过来后会先执行dispatch()这个方法,若是须要批量对具体的请求处理方法,如get,post等作一些操做的时候,这里咱们能够手动改写dispatch方法,这个dispatch方法就和在FBV上加装饰器的效果同样。
class Login(View):
def dispatch(self, request, *args, **kwargs):
print('before')
obj = super(Login,self).dispatch(request, *args, **kwargs)
print('after')
return obj
def get(self,request):
return render(request,'login.html')
def post(self,request):
print(request.POST.get('user'))
return HttpResponse('Login.post')
模块倒入method_decorator
from django.utils.decorators import method_decorator
def timer(func):
def inner(request, *args, **kwargs):
now = time.time()
ret = func(request, *args, **kwargs)
print("函数执行时间是{}".format(time.time() - now))
return ret
return inner
class AddPublisher(View):
# http_method_names = ['get']
def dispatch(self, request, *args, **kwargs):
ret = super().dispatch(request, *args, **kwargs)
return ret
@method_decorator(timer)
def get(self, request):
return render(request, 'publisher_add.html')
def post(self, request):
print(request.body)
new_name = self.request.POST.get('name')
models.Publisher.objects.create(name=new_name)
return redirect(reverse('app01:publisher'))
class AddPublisher(View):
# 只须要加一条就能够同时获取get和POST最方便
@method_decorator(timer)
def dispatch(self, request, *args, **kwargs):
ret = super().dispatch(request, *args, **kwargs)
return ret
def get(self, request):
return render(request, 'publisher_add.html')
def post(self, request):
print(request.body)
new_name = self.request.POST.get('name')
models.Publisher.objects.create(name=new_name)
return redirect(reverse('app01:publisher'))
@method_decorator(timer,name='post')
@method_decorator(timer,name='get')
class AddPublisher(View):
# http_method_names = ['get']
@method_decorator(timer)
def dispatch(self, request, *args, **kwargs):
ret = super().dispatch(request, *args, **kwargs)
return ret
def get(self, request):
return render(request, 'publisher_add.html')
def post(self, request):
print(request.body)
new_name = self.request.POST.get('name')
models.Publisher.objects.create(name=new_name)
return redirect(reverse('app01:publisher'))
返回用户访问url,不包括域名
请求中使用的HTTP方法的字符串表示,全大写表示。
包含全部HTTP GET参数的类字典对象
包含全部HTTP POST参数的类字典对象
请求体,byte类型 request.POST的数据就是从body里面提取到的
属性:
django将请求报文中的请求行、头部信息、内容主体封装成 HttpRequest 类中的属性。
除了特殊说明的以外,其余均为只读的。
表示请求方案的字符串(一般为http或https)
一个字符串,表明请求报文的主体。在处理非 HTTP 形式的报文时很是有用,例如:二进制图片、XML,Json等。可是,若是要处理表单数据的时候,推荐仍是使用 HttpRequest.POST 。
另外,咱们还能够用 python 的类文件方法去操做它,详情参考 HttpRequest.read() 。
一个字符串,表示请求的路径组件(不含域名)。
例如:"/music/bands/the_beatles/"
一个字符串,表示请求使用的HTTP 方法。必须使用大写。
例如:"GET"、"POST"
一个字符串,表示提交的数据的编码方式(若是为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。
这个属性是可写的,你能够修改它来修改访问表单数据使用的编码。
接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。
若是你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。
一个相似于字典的对象,包含 HTTP GET 的全部参数。详情请参考 QueryDict 对象。
一个相似于字典的对象,若是请求中包含表单数据,则将这些数据封装成 QueryDict 对象。
POST 请求能够带有空的 POST 字典 —— 若是经过 HTTP POST 方法发送一个表单,可是表单中没有任何的数据,QueryDict 对象依然会被建立。
所以,不该该使用 if request.POST 来检查使用的是不是POST 方法;应该使用 if request.method == "POST"
另外:若是使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。
一个标准的Python 字典,包含全部的cookie。键和值都为字符串。
一个相似于字典的对象,包含全部的上传文件信息。
FILES 中的每一个键为<input type="file" name="" /> 中的name,值则为对应的数据。
注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的状况下才会
包含数据。不然,FILES 将为一个空的相似于字典的对象。
一个标准的Python 字典,包含全部的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例:
CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。
CONTENT_TYPE —— 请求的正文的MIME 类型。
HTTP_ACCEPT —— 响应可接收的Content-Type。
HTTP_ACCEPT_ENCODING —— 响应可接收的编码。
HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。
HTTP_HOST —— 客服端发送的HTTP Host 头部。
HTTP_REFERER —— Referring 页面。
HTTP_USER_AGENT —— 客户端的user-agent 字符串。
QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。
REMOTE_ADDR —— 客户端的IP 地址。
REMOTE_HOST —— 客户端的主机名。
REMOTE_USER —— 服务器认证后的用户。
REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。
SERVER_NAME —— 服务器的主机名。
SERVER_PORT —— 服务器的端口(是一个字符串)。
从上面能够看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 以外,请求中的任何 HTTP 首部转换为 META 的键时,
都会将全部字母大写并将链接符替换为下划线最后加上 HTTP_ 前缀。
因此,一个叫作 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。
一个 AUTH_USER_MODEL 类型的对象,表示当前登陆的用户。
若是用户当前没有登陆,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你能够经过 is_authenticated() 区分它们。
例如:
if request.user.is_authenticated():
# Do something for logged-in users.
else:
# Do something for anonymous users.
user 只有当Django 启用 AuthenticationMiddleware 中间件时才可用。
匿名用户
class models.AnonymousUser
django.contrib.auth.models.AnonymousUser 类实现了django.contrib.auth.models.User 接口,但具备下面几个不一样点:
id 永远为None。
username 永远为空字符串。
get_username() 永远返回空字符串。
is_staff 和 is_superuser 永远为False。
is_active 永远为 False。
groups 和 user_permissions 永远为空。
is_anonymous() 返回True 而不是False。
is_authenticated() 返回False 而不是True。
set_password()、check_password()、save() 和delete() 引起 NotImplementedError。
New in Django 1.8:
新增 AnonymousUser.get_username() 以更好地模拟 django.contrib.auth.models.User。
一个既可读又可写的相似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。
view.py
from django.shortcuts import render, redirect, reverse, HttpResponse
from app01 import models
from django.views import View
class Upload(View):
def get(self, request):
return render(request, 'upload.html')
def post(self, request):
my_file = request.FILES.get('my_file')
print(my_file.name)
with open(my_file.name, 'wb') as f:
for chunk in my_file.chunks():
f.write(chunk)
return HttpResponse('ok')
upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="my_file">
<button type="submit">提交</button>
</form>
</body>
</html>
urls.py
url(r'^pub/add/$', views.AddPublisher.as_view(),name='publisher_add')
与由Django自动建立的HttpRequest对象相比,HttpResponse对象是咱们的职责范围了。咱们写的每一个视图都须要实例化,填充和返回一个HttpResponse。
HttpResponse类位于django.http模块中。
传递字符串
from django.http import HttpResponse
response = HttpResponse("Here's the text of the Web page.")
response = HttpResponse("Text only, please.", content_type="text/plain")
设置或删除响应头信息
response = HttpResponse()
response['Content-Type'] = 'text/html; charset=UTF-8'
del response['Content-Type']
属性
HttpResponse.content:响应内容
HttpResponse.charset:响应内容的编码
HttpResponse.status_code:响应的状态码
JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应。
from django.http import JsonResponse
response = JsonResponse({'foo': 'bar'})
print(response.content)
b'{"foo": "bar"}'
默认只能传递字典类型,若是要传递非字典类型须要设置一下safe关键字参数。
response = JsonResponse([1, 2, 3], safe=False)
结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。
参数:
l request: 用于生成响应的请求对象。
l template_name:要使用的模板的完整名称,可选的参数
l context:添加到模板上下文的一个字典。默认是一个空字典。若是字典中的某个值是可调用的,视图将在渲染模板以前调用它。
l content_type:生成的文档要使用的MIME类型。默认为 DEFAULT_CONTENT_TYPE 设置的值。默认为'text/html'
l status:响应的状态码。默认为200。
l useing: 用于加载模板的模板引擎的名称。
例:
from django.shortcuts import render
def my_view(request):
# 视图的代码写在这里
return render(request, 'myapp/index.html', {'foo': 'bar'})
等价于
from django.http import HttpResponse
from django.template import loader
def my_view(request):
# 视图代码写在这里
t = loader.get_template('myapp/index.html')
c = {'foo': 'bar'}
return HttpResponse(t.render(c, request))
参数能够是:
l 一个模型:将调用模型的get_absolute_url() 函数
l 一个视图,能够带有参数:将使用urlresolvers.reverse 来反向解析名称
l 一个绝对的或相对的URL,将原封不动的做为重定向的位置。
l 默认返回一个临时的重定向;传递permanent=True 能够返回一个永久的重定向。
传递一个具体的ORM对象(了解便可)
将调用具体ORM对象的get_absolute_url() 方法来获取重定向的URL:
from django.shortcuts import redirect
def my_view(request):
...
object = MyModel.objects.get(...)
return redirect(object)
传递一个视图的名称
def my_view(request):
...
return redirect('some-view-name', foo='bar')
传递要重定向到的一个具体的网址
def my_view(request):
...
return redirect('/some/url/')
固然也能够是一个完整的网址
def my_view(request):
...
return redirect('http://example.com/')
默认状况下,redirect() 返回一个临时重定向。以上全部的形式都接收一个permanent 参数;若是设置为True,将返回一个永久的重定向:
def my_view(request):
...
object = MyModel.objects.get(...)
return redirect(object, permanent=True)
前端交互
自带
区别
建议直接用json格式少一步反序列化
Django模板中只须要记两种特殊符号:
{{ }}和 {% %}
{{ }}表示变量,在模板渲染的时候替换成值,{% %}表示逻辑相关的操做。
{{ 变量名 }}
变量名由字母数字和下划线组成。
点(.)在模板语言中有特殊的含义,用来获取对象的相应属性值。
view中的代码
def template_test(request):
l = [11, 22, 33]
d = {"name": "alex"}
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def dream(self):
return "{} is dream...".format(self.name)
Alex = Person(name="Alex", age=34)
Egon = Person(name="Egon", age=9000)
Eva_J = Person(name="Eva_J", age=18)
person_list = [Alex, Egon, Eva_J]
return render(request, "template_test.html", {"l": l, "d": d, "person_list": person_list})
模板中支持的写法:
{# 取l中的第一个参数 #}
{{ l.0 }}
{# 取字典中key的值 #}
{{ d.name }}
{# 取对象的name属性 #}
{{ person_list.0.name }}
{# .操做只能调用不带参数的方法 #}
{{ person_list.0.dream }}
注:当模板系统遇到一个(.)时,会按照以下的顺序去查询:
在字典中查询
属性或者方法
数字索引
翻译为过滤器,用来修改变量的显示结果。
语法: {{ value|filter_name:参数 }}
'|'左右没有空格没有空格没有空格
{{ value|default:"nothing"}}
若是value值没传的话就显示nothing
注:TEMPLATES的OPTIONS能够增长一个选项:string_if_invalid:'找不到',能够替代default的的做用。
将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:
{{ value|filesizeformat }}
若是 value 是 123456789,输出将会是 117.7 MB。
给变量加参数
{{ value|add:"2" }}
value是数字4,则输出结果为6。
{{ first|add:second }}
若是first是 [1,.2,3] ,second是 [4,5,6] ,那输出结果是 [1,2,3,4,5,6] 。
小写
{{ value|lower }}
upper
大写
{{ value|upper}}
标题
{{ value|title }}
ljust
左对齐
"{{ value|ljust:"10" }}"
rjust
右对齐
"{{ value|rjust:"10" }}"
center
居中
"{{ value|center:"15" }}"
{{ value|length }}
返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.
切片
{{value|slice:"2:-1"}}
取第一个元素
{{ value|first }}
取最后一个元素
{{ value|last }}
使用字符串拼接列表。同python的str.join(list)。
{{ value|join:" // " }}
若是字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:截断的字符数
{{ value|truncatechars:9}}
日期格式化
{{ value|date:"Y-m-d H:i:s"}}
可格式化输出的字符:点击查看。
Django的模板中会对HTML标签和JS等语法标签进行自动转义,缘由显而易见,这样是为了安全。可是有的时候咱们可能不但愿这些HTML元素被转义,好比咱们作一个内容管理系统,后台添加的文章中是通过修饰的,这些修饰多是经过一个相似于FCKeditor编辑加注了HTML修饰符的文本,若是自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,若是是一个单独的变量咱们能够经过过滤器“|safe”的方式告诉Django这段代码是安全的没必要转义。
好比:
value = "<a href='#'>点我</a>"
{{ value|safe}}
时间格式全局化
自定义过滤器只是带有一个或两个参数的Python函数:
n 变量(输入)的值 - -不必定是一个字符串
n 参数的值 - 这能够有一个默认值,或彻底省略
例如,在过滤器{{var | foo:“bar”}}中,过滤器foo将传递变量var和参数“bar”。
自定义filter代码文件摆放位置:
app01/
__init__.py
models.py
templatetags/ # 在app01下面新建一个package package
__init__.py
app01_filters.py # 建一个存放自定义filter的py文件
views.py
编写自定义filter
from django import template
register = template.Library()
@register.filter
def fill(value, arg):
return value.replace(" ", arg)
@register.filter(name="addSB")
def add_sb(value):
return "{} SB".format(value)
使用自定义filter
{# 先导入咱们自定义filter那个文件 #}
{% load app01_filters %}
{# 使用咱们自定义的filter #}
{{ somevariable|fill:"__" }}
{{ d.name|addSB }}
<ul>
{% for user in user_list %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>
for循环可用的一些参数:
Variable Description
forloop.counter 当前循环的索引值(从1开始)
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(从1开始)
forloop.revcounter0 当前循环的倒序索引值(从0开始)
forloop.first 当前循环是否是第一次循环(布尔值)
forloop.last 当前循环是否是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环
for ... empty
<ul>
{% for user in user_list %}
<li>{{ user.name }}</li>
{% empty %}
<li>空空如也</li>
{% endfor %}
</ul>
if,elif和else
{% if user_list %}
用户人数:{{ user_list|length }}
{% elif black_list %}
黑名单数:{{ black_list|length }}
{% else %}
没有用户
{% endif %}
固然也能够只有if和else
{% if user_list|length > 5 %}
七座豪华SUV
{% else %}
黄包车
{% endif %}
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
定义一个中间变量
{% with total=business.employees.count %}
{{ total }} employee{{ total|pluralize }}
{% endwith %}
csrf_token
这个标签用于跨站请求伪造保护。
在页面的form表单里面写上{% csrf_token %}
{# ... #}
1. Django的模板语言不支持连续判断,即不支持如下写法:
{% if a > b > c %}
...
{% endif %}
2. Django的模板语言中属性的优先级大于方法
def xx(request):
d = {"a": 1, "b": 2, "c": 3, "items": "100"}
return render(request, "xx.html", {"data": d})
如上,咱们在使用render方法渲染一个页面的时候,传的字典d有一个key是items而且还有默认的 d.items() 方法,此时在模板语言中:
{{ data.items }}
默认会取d的items key的值。
母板
<!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>
{% block page-css %}
{% endblock %}
</head>
<body>
<h1>这是母板的标题</h1>
{% block page-main %}
{% endblock %}
<h1>母板底部内容</h1>
{% block page-js %}
{% endblock %}
</body>
</html>
注意:咱们一般会在母板中定义页面专用的CSS块和JS块,方便子页面替换。
继承母板
在子页面中在页面最上方使用下面的语法来继承母板。
{% extends 'layouts.html' %}
经过在母板中使用{% block xxx %}来定义"块"。
在子页面中经过定义母板中的block名来对应替换母板中相应的内容。
{% block page-main %}
<p>世情薄</p>
<p>人情恶</p>
<p>雨送黄昏花易落</p>
{% endblock %}
能够将经常使用的页面内容如导航条,页尾信息等组件保存在单独的文件中,而后在须要使用的地方按以下语法导入便可。
{% include 'navbar.html' %}
静态文件相关
{% load static %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />
引用JS文件时使用:
{% load static %}
<script src="{% static "mytest.js" %}"></script>
某个文件多处被用到能够存为一个变量
{% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>
使用get_static_prefix
{% load static %}
<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />
或者
{% load static %}
{% get_static_prefix as STATIC_PREFIX %}
<img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />
和自定义filter相似,只不过接收更灵活的参数。
定义注册simple tag
@register.simple_tag(name="plus")
def plus(a, b, c):
return "{} + {} + {}".format(a, b, c)
使用自定义simple tag
{% load app01_demo %}
{# simple tag #}
{% plus "1" "2" "abc" %}
inclusion_tag
示例:
from django import template
register = template.Library()
@register.inclusion_tag('result.html')
def show_results(n):
n = 1 if n < 1 else int(n)
data = ["第{}项".format(i) for i in range(1, n+1)]
return {"data": data}
<ul>
{% for choice in data %}
<li>{{ choice }}</li>
{% endfor %}
</ul>
<!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>inclusion_tag test</title>
</head>
<body>
{% load my_inclusion %}
{% show_results 10 %}
</body>
</html>
{% empty %}
<h2 class="sub-header">用户管理列表</h2> <a class="btn btn-success" href="{% url 'app01:manage_add' %}">添加</a> <div class="table-responsive"> <table class="table table-bordered table-hover"> <thead> <tr> <th>number</th> <th>ID</th> <th>name</th> <th>password</th> <th>操做</th> </tr> </thead> <tbody> {% for server in server %} <tr> <td>{{ forloop.counter }}</td> <td>{{ server.id }}</td> <td>{{ server.name }}</td> <td>{{ server.password}}</td> <td> <a class="btn btn-success btn-sm" href="">编辑</a> <a class="btn btn-danger btn-sm" href="{% url 'app01:manage_del' pk=server.id %}">删除</a> </td> </tr> {% empty %} <tr> <td colspan="4" style="text-align: center">没有数据</td> </tr> {% endfor %} </tbody> </table> </div>{% endblock %}