内容:css
1.课前复习html
2.django路由规则python
3.django视图函数mysql
4.django ORMjquery
5.模板git
django预备知识:http://www.javashuo.com/article/p-gaxyavsw-bm.htmlweb
django基础参考:http://www.cnblogs.com/wupeiqi/articles/5237704.html正则表达式
1、课前复习sql
1.HTTP协议消息格式数据库
1 请求(request): 2 请求方法 路径 HTTP/1.1\r\n 3 k1:v1\r\n 4 ...\r\n 5 \r\n 6 请求体 <-- 能够有,能够没有 7 8 响应(response): 9 HTTP/1.1 状态码 状态描述符\r\n 10 k1:v1\r\n 11 Content-Type: text/html; charset=utf8\r\n 12 \r\n 13 响应正文 <-- HTML内容
2.python的web框架本质
3.一个完整的请求过程:
2、django路由系统
在django程序中,能够经过urls.py文件对全部的url进行任务的分配,根据路由规则的定义选择不一样的业务处理函数进行处理,urls.py中规定的对应规则能够说是路由系统(URLconf)
关于路由规则的详细内容:http://www.cnblogs.com/liwenzhou/p/8271147.html
1.基本路由规则
基本格式(1.x版本):
1 from django.conf.urls import url 2 3 urlpatterns = [ 4 url(正则表达式, views视图函数,参数,别名), 5 ]
Django 2.0版本路由系统的写法:
1 from django.urls import path 2 3 urlpatterns = [ 4 path('articles/', views.articles), 5 path('articles/<int:year>/', views.year_archive), 6 path('articles/<int:year>/<int:month>/', views.month_archive), 7 path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail), 8 ]
2.路由系统正则表达式详解
基础样例 - 分组匹配:
1 from django.conf.urls import url 2 from . import views 3 4 urlpatterns = [ 5 url(r'^articles/2003/$', views.special_case_2003), 6 url(r'^articles/([0-9]{4})/$', views.year_archive), 7 url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), 8 url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), 9 ]
注意:
上面的示例使用简单的正则表达式分组匹配(经过圆括号)来捕获URL中的值并以位置参数形式传递给视图;在更高级的用法中,可使用分组命名匹配的正则表达式组来捕获URL中的值并以关键字参数形式传递给视图
在Python的正则表达式中,分组命名正则表达式组的语法是(?P<name>pattern)
,其中name
是组的名称,pattern
是要匹配的模式
分组命名匹配:
1 from django.conf.urls import url 2 from . import views 3 4 urlpatterns = [ 5 url(r'^articles/2003/$', views.special_case_2003), 6 url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), 7 url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), 8 url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), 9 ]
这个实现与前面的示例彻底相同,只有一个细微的差异:捕获的值做为关键字参数而不是位置参数传递给视图函数,另外注意不管哪一种方法每一个在路由中捕获的参数都做为一个普通的Python字符串传递给视图
另外views.py中能够给视图函数的参数设置默认值:
3.django路由分发
1个Django 项目里面有多个APP目录你们共有一个 url容易形成混淆,因而路由分发让每一个APP的拥有了本身单独的url:
项目目录下的urls.py:
1 from django.conf.urls import url, include 2 from django.contrib import admin 3 4 urlpatterns = [ 5 # 分发到APP的路由 6 url(r'^basic/', include('basic.urls')), 7 url(r'^app1/', include('app1.urls')), 8 url(r'^app2/', include('app2.urls')), 9 ]
basic这个APP下的urls.py:
1 from django.conf.urls import url 2 from basic import views 3 4 urlpatterns = [ 5 url(r'^index/', views.index), 6 url(r'^login/', views.login), 7 url(r'^register/', views.register), 8 ]
完成上述设置后,basic这个APP的路由只需在本身APP下的urls.py配置便可,访问时前面带上basic路径便可
4.命名URL和URL反向解析
(1)前言
在使用Django 项目时,一个常见的需求是得到URL的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。
人们强烈但愿不要硬编码这些URL(费力、不可扩展且容易产生错误)或者设计一种与URLconf 绝不相关的专门的URL 生成机制,由于这样容易致使必定程度上产生过时的URL。
换句话讲,须要的是一个DRY 机制。除了其它有点,它还容许设计的URL 能够自动更新而不用遍历项目的源代码来搜索并替换过时的URL。
获取一个URL 最开始想到的信息是处理它视图的标识(例如名字),查找正确的URL 的其它必要的信息有视图参数的类型(位置参数、关键字参数)和值。
Django 提供一个办法是让URL 映射是URL 设计惟一的地方。你填充你的URLconf,而后能够双向使用它:
(2)命名URL和URL反向解析
前言中第一种方式是咱们在前面的章节中一直讨论的用法,是直接得到url的最终形式,能够称之为命名URL
而第二种方式叫作反向解析URL或者简单的URL 反查
在须要URL 的地方,对于不一样层级,Django 提供不一样的工具用于URL 反查:
反向解析URL本质上就是给url匹配模式起别名,而后用过别名拿到具体的URL路径
用法以下:
1 起别名: 在url匹配模式中,定义name="别名" 2 3 1. 在模板语言里面使用: 4 {% url "别名" %} --> 获得具体的URL路径 5 6 7 2. 在视图中如何使用: 8 from django.urls import reverse 9 10 reverse("别名") --> 获得具体的URL路径 11 12 13 3. 如何传参数? 14 模板语言中: 15 {% url "别名" 2018 "nb" %} 16 17 视图函数中 18 传位置参数: reverse("别名", args=(2018, "nb")) 19 传关键字参数: reverse("别名" kwargs={"year": 2018, "title": "nb"}) 20 21 22 4. namespace 23 为了防止不一样的app下面的url匹配模式有重复的别名,能够给app起别名
(3)实例以下:
urls.py:
1 urlpatterns = [ 2 url(r'^admin/', admin.site.urls, name="admin"), 3 # 分发到APP的路由 4 url(r'^basic/', include('basic.urls', namespace="basic")), 5 ]
1 urlpatterns = [ 2 url(r'^user_list/', views.user_list, name="user_list"), 3 url(r'^add_user/', views.add_user, name="add_user"),
4 ]
views.py:
1 def user_list(request): 2 res = models.UserInfo.objects.all() 3 return render(request, "user/user_list.html", {"user_list": res}) 4 5 def add_user(request): 6 err_msg = "" 7 if request.method == "POST": 8 new_name = request.POST.get("username", None) 9 new_pwd = request.POST.get("password", None) 10 if new_name and new_pwd: 11 models.UserInfo.objects.create(username=new_name, password=new_pwd) 12 return redirect(reverse("basic:user_list")) 13 else: 14 err_msg = "用户名或密码不能为空!" 15 return render(request, "user/add_user.html", {"error": err_msg})
HTML:
1 <a class="btn btn-default" href="{% url "basic:add_user" %}" role="button">添加用户</a>
3、django视图系统
视图系统简称视图,能够是一个简单的Python 函数,它接受Web请求而且返回Web响应。响应能够是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. . . 是任何东西均可以。不管视图自己包含什么逻辑,都要返回响应。
约定将视图放置在项目或APP目录中的名为views.py中(通常为了模块化都是放在APP的views里)
关于视图系统详细:http://www.cnblogs.com/liwenzhou/articles/8305104.html
1.最简单的视图
不论什么视图都包含两个对象:
最简单的视图:
1 from django.shortcuts import HttpResponse 2 3 def easy_view(request): 4 # 每一个视图函数都使用HttpRequest对象做为第一个参数,而且一般称之为request 5 return HttpResponse("hello world!")
视图函数,围绕着两个对象进行:HttpResponse和HttpRequest
2.HttpRequest
(1)属性
1 request.path 获取访问文件路径 2 request.path_info 获取用户请求的路径(不包含IP和端口和URL参数) 3 request.method 获取请求中使用的HTTP方式(POST/GET) 4 request.body 含全部请求体信息 是bytes类型 5 request.GET GET请求的数据(类字典对象) 请求头中的url中?后面拿值 6 request.POST POST请求的数据(类字典对象) 请求体里拿值 7 8 request.FILES: 包含全部上传文件的类字典对象;FILES中的每个Key都是<input type="file" name="" />标签中 9 name属性的值,FILES中的每个value同时也是一个标准的python字典对象,包含下面三个Keys: 10 filename: 上传文件名,用字符串表示 11 content_type: 上传文件的Content Type 12 content: 上传文件的原始内容 13 14 request.user: 是一个django.contrib.auth.models.User对象,表明当前登录的用户。若是访问用户当前 15 没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你 16 能够经过user的is_authenticated()方法来辨别用户是否登录: 17 if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware 18 时该属性才可用 19 20 request.COOKIES 包含全部cookies的标准Python字典对象;keys和values都是字符串。 21 request.session 惟一可读写的属性,表明当前会话的字典对象;本身有激活Django中的session支持时该属性才可用
属性实例 - 上传文件:
1 def upload(request): 2 """ 3 保存上传文件前,数据须要存放在某个位置。默认当上传文件小于2.5M时,django会将上传文件的所有内容读进内存。从内存读取一次,写磁盘一次。 4 但当上传文件很大时,django会把上传文件写到临时文件中,而后存放到系统临时文件夹中。 5 :param request: 6 :return: 7 """ 8 if request.method == "POST": 9 # 从请求的FILES中获取上传文件的文件名,file-name为页面上type=files类型input的name属性值 10 filename = request.FILES["file-name"].name 11 # 在项目目录下新建一个文件 12 with open(filename, "wb") as f: 13 # 从上传的文件对象中一点一点读 14 for chunk in request.FILES["file-name"].chunks(): 15 # 写入本地文件 16 f.write(chunk) 17 return HttpResponse("上传OK")
(2)方法
1 request.GET.get('name', None) 拿到GET请求里name的值(不存在就为None) 2 request.POST.get('username', None) 拿到GET请求里username的值(不存在就为None) 3 若是某个键对应有多个值,则不能直接用get取值,须要用getlist,如:request.POST.getlist("hobby")
4
5 获取请求路径:
6 请求url: http://127.0.0.1:8000/index.html/23?a=1
7 request.path 结果: /index.html/23
8 request.get_full_path() 结果: /index.html/23?a=1
3.HttpResponse
对于HttpRequest请求对象来讲,是由django自动建立的,可是,HttpResponse响应对象就必须咱们本身建立。每一个view请求处理方法必须返回一个响应。HttpResponse类在django.http.HttpResponse
能够由HttpResponse对象上扩展出多种经常使用方法,以下所示
(1)HttpResponse函数
1 from django.shortcuts import HttpResponse 2 3 4 # 最简单的视图函数 5 def easy_view(request): 6 # 返回最简单的一个响应(一个字符串): hello world! 7 return HttpResponse("hello world!")
补充 - JsonResponse
JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应:
1 from django.http import JsonResponse 2 3 response = JsonResponse({'foo': 'bar'}) 4 print(response.content) 5 6 b'{"foo": "bar"}'
默认只能传递字典类型,若是要传递非字典类型须要设置一下safe关键字参数:
response = JsonResponse([1, 2, 3], safe=False)
(2)render函数
做用:将特色页面渲染后返回给浏览器
渲染 -> 给页面中的参数赋值
render(request, template_name[, context])
结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象
参数以下:
render实例:
1 from django.shortcuts import render 2 3 def my_view(request): 4 # 视图的代码写在这里 5 return render(request, 'index.html', {'foo': 'bar'})
1 def render(request, template_name, context=None, content_type=None, status=None, using=None): 2 """ 3 Returns a HttpResponse whose content is filled with the result of calling 4 django.template.loader.render_to_string() with the passed arguments. 5 """ 6 content = loader.render_to_string(template_name, context, request, using=using) 7 return HttpResponse(content, content_type, status)
关于render:render方法主要是将从服务器提取的数据,填充到模板中,而后将渲染后的html静态文件返回给浏览器
(3)redirect函数
redirect函数主要用于重定向,默认返回一个临时的重定向;传递permanent=True 能够返回一个永久的重定向
参数能够是:
redirect实例:
1 from django.shortcuts import redirect 2 3 # 经过一些对象来重定向(将调用该对象的get_absolute_url方法): 4 def my_view(request): 5 ... 6 object = MyModel.objects.get(...) 7 return redirect(object) 8 9 # 传递视图的名称和可选参数来重定向(将使用reverse方法进行反向解析出url): 10 def my_view(request): 11 ... 12 return redirect('some-view-name', foo='bar') 13 14 # 传递一个url重定向: 15 def my_view(request): 16 ... 17 return redirect('/some/url/')
对比render和redirect:
另外:
临时重定向(响应状态码:302)和永久重定向(响应状态码:301)对普通用户来讲是没什么区别的,它主要面向的是搜索引擎的机器人。
(4)实战 - 简单登陆的完整示例
HTML:
1 form表单日后端提交数据须要注意三点: 2 1. form不是from,全部获取用户输入的标签都应该放在form里面, 而且必需要有name属性 3 2. action属性控制往哪儿提交,method通常都设置成post 4 3. 提交按钮必须是type=submit,不能是别的类型
1 <!-- author: wyb --> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <meta charset="UTF-8"> 6 <!-- 移动端适配 --> 7 <meta name="viewport" content="width=device-width, initial-scale=1"> 8 <title>登陆页面</title> 9 <!-- 引入normalize.css --> 10 <link href="https://cdn.bootcss.com/normalize/8.0.0/normalize.css" rel="stylesheet"> 11 <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> 12 <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" 13 integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> 14 15 <style> 16 body{ 17 background: #eeeeee; 18 } 19 #form-box{ 20 margin-top: 199px; 21 } 22 </style> 23 </head> 24 <body> 25 26 <div class="container-fluid"> 27 <div class="row"> 28 <div class="col-md-4 col-lg-3 col-md-offset-4"> 29 <div id="form-box"> 30 <h3 class="text-center">请登陆</h3> 31 <form class="form-horizontal" method="post" action="/baobao/"> 32 <div class="form-group"> 33 <label for="inputUsername" class="col-sm-3 control-label">用户名</label> 34 <div class="col-sm-9"> 35 <input name="username" type="text" class="form-control" id="inputUsername" placeholder="输入用户名"> 36 </div> 37 </div> 38 <div class="form-group"> 39 <label for="inputPassword3" class="col-sm-3 control-label">密码</label> 40 <div class="col-sm-9"> 41 <input name="password" type="password" class="form-control" id="inputPassword3" placeholder="输入密码"> 42 </div> 43 </div> 44 <div class="form-group"> 45 <div class="col-sm-offset-3 col-sm-9"> 46 <div class="checkbox"> 47 <label> 48 <input type="checkbox"> 记住我 49 </label> 50 </div> 51 </div> 52 </div> 53 <div class="form-group"> 54 <div class="col-sm-offset-3 col-sm-9"> 55 <button type="submit" class="btn btn-primary btn-block">登陆</button> 56 </div> 57 </div> 58 </form> 59 </div> 60 </div> 61 </div> 62 </div> 63 64 65 <!-- 引入jQuery --> 66 <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> 67 <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> 68 <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" 69 integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" 70 crossorigin="anonymous"></script> 71 72 </body> 73 </html>
urls:
1 url(r'^login/', views.login),
2 url(r'^baobao/', views.baobao),
views(GET和POST分开写):
1 def login(request): 2 return render(request, "login.html") 3 4 5 def baobao(request): 6 # 获取用户提交的数据 7 # 获取全部POST的数据: print(request.POST) 8 username = request.POST.get("username", None) 9 password = request.POST.get("password", None) 10 print(username, password) 11 # 作是否登陆成功的判断 12 if username == "wyb" and password == "wyb666": 13 # 登陆成功 14 return HttpResponse("登陆成功!") 15 return HttpResponse("登陆失败!")
views(GET和POST一块儿写):
1 # 先把form表单的action属性去掉(不写就是往当前路由提交) 2 3 # 而后修改login函数以下: 4 def login(request): 5 if request.method == "GET": 6 # 若是是GET请求: 7 return render(request, "login.html") 8 else: 9 # 若是是POST请求: 10 username = request.POST.get("username", None) 11 password = request.POST.get("password", None) 12 print(username, password) 13 # 作是否登陆成功的判断 14 if username == "wyb" and password == "wyb666": 15 # 登陆成功 16 return HttpResponse("登陆成功!") 17 return HttpResponse("登陆失败!")
views优化版:
1 # render和redirect实例 2 # 首先在login.html中的form表单结束以前插入一个p标签(内容: {{ error}}) 3 # 而后修改login函数代码以下: 4 def login(request): 5 error_msg = "" 6 if request.method == "POST": 7 # 若是是POST请求: 8 username = request.POST.get("username", None) 9 password = request.POST.get("password", None) 10 print(username, password) 11 # 作是否登陆成功的判断 12 if username == "wyb" and password == "wyb666": 13 # 登陆成功 14 # return HttpResponse("登陆成功!") 15 # 回复一个特殊的响应(重定向) 这个响应让用户的浏览器自动请求指定的url 16 return redirect("http://www.luffycity.com") 17 else: 18 # 登陆失败 19 error_msg = "用户名或密码错误" 20 # 不是POST走这下面: 21 return render(request, "login.html", {"error": error_msg})
(5)CBV和FBV
以前写过的都是基于函数的view,就叫FBV。还能够把view写成基于类的。
就拿上面写的登录为例:
FBV版:
1 # FBV版登录 2 def login(request): 3 error_msg = "" 4 if request.method == "POST": 5 username = request.POST.get("username", None) 6 password = request.POST.get("password", None) 7 7 if username == "wyb" and password == "safsfwefvs": 8 return HttpResponse("登陆成功!") 9 else: 10 error_msg = "登录失败: 用户名或密码错误" 11 return render(request, "user/login.html", {"error": error_msg})
CBV版:
1 # CBV版登录: 2 from django.views import View 3 4 class Login(View): 5 def get(self, request): 6 return render(request, "user/login.html") 7 8 def post(self, request): 9 username = request.POST.get("username", None) 10 password = request.POST.get("password", None) 11 if username == "wyb" and password == "sdfsadf": 12 return HttpResponse("登陆成功!") 13 else: 14 error_msg = "登录失败: 用户名或密码错误" 15 return HttpResponse(error_msg)
注意当使用CBV时,urls.py中也作对应的修改:
# urls.py中 url(r'^login/$', views.Login.as_view()),
4、django ORM
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。
简单的说,ORM是经过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
ORM在业务逻辑层和数据库层之间充当了桥梁的做用
ORM详细内容:http://www.cnblogs.com/liwenzhou/articles/8276526.html
1.ORM介绍
(1)django中的数据库操做
到目前为止,当咱们的程序涉及到数据库相关操做时,咱们通常会这样作:
django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)来完成上述的数据访问层
django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表
(2)ORM优缺点
优势:
缺点:
(3)ORM补充说明
ORM对应关系:
1 类 ---> 数据表 2 对象 ---> 数据行 3 属性 ---> 字段
实例以下:
ORM能作的事:
另外注意ORM不能建立数据库,须要本身动手建立数据库
2.django中ORM基础配置
(1)建立数据库
create database 数据库名;
(2)设置数据库配置
在Django项目中的settings.py中设置链接数据库的相关配置(告诉Django链接哪个数据库)
1 # Database 2 # https://docs.djangoproject.com/en/1.11/ref/settings/#databases 3 4 # 默认使用sqlite数据库 5 # DATABASES = { 6 # 'default': { 7 # 'ENGINE': 'django.db.backends.sqlite3', 8 # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 9 # } 10 # } 11 12 # 数据库相关配置: 13 DATABASES = { 14 'default': { 15 'ENGINE': 'django.db.backends.mysql', # 链接的数据库类型 16 'HOST': '127.0.0.1', # 链接数据库的地址 17 'PORT': 3306, # 端口 18 'NAME': "django", # 数据库名称 19 'USER': 'root', # 用户 20 'PASSWORD': 'root' # 密码 21 } 22 }
(3)__init__.py添加内容
告诉Django用pymysql代替默认的MySQLDB 链接MySQL数据库
在项目/__init__.py文件中,写下面两句:
1 import pymysql 2 # 告诉Django用pymysql来代替默认的MySQLdb 3 pymysql.install_as_MySQLdb()
3.django中ORM使用步骤
(1)定义类
在app下面的models.py文件中定义一个类,这个类必须继承models.Model
1 # ORM相关的只能写在这个文件里,写到别的文件里django找不到 2 from django.db import models 3 4 5 class UserInfo(models.Model): 6 id = models.AutoField(primary_key=True) # 建立一个自增的主键字段 7 # 用户名及密码 8 username = models.CharField(null=False, max_length=20) 9 password = models.CharField(null=False, max_length=64)
(2)执行如下命令
4.ORM字段
(1)Django ORM经常使用字段
1 AutoField(Field) 2 - int自增列,必须填入参数 primary_key=True 3 4 BigAutoField(AutoField) 5 - bigint自增列,必须填入参数 primary_key=True 6 7 注:当model中若是没有自增列,则自动会建立一个列名为id的列 8 from django.db import models 9 10 class UserInfo(models.Model): 11 # 自动建立一个列名为id的且为自增的整数列 12 username = models.CharField(max_length=32) 13 14 class Group(models.Model): 15 # 自定义自增列 16 nid = models.AutoField(primary_key=True) 17 name = models.CharField(max_length=32) 18 19 SmallIntegerField(IntegerField): 20 - 小整数 -32768 ~ 32767 21 22 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 23 - 正小整数 0 ~ 32767 24 IntegerField(Field) 25 - 整数列(有符号的) -2147483648 ~ 2147483647 26 27 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 28 - 正整数 0 ~ 2147483647 29 30 BigIntegerField(IntegerField): 31 - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 32 33 BooleanField(Field) 34 - 布尔值类型 35 36 NullBooleanField(Field): 37 - 能够为空的布尔值 38 39 CharField(Field) 40 - 字符类型 41 - 必须提供max_length参数, max_length表示字符长度 42 43 TextField(Field) 44 - 文本类型 45 46 EmailField(CharField): 47 - 字符串类型,Django Admin以及ModelForm中提供验证机制 48 49 IPAddressField(Field) 50 - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 51 52 GenericIPAddressField(Field) 53 - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 54 - 参数: 55 protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6" 56 unpack_ipv4, 若是指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,须要protocol="both" 57 58 URLField(CharField) 59 - 字符串类型,Django Admin以及ModelForm中提供验证 URL 60 61 SlugField(CharField) 62 - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、链接符(减号) 63 64 CommaSeparatedIntegerField(CharField) 65 - 字符串类型,格式必须为逗号分割的数字 66 67 UUIDField(Field) 68 - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 69 70 FilePathField(Field) 71 - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 72 - 参数: 73 path, 文件夹路径 74 match=None, 正则匹配 75 recursive=False, 递归下面的文件夹 76 allow_files=True, 容许文件 77 allow_folders=False, 容许文件夹 78 79 FileField(Field) 80 - 字符串,路径保存在数据库,文件上传到指定目录 81 - 参数: 82 upload_to = "" 上传文件的保存路径 83 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage 84 85 ImageField(FileField) 86 - 字符串,路径保存在数据库,文件上传到指定目录 87 - 参数: 88 upload_to = "" 上传文件的保存路径 89 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage 90 width_field=None, 上传图片的高度保存的数据库字段名(字符串) 91 height_field=None 上传图片的宽度保存的数据库字段名(字符串) 92 93 DateTimeField(DateField) 94 - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] 95 96 DateField(DateTimeCheckMixin, Field) 97 - 日期格式 YYYY-MM-DD 98 99 TimeField(DateTimeCheckMixin, Field) 100 - 时间格式 HH:MM[:ss[.uuuuuu]] 101 102 DurationField(Field) 103 - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 104 105 FloatField(Field) 106 - 浮点型 107 108 DecimalField(Field) 109 - 10进制小数 110 - 参数: 111 max_digits,小数总长度 112 decimal_places,小数位长度 113 114 BinaryField(Field) 115 - 二进制类型 116 117 字段合集
(2) 自定义char字段
1 class FixedCharField(models.Field): 2 """ 3 自定义的char类型的字段类 4 """ 5 def __init__(self, max_length, *args, **kwargs): 6 self.max_length = max_length 7 super(FixedCharField, self).__init__(max_length=max_length, *args, **kwargs) 8 9 def db_type(self, connection): 10 """ 11 限定生成数据库表的字段类型为char,长度为max_length指定的值 12 """ 13 return 'char(%s)' % self.max_length
(3)经常使用的字段参数
DateField和DateTimeField才有的参数:
(4)关系字段
ForeignKey:
外键类型在ORM中用来表示外键关联关系,通常把ForeignKey字段设置在 '一对多'中'多'的一方。
字段参数以下:
db_constraint:是否在数据库中建立外键约束,默认为True,赋值为False,表示为软关联
1 models.CASCADE: 2 删除关联数据,与之关联也删除 3 4 models.DO_NOTHING: 5 删除关联数据,引起错误IntegrityError 6 7 models.PROTECT: 8 删除关联数据,引起错误ProtectedError 9 10 models.SET_NULL: 11 删除关联数据,与之关联的值设置为null(前提FK字段须要设置为可空) 12 13 models.SET_DEFAULT: 14 删除关联数据,与之关联的值设置为默认值(前提FK字段须要设置默认值) 15 16 models.SET: 17 删除关联数据, 18 a. 与之关联的值设置为指定值,设置:models.SET(值) 19 b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
OneToOneField:
一对一字段 一般一对一字段用来扩展已有字段。
字段参数:
示例:
1 # 一对一的关联关系多用在当一张表的不一样字段查询频次差距过大的状况下,将本能够存储在一张表的字段拆开放置在两张表中, 2 # 而后将两张表创建一对一的关联关系。 3 4 class Author(models.Model): 5 name = models.CharField(max_length=32) 6 info = models.OneToOneField(to='AuthorInfo') 7 8 class AuthorInfo(models.Model): 9 phone = models.CharField(max_length=11) 10 email = models.EmailField()
ManyToManyField:
用于表示多对多的关联关系。在数据库中经过第三张表来创建关联关系。
字段参数:
实例:
1 class Person(models.Model): 2 name = models.CharField(max_length=16) 3 friends = models.ManyToManyField("self") 4 # 此时,person对象就没有person_set属性。 5 6 class Person(models.Model): 7 name = models.CharField(max_length=16) 8 friends = models.ManyToManyField("self", symmetrical=False) 9 # 此时,person对象如今就可使用person_set属性进行反向查询。
1 # 方式一:自行建立第三张表 2 class Book(models.Model): 3 title = models.CharField(max_length=32, verbose_name="书名") 4 5 class Author(models.Model): 6 name = models.CharField(max_length=32, verbose_name="做者姓名") 7 8 9 # 本身建立第三张表,分别经过外键关联书和做者 10 class Author2Book(models.Model): 11 author = models.ForeignKey(to="Author") 12 book = models.ForeignKey(to="Book") 13 14 class Meta: 15 unique_together = ("author", "book") 16 17 18 # 方式二:经过ManyToManyField自动建立第三张表 19 class Book(models.Model): 20 title = models.CharField(max_length=32, verbose_name="书名") 21 22 # 经过ORM自带的ManyToManyField自动建立第三张表 23 class Author(models.Model): 24 name = models.CharField(max_length=32, verbose_name="做者姓名") 25 books = models.ManyToManyField(to="Book", related_name="authors") 26 27 28 # 方式三:设置ManyTomanyField并指定自行建立的第三张表 29 class Book(models.Model): 30 title = models.CharField(max_length=32, verbose_name="书名") 31 32 # 本身建立第三张表,并经过ManyToManyField指定关联 33 class Author(models.Model): 34 name = models.CharField(max_length=32, verbose_name="做者姓名") 35 books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book")) 36 # through_fields接受一个2元组('field1','field2'): 37 # 其中field1是定义ManyToManyField的模型外键的名(author),field2是关联目标模型(book)的外键名。 38 39 class Author2Book(models.Model): 40 author = models.ForeignKey(to="Author") 41 book = models.ForeignKey(to="Book") 42 43 class Meta: 44 unique_together = ("author", "book") 45 46 # 注意: 当咱们须要在第三张关系表中存储额外的字段时,就要使用第三种方式 47 可是当咱们使用第三种方式建立多对多关联关系时,就没法使用set、add、remove、clear方法来管理多对多的关系了, 48 须要经过第三张表的model来管理多对多关系
(5)元信息
ORM对应的类里面包含另外一个Meta类,而Meta类封装了一些数据库的信息。主要字段以下:
例如设置重写表名:
1 class Meta: 2 db_table = "xxx"
5.ORM操做
(1)操做数据表 --> 建立表/删除表/修改表
使用ORM操做数据表实际上就是按上述ORM使用步骤来操做models.py里面的类(把上面第一步替换成以下步骤):
(2)操做数据行 --> 数据的增删改查
ORM操做数据详细讲解看这里:http://www.javashuo.com/article/p-emhmbenx-bp.html
详细以下:
1 # 增: 2 # 3 # models.Tb.objects.create(c1='xx', c2='oo') 增长一条数据,能够接受字典类型数据 **kwargs 4 # obj = models.Tb(c1='xx', c2='oo') 5 # obj.save() 6 7 8 # 查 9 # 10 # models.Tb.objects.all() # 获取所有 11 # models.Tb.objects.filter(name='seven') # 获取指定条件的数据 12 13 # 删 14 # 15 # models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据 16 17 # 改 18 # models.Tb1.objects.filter(name='seven').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs 19 # obj = models.Tb1.objects.get(id=1) 20 # obj.c1 = '111' 21 # obj.save() # 修改单条数据 22 23 24
6.ORM表关系
(1)三种表关系
ORM表关系有以下三种:
实例以下:
一对多:当一张表中建立一行数据时,有一个单选的下拉框(能够被重复选择)
例如:建立用户信息时候,须要选择一个用户类型【普通用户】【会员用户】【超级会员用户】等
多对多:在某表中建立一行数据是,有一个能够多选的下拉框
例如:建立用户信息,须要为用户指定多个爱好 但同时一个爱好能够被多个用户选择
一对一: 好比公司对应的董事长只能有一个
(2)详细使用
1 ForeignKey(ForeignObject) # ForeignObject(RelatedField) 2 to, # 要进行关联的表名 3 to_field=None, # 要关联的表中的字段名称 4 on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为 5 - models.CASCADE,删除关联数据,与之关联也删除 6 - models.DO_NOTHING,删除关联数据,引起错误IntegrityError 7 - models.PROTECT,删除关联数据,引起错误ProtectedError 8 - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段须要设置为可空) 9 - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段须要设置默认值) 10 - models.SET,删除关联数据, 11 a. 与之关联的值设置为指定值,设置:models.SET(值) 12 b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象) 13 14 def func(): 15 return 10 16 17 class MyModel(models.Model): 18 user = models.ForeignKey( 19 to="User", 20 to_field="id" 21 on_delete=models.SET(func),) 22 related_name=None, # 反向操做时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all() 23 related_query_name=None, # 反向操做时,使用的链接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名') 24 limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件: 25 # 如: 26 - limit_choices_to={'nid__gt': 5} 27 - limit_choices_to=lambda : {'nid__gt': 5} 28 29 from django.db.models import Q 30 - limit_choices_to=Q(nid__gt=10) 31 - limit_choices_to=Q(nid=8) | Q(nid__gt=10) 32 - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') 33 db_constraint=True # 是否在数据库中建立外键约束 34 parent_link=False # 在Admin中是否显示关联数据 35 36 37 OneToOneField(ForeignKey) 38 to, # 要进行关联的表名 39 to_field=None # 要关联的表中的字段名称 40 on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为 41 42 ###### 对于一对一 ###### 43 # 1. 一对一其实就是 一对多 + 惟一索引 44 # 2.当两个类之间有继承关系时,默认会建立一个一对一字段 45 # 以下会在A表中额外增长一个c_ptr_id列且惟一: 46 class C(models.Model): 47 nid = models.AutoField(primary_key=True) 48 part = models.CharField(max_length=12) 49 50 class A(C): 51 id = models.AutoField(primary_key=True) 52 code = models.CharField(max_length=1) 53 54 ManyToManyField(RelatedField) 55 to, # 要进行关联的表名 56 related_name=None, # 反向操做时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all() 57 related_query_name=None, # 反向操做时,使用的链接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名') 58 limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件: 59 # 如: 60 - limit_choices_to={'nid__gt': 5} 61 - limit_choices_to=lambda : {'nid__gt': 5} 62 63 from django.db.models import Q 64 - limit_choices_to=Q(nid__gt=10) 65 - limit_choices_to=Q(nid=8) | Q(nid__gt=10) 66 - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') 67 symmetrical=None, # 仅用于多对多自关联时,symmetrical用于指定内部是否建立反向操做的字段 68 # 作以下操做时,不一样的symmetrical会有不一样的可选字段 69 models.BB.objects.filter(...) 70 71 # 可选字段有:code, id, m1 72 class BB(models.Model): 73 74 code = models.CharField(max_length=12) 75 m1 = models.ManyToManyField('self',symmetrical=True) 76 77 # 可选字段有: bb, code, id, m1 78 class BB(models.Model): 79 80 code = models.CharField(max_length=12) 81 m1 = models.ManyToManyField('self',symmetrical=False) 82 83 through=None, # 自定义第三张表时,使用字段用于指定关系表 84 through_fields=None, # 自定义第三张表时,使用字段用于指定关系表中那些字段作多对多关系表 85 from django.db import models 86 87 class Person(models.Model): 88 name = models.CharField(max_length=50) 89 90 class Group(models.Model): 91 name = models.CharField(max_length=128) 92 members = models.ManyToManyField( 93 Person, 94 through='Membership', 95 through_fields=('group', 'person'), 96 ) 97 98 class Membership(models.Model): 99 group = models.ForeignKey(Group, on_delete=models.CASCADE) 100 person = models.ForeignKey(Person, on_delete=models.CASCADE) 101 inviter = models.ForeignKey( 102 Person, 103 on_delete=models.CASCADE, 104 related_name="membership_invites", 105 ) 106 invite_reason = models.CharField(max_length=64) 107 db_constraint=True, # 是否在数据库中建立外键约束 108 db_table=None, # 默认建立第三张表时,数据库中表的名称
(3)ORM多对多关联查询原理
多对多其实本质上要经过一张中间表来实现查找,中间表就以下图中的author2book表:
(4)使用实例 - 图书管理系统
表结构说明:
1 图书管理系统: 2 主要是练习增删改查操做以及表与表之间的关联关系 3 4 图书管理系统的三种角色: 出版社、书、做者,这三种关系对应三张表 5 6 表之间的关系 7 一本书 只能 有一个出版社 8 一本书 能有 多个做者 9 一个做者 能写 多本书 10 11 出版社和书: 一对多 --> 外键(放在多的一端) 12 书和做者: 多对多 --> 用第三张表作关联
ORM类以下:
1 from django.db import models 2 3 # 出版社 4 class Publisher(models.Model): 5 id = models.AutoField(primary_key=True) 6 # 建立一个惟一的不为空的字段 7 name = models.CharField(max_length=64, null=False, unique=True) 8 9 def __str__(self): 10 return "<Publisher Object: {}>".format(self.name) 11 12 13 # 书 14 class Book(models.Model): 15 id = models.AutoField(primary_key=True) 16 # 建立一个惟一的不为空的字段 17 title = models.CharField(max_length=64, null=False, unique=True) 18 # 和出版社关联的外键字段 存储到数据中会自动加上_id变成publisher_id 19 publisher = models.ForeignKey(to="Publisher") 20 21 def __str__(self): 22 return "<Book Object: {}>".format(self.title) 23 24 25 # 做者 26 class Author(models.Model): 27 id = models.AutoField(primary_key=True) 28 name = models.CharField(max_length=32, null=False, unique=True) 29 book = models.ManyToManyField(to="Book") # 告诉ORM Author和Book是多对多关系 自动生成第三张表 30 31 def __str__(self): 32 return "<Author Object: {}>".format(self.name)
添加书籍:
1 def add_book(request): 2 if request.method == "POST": 3 new_title = request.POST.get("book_title") 4 new_publisher_id = request.POST.get("publisher") # 书籍关联的出版社id 5 # print(new_title, new_publisher_id) 6 if new_title: 7 models.Book.objects.create(title=new_title, publisher_id=new_publisher_id) 8 9 return redirect("/book/book_list/")
添加做者:
1 def add_author(request): 2 if request.method == "POST": 3 # 注意post提交若是获取多选要用getlist: 4 author_name = request.POST.get("author_name") 5 books = request.POST.getlist("books") # book的一系列id 6 # print(author_name, books) 7 # 建立做者并把做者和书籍创建关系 8 if author_name: 9 new_author_obj = models.Author.objects.create(name=author_name) 10 new_author_obj.book.set(books) 11 12 return redirect("/book/author_list/")
编辑书籍:
1 def edit_book(request): 2 if request.method == "POST": 3 # 从提交的数据里面取要编辑的书的如下内容: id 书名 书关联的出版社 4 edit_id = request.POST.get("id") 5 new_title = request.POST.get("book_title") 6 new_publisher_id = request.POST.get("publisher") 7 # 书名为空或书关联的出版社不存在时重定向 8 if not new_title or not models.Publisher.objects.filter(id=new_publisher_id): 9 return redirect("/book/book_list/") 10 # 更新 11 edit_book_obj = models.Book.objects.filter(id=edit_id)[0] 12 if edit_book_obj: 13 edit_book_obj.title = new_title # 更新书名 14 edit_book_obj.publisher_id = new_publisher_id # 更新书籍关联的出版社 15 # 将修改提交到数据库 16 edit_book_obj.save() 17 else: 18 return HttpResponse("书籍不存在!") 19 # 返回书籍列表页面,查看是否编辑成功 20 return redirect("/book/book_list/")
编辑做者:
1 def edit_author(request): 2 if request.method == "POST": 3 # 从提交的数据里面取要编辑的做者的如下内容: id 做者名 做者的一系列做品id 4 edit_author_id = request.POST.get("author_id") 5 new_author_name = request.POST.get("author_name") 6 new_books = request.POST.getlist("books") 7 print(edit_author_id, new_author_name, new_books) 8 # 做者名为空时重定向 9 if not new_author_name: 10 return redirect("/book/author_list/") 11 # 更新 12 edit_author_obj = models.Author.objects.filter(id=edit_author_id)[0] 13 if edit_author_obj: 14 edit_author_obj.name = new_author_name # 更新做者名 15 edit_author_obj.book.set(new_books) # 更新做者关联的做品 16 # 将修改提交到数据库 17 edit_author_obj.save() 18 else: 19 return HttpResponse("做者不存在!") 20 # 返回书籍列表页面,查看是否编辑成功 21 return redirect("/book/author_list/")
注意:以上添加功能和编辑功能没有get请求,实际上在这里后端省去了对get请求的处理(也就是添加和编辑没有新页面出现),
在这里点击添加或编辑后会在当前页面(书籍列表页或做者列表页)出现一个弹框,点击弹框的提交键便可向后端提交数据,
关于弹框的实现,能够自定义弹框,也可使用Bootstrap的弹框样式,我我的是直接使用Bootstrap的弹框
7.其余
数据已有数据修改表结构问题:
5、模板
模板详细内容:http://www.cnblogs.com/liwenzhou/p/7931828.html
1.经常使用语法
只须要记两种特殊符号:{{ }}和 {% %}
变量相关的用{{}},逻辑相关的用{%%}
(1)变量相关
1 {{ 变量名 }} -> 变量名由字母数字和下划线组成 2 点(.)在模板语言中有特殊的含义,用来获取对象的相应属性值 3 4 {# 这是注释 #} 5 6 {# 取s中的第一个参数 #} 7 {{ s.0 }} 8 {# 取字典中key的值 #} 9 {{ d.name }} 10 {# 取对象的name属性 #} 11 {{ person_list.0.name }} 12 {# .操做只能调用不带参数的方法 #} 13 {{ person_list.0.dream }}
(2)tags
1 # for相关 2 for循环: 3 <ul> 4 {% for user in user_list %} 5 <li>{{ user.name }}</li> 6 {% endfor %} 7 </ul> 8 9 for循环中可用的参数: 10 forloop.counter 当前循环的索引值(从1开始) 11 forloop.counter0 当前循环的索引值(从0开始) 12 forloop.revcounter 当前循环的倒序索引值(从1开始) 13 forloop.revcounter0 当前循环的倒序索引值(从0开始) 14 forloop.first 当前循环是否是第一次循环(布尔值) 15 forloop.last 当前循环是否是最后一次循环(布尔值) 16 forloop.parentloop 本层循环的外层循环 17 18 for ... empty: 19 <ul> 20 {% for user in user_list %} 21 <li>{{ user.name }}</li> 22 {% empty %} 23 <li>空空如也</li> 24 {% endfor %} 25 </ul> 26 27 28 # if相关 29 if和else: 30 {% if 判断条件 %} 31 xxx 32 {% else %} 33 xxx 34 {% endif %} 35 36 37 if,elif和else: 38 {% if 判断条件 %} 39 xxx 40 {% elif 判断条件 %} 41 xxx 42 {% else %} 43 xxx 44 {% endif %} 45 46 另外if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断 47 if ... in 判断: 48 {% if xxx in xxx %} 49 ... 50 {% endif %} 51 52 53 with: 定义一个中间变量 54 {% with total=business.employees.count %} 55 {{ total }} employee{{ total|pluralize }} 56 {% endwith %}
(3)filter
filter主要是针对模板中的变量作一些额外的操做,语法: {{ value|filter_name:参数 }}
常见的以下:
safe - 关闭自动转义
Django的模板中会对HTML标签和JS等语法标签进行自动转义,缘由显而易见,这样是为了安全(防止XSS攻击)。可是有的时候咱们可能不但愿这些HTML元素被转义,好比咱们作一个内容管理系统,后台添加的文章中是通过修饰的,这些修饰多是经过一个相似于FCKeditor编辑加注了HTML修饰符的文本,若是自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,若是是一个单独的变量咱们能够经过过滤器“|safe”的方式告诉Django这段代码是安全的没必要转义。
好比:
value = "<a href='#'>点我</a>"
1 {{ value|safe}}
自定义filter
自定义过滤器只是带有一个或两个参数的Python函数:
例如,在过滤器{{var|foo:“bar”}}中,过滤器foo将传递变量var和参数“bar”。
自定义filter代码文件(py文件)要放在以下位置:
1 app/ 2 __init__.py 3 models.py 4 templatetags/ # 在app下面新建一个package package 5 __init__.py 6 app_filters.py # 建一个存放自定义filter的文件 7 views.py
编写自定义filter:
1 from django import template 2 register = template.Library() 3 4 # 带参数的filter 5 @register.filter(name="cut") 6 def cut(value, arg): 7 return value.replace(arg, "") 8 9 # 不带参数的filter 10 @register.filter(name="addSB") 11 def add_sb(value): 12 return "{} SB".format(value)
上述代码注释中的参数是指filter中的参数,而真正函数中的第一个参数(函数参数)永远传入的是value的值(|前面那个值)
使用自定义filter:
1 {# 先导入咱们自定义filter那个文件 #} 2 {% load app_filters %} 3 4 {# 使用咱们自定义的filter #} 5 {{ somevariable|cut:"0" }} 6 {{ d.name|addSB }}
2.母版和继承
(1)为何要有母版和继承
把多个页面公用的部分提取出来,放在一个 母版 里面。其余的页面只须要 继承 母版就能够了。能够简化代码,写更少的代码
(2)具体使用步骤
base.html:
1 <!-- 页面主体 --> 2 <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main"> 3 {% block page-main %} 4 5 {% endblock %} 6 </div>
具体的页面中:
1 {# 继承母版 #} 2 {% extends "base.html" %} 3 4 {# 把本身页面的内容塞到母版中相应的位置 #} 5 6 {% block page-main %} 7 <h1>这是具体页面</h1> 8 {% endblock %}
(3)使用的注意事项
3.组件及静态文件
(1)什么是模板中的组件
能够将经常使用的页面内容如导航条,页尾信息等组件保存在单独的文件中,而后在须要使用的地方按以下语法导入便可:
1 {% include 'navbar.html' %}
(2)静态文件导入问题
静态文件:图片、CSS、js
前面咱们的静态文件的路径都是写死的,如过将static文件夹的名字改成static333,在代码中咱们还要修改多处,这样十分不方便,不过django中提供了方法,可让HTML中的静态文件路径动态跟随文件夹的名字变化而变化,从而实现动态导入
引入CSS:
1 {% load static %} 2 <link href="{% static 'CSS路径' %}" rel="stylesheet">
引入图片:
1 {% load static %} 2 <img src="{% static '图片路径' %}" alt="Hi" />
引用JS文件:
1 {% load static %} 2 <script src="{% static 'js路径' %}"></script>
上述导入实例:
另外某个文件多处被用到能够存为一个变量:
1 {% load static %} 2 {% static "images/hi.jpg" as myphoto %} 3 <img src="{{ myphoto }}"></img>
(3)get_static_prefix
上面的导入静态文件过程,是自动拼接static目录名和后面的路径,导入咱们也能够手动拼接:
1 {% load static %} 2 <img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" /> 3 4 或者: 5 {% load static %} 6 {% get_static_prefix as STATIC_PREFIX %} 7 8 <img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" /> 9 <img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />
(4)自定义simpletag
相似上面的自定义filter不过使用起来更加自由
自定义simpletag文件(py文件)放在以下位置:
1 app/ 2 __init__.py 3 models.py 4 templatetags/ # 在app下面新建一个package -> 放自定义filter文件和自定义simpletag文件 5 __init__.py 6 app_filters.py # 建一个存放自定义filter的文件 7 app_simpletag.py # 建一个存放自定义simpletag的文件 8 views.py
编写自定义simpletag:
1 from django import template 2 3 register = template.Library() 4 5 @register.simple_tag(name="plus") 6 def plus(a, b, c): 7 return "{} + {} + {}".format(a, b, c)
使用自定义simpletag:
1 {% load app_simpletag.py %} 2 3 {# simple tag #} 4 {% plus "1" "2" "abc" %}
(5)inclusion_tag
上面的自定义simpletag没法返回HTML,要返回HTML就要使用inclusion_tag,使用方法以下:
1 templatetags/my_inclusion.py: 2 from django import template 3 register = template.Library() 4 5 @register.inclusion_tag('result.html') 6 def show_results(n): 7 n = 1 if n < 1 else int(n) 8 data = ["第{}项".format(i) for i in range(1, n+1)] 9 return {"data": data} 10 11 12 templates/result.html:13 <ul> 14 {% for choice in data %} 15 <li>{{ choice }}</li> 16 {% endfor %} 17 </ul> 18 19 20 templates/index.html: 21 <!DOCTYPE html> 22 <html lang="en"> 23 <head> 24 <meta charset="UTF-8"> 25 <meta http-equiv="x-ua-compatible" content="IE=edge"> 26 <meta name="viewport" content="width=device-width, initial-scale=1"> 27 <title>inclusion_tag test</title> 28 </head> 29 <body> 30 31 {% load inclusion_tag_test %} 32 {% show_results 10 %} 33 34 </body> 35 </html>