django基础之路由、视图、模板、表单验证
路由
Django 默认项目有根 urls.py,各 app 下分别有自己的 urls.py,既集中又分治,是一种解耦的模式。
from django.urls import include, path
urlpatterns = [
path('article/', include('article.urls')),
path('contact/', include('contact.urls')),
]
URL 配置
from django.urls import path
from . import views
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),
]
urlpatterns = [
path('<page_slug>-<page_id>/', include([
path('history/', views.history),
path('edit/', views.edit),
path('discuss/', views.discuss),
path('permissions/', views.permissions),
])),
]
URL 配置不检查使用何种 HTTP 请求方法,所有请求方法 POST、GET、HEAD 等都将路由到同一个 URL 的同一个视图。在视图中,才根据具体请求方法的不同,进行不同的处理。
注意:
- 要从 URL 中取值,使用尖括号。
- 捕获的值可以选择性地包含转换器类型。
常用路径转换器
-
str
匹配除了 '/' 之外的非空字符串。如果表达式内不包含转换器,则会默认匹配字符串。
-
int
匹配 0 或任何正整数。返回一个 int 。
-
slug
匹配任意由 ASCII 字母或数字以及连字符和下划线组成的短标签。比如,building-your-1st-django-site 。
-
uuid
匹配一个格式化的 UUID 。为了防止多个 URL 映射到同一个页面,必须包含破折号并且字符都为小写。比如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID 实例。
-
path
匹配非空字段,包括路径分隔符 '/' 。它允许你匹配完整的 URL 路径而不是像 str 那样匹配 URL 的一部分。
使用正则表达式
如果路径和转化器语法不能很好的定义你的 URL 模式,你可以可以使用正则表达式。如果要这样做,请使用 re_path() 而不是 path() 。
在 Python 正则表达式中,命名正则表达式组的语法是 (?P
from django.urls import path, re_path
from . import views
urlpatterns = [
path("articles/2003/", views.special_case_2003),
re_path(r"^articles/(?P<year>[0-9]{4})/$", views.year_archive),
re_path(r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.month_archive),
re_path(
r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$",
views.article_detail,
),
]
无论正则表达式进行哪种匹配,每个捕获的参数都作为字符串发送到视图。
当从使用 path() 切换到 re_path() (反之亦然),要特别注意,视图参数类型可能发生变化
向视图传递额外的参数
urlpatterns = [
path('blog/<int:year>/', views.year_archive, {'foo': 'bar'}),
]
urlpatterns = [
path('blog/', include('inner'), {'blog_id': 3}),
]
路由反向解析
命名 URL
urlpatterns = [
path('articles/<int:year>/', views.year_archive, name='news-year-archive'),
]
模板中使用
<a href="{% url 'news-year-archive' 2020 %}">2020 Archive</a>
<a href="{% url 'news-year-archive' year %}">{{ year }} Archive</a>
视图中使用
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
实例命名空间 namespace
urlpatterns = [
path('author/', include('app.urls', namespace='author')),
path('publisher/', include('app.urls', namespace='publisher')),
]
视图
from django.shortcuts import render,HttpResponse
def index(request):
if request.resolver_match.namespace == 'author':
return HttpResponse(reverse('author:index'))
elif request.resolver_match.namespace == 'publisher':
return HttpResponse(reverse('publisher:index'))
else:
return HttpResponse('其它')
def detail(request):
if request.resolver_match.namespace == 'author':
return HttpResponse('这里是作者的页面')
elif request.resolver_match.namespace == 'publisher':
return HttpResponse('这里是出版商的页面')
else:
return HttpResponse('其它')
模板中使用
{% url 'author:index' %}
{% url 'publisher:index' %}
内置快捷方法
-
render()
将给定的模板与给定的上下文字典组合在一起,并以渲染的文本返回一个 HttpResponse 对象。
return render(request, 'myapp/index.html', {'foo': 'bar'}, content_type='application/xhtml+xml') -
redirect()
返回一个 HttpResponseRedirect,指向传递参数的适当 URL。
默认情况下发出临时重定向;通过传递 permanent=True 发出永久重定向。return redirect('news-year-archive', year=2023) -
get_object_or_404()
常用于查询某个对象,找到了则进行下一步处理,如果未找到则给用户返回 404 页面
obj = get_object_or_404(Entry, pk=1) obj = get_object_or_404(Book.objects.filter(title__startswith='M'), pk=1) obj = get_object_or_404(Book, title__startswith='M', pk=1) -
get_list_or_404()
get_object_or_404 的多值获取版本
my_objects = get_list_or_404(MyModel, published=True)
异步视图
异步(“async”)函数,通常使用 Python 的 async def 语法定义。Django 会自动检测这些函数,并在异步上下文中运行它们。但是,你需要使用基于 ASGI 的异步服务器来获得它们的性能优势。
import datetime
from django.http import HttpResponse
async def current_datetime(request):
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
视图装饰器
from django.views.decorators.http import require_http_methods,require_GET,require_POST,require_safe,condition
from django.views.decorators.vary import vary_on_cookie,vary_on_headers
from django.views.decorators.cache import cache_control,never_cache
from django.views.decorators.gzip import gzip_page
# 只有 GET 或者 POST 请求可以访问这个视图
@require_http_methods(["GET", "POST"])
def my_view(request):
pass
# 只允许 GET 请求访问
@require_GET()
# 只允许 POST 请求访问
@require_POST()
# 只允许安全的请求类型,也就是 GET 和 HEAD 访问
@require_safe()
# 控制特殊视图中的缓存行为,来生成 ETag 和 Last-Modified 头部
@condition(etag_func=None, last_modified_func=None)
# 根据特殊请求头的缓存控制
@vary_on_cookie(func=None)
# 根据特殊请求头的缓存控制,Vary 头定义了缓存机制在构建其缓存密钥时应该考虑哪些请求报头。
@vary_on_headers(*headers)
# 控制服务器及客户端的缓存,通过添加所有关键字参数来修补响应的 Cache-Control 头
@cache_control(**kwargs)
# 控制服务器及客户端的缓存,会为当前日期/时间添加一个 Expires 头部,添加 Cache-Control: max-age=0, no-cache, no-store, must-revalidate 头到一个响应来标识禁止缓存该页面。
@never_cache(view_func)
# 对视图的响应内容进行压缩
@gzip_page()
HttpRequest 对象
def my_view(request):
if request.method == 'GET':
do_something()
elif request.method == 'POST':
do_something_else()
属性:
除非另有说明,否则所有属性都应视为只读。
-
HttpRequest.scheme
字符串类型,表示请求的协议种类,'http'或'https'。
-
HttpRequest.body
bytes 类型,表示原始 HTTP 请求的正文。
-
HttpRequest.path
字符串类型,表示当前请求页面的完整路径,但是不包括协议名和域名。
-
HttpRequest.path_info
在某些 Web 服务器配置下,主机名后的 URL 部分被分成脚本前缀部分和路径信息部分。path_info 属性将始终包含路径信息部分,不论使用的 Web 服务器是什么。
使用它代替 path 可以让代码在测试和开发环境中更容易地切换。 -
HttpRequest.method
字符串类型,表示请求使用的 HTTP 方法。默认为大写。
-
HttpRequest.encoding
字符串类型,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 设置)。
这个属性是可写的,可以通过修改它来改变表单数据的编码。 -
HttpRequest.content_type
表示从 CONTENT_TYPE 头解析的请求的 MIME 类型。
-
HttpRequest.content_params
包含在 CONTENT_TYPE 标题中的键/值参数字典。
-
HttpRequest.GET
一个类似于字典的对象,包含 GET 请求中的所有参数
-
HttpRequest.POST
包含所有 POST 表单数据的键值对字典。
-
HttpRequest.COOKIES
包含所有 Cookie 信息的字典。
-
HttpRequest.FILES
一个类似于字典的对象,包含所有上传的文件数据。
HttpRequest.FILES 中的每个键为
<input type="file" name="" />中的 name 属性值。 HttpRequest.FILES 中的每个值是一个 UploadedFile 对象。 -
HttpRequest.META
包含所有 HTTP 头部信息的字典。 可用的头部信息取决于客户端和服务器
- CONTENT_LENGTH —— 请求正文的长度(以字符串计)。
- CONTENT_TYPE —— 请求正文的 MIME 类型。
- HTTP_ACCEPT —— 可接收的响应 Content-Type。
- HTTP_ACCEPT_ENCODING —— 可接收的响应编码类型。
- HTTP_ACCEPT_LANGUAGE —— 可接收的响应语言种类。
- HTTP_HOST —— 客服端发送的 Host 头部。
- HTTP_REFERER —— Referring 页面。
- HTTP_USER_AGENT —— 客户端的 user-agent 字符串。
- QUERY_STRING —— 查询字符串。
- REMOTE_ADDR —— 客户端的 IP 地址。想要获取客户端的 ip 信息,就在这里!
- REMOTE_HOST —— 客户端的主机名。
- REMOTE_USER —— 服务器认证后的用户,如果可用。
- REQUEST_METHOD —— 表示请求方法的字符串,例如"GET" 或"POST"。
- SERVER_NAME —— 服务器的主机名。
- SERVER_PORT —— 服务器的端口(字符串)。
-
HttpRequest.headers
一个不区分大小写、类似 dict 的对象,包含请求中 HTTP 头部的所有信息。
request.headers['user-agent'] -
HttpRequest.resolver_match
对请求中的 URL 进行解析,获取一些相关的信息,比如 namespace。
中间件带来的属性
-
HttpRequest.session
来自 SessionMiddleware 中间件:一个可读写的,类似字典的对象,表示当前会话。
-
HttpRequest.site
来自 CurrentSiteMiddleware 中间件:get_current_site()方法返回的 Site 或 RequestSite 的实例,代表当前站点是哪个。
Django 是支持多站点的,如果你同时上线了几个站点,就需要为每个站点设置一个站点 id。 -
HttpRequest.user
来自 AuthenticationMiddleware 中间件:表示当前登录的用户的 AUTH_USER_MODEL 的实例,这个模型是 Django 内置的 Auth 模块下的 User 模型。如果用户当前未登录,则 user 将被设置为 AnonymousUser 的实例。
可以使用 is_authenticated 方法判断当前用户是否合法用户if request.user.is_authenticated: pass else: pass
方法
-
HttpRequest.get_host()
获取请求的原始主机
-
HttpRequest.get_port()
返回请求的始发端口
-
HttpRequest.get_full_path()
返回包含完整参数列表的 path。例如:/music/bands/the_beatles/?print=true
-
HttpRequest.build_absolute_uri(location)
返回 location 的绝对 URI 形式。 如果 location 没有提供,则使用 request.get_full_path()的值。
QueryDict
QueryDict 是对 HTTP 请求数据包中携带的数据的封装
HttpRequest.GET 和 HttpRequest.POST 都是一个 django.http.QueryDict 的实例
QueryDict 的键值是可以重复的
q=QueryDict.fromkeys(['a', 'a', 'b'], value='val') # <QueryDict: {'a': ['val', 'val'], 'b': ['val']}>
q=QueryDict('a=1&a=2&c=3') # <QueryDict: {'a': ['1', '2'], 'c': ['3']}>
q.lists() # [('a', ['1', '2', '3'])]
HttpResponse 对象
使用方法
# 返回一个字符串
response = HttpResponse("Text only, please.", content_type="text/plain")
response = HttpResponse()
response.write("<p>Here's the text of the Web page.</p>")
# 设置头部字段
response = HttpResponse()
response['Age'] = 120
# 附件形式
response = HttpResponse(my_data, content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename="foo.xls"'
属性
-
content
响应的内容。bytes 类型。
-
charset
编码的字符集。 如果没指定,将会从 content_type 中解析出来。
-
status_code
响应的状态码,比如 200。
-
reason_phrase
响应的 HTTP 原因短语。 使用标准原因短语。
-
streaming
这个属性的值总是 False。由于这个属性的存在,使得中间件能够区别对待流式响应和常规响应。
-
closed
如果响应已关闭,那么这个属性的值为 True。
JsonResponse 类
JsonResponse 是 HttpResponse 的一个子类,是 Django 提供的用于创建 JSON 编码类型响应的快捷类。
response = JsonResponse({'foo': 'bar'}) # b'{"foo": "bar"}'
若要序列化非 dict 对象,必须设置 safe 参数为 False:
response = JsonResponse([1, 2, 3], safe=False)
StreamingHttpResponse 类
StreamingHttpResponse 类被用来从 Django 响应一个流式对象到浏览器。如果生成的响应太长或者是占用的内存较大,这么做更有效率。 例如,生成大型的 CSV 文件。
StreamingHttpResponse 不是 HttpResponse 的子类(而是兄弟类)
FileResponse
文件类型响应。通常用于给浏览器返回一个文件附件。
FileResponse 是 StreamingHttpResponse 的子类,为二进制文件专门做了优化。
FileResponse 需要通过二进制模式打开文件,文件会被自动关闭,所以不需要在上下文管理器中打开
response = FileResponse(open('myfile.png', 'rb'))
如果 as_attachment=True,则 Content-Disposition 被设置为 attachment,,告诉浏览器这是一个附件,以文件形式下载。否则 Content-Disposition 会被设置为 inline (浏览器默认行为)。
response = FileResponse(open('myfile.png', 'rb'),as_attachment=True,filename='a.png')
文件上传
当 Django 处理文件上传时,文件数据最终会被放置在 request.FILES。
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm
def handle_uploaded_file(f):
with open("some/file/name.txt", "wb+") as destination:
for chunk in f.chunks():
destination.write(chunk)
def upload_file(request):
if request.method == "POST":
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES["file"])
return HttpResponseRedirect("/success/url/")
else:
form = UploadFileForm()
return render(request, "upload.html", {"form": form})
基于类的视图
from django.urls import path
from django.views.generic import TemplateView
urlpatterns = [
path("about/", TemplateView.as_view(template_name="about.html")),
]
# 或者
class AboutView(TemplateView):
template_name = "about.html"
urlpatterns = [
path("about/", AboutView.as_view()),
]
使用通用视图
from django.views.generic import ListView
from books.models import Publisher
class PublisherListView(ListView):
# model = Publisher # 等同于 queryset = Publisher.objects.all()
queryset = Publisher.objects.order_by("-create_date")
context_object_name = "favorite_publishers"
template_name = "publishers.html"
动态过滤
# urls.py
from django.urls import path
from books.views import PublisherBookListView
urlpatterns = [
path("books/<publisher>/", PublisherBookListView.as_view()),
]
# views.py
from django.shortcuts import get_object_or_404
from django.views.generic import ListView
from books.models import Book, Publisher
class PublisherBookListView(ListView):
template_name = "books/books_by_publisher.html"
def get_queryset(self):
self.publisher = get_object_or_404(Publisher, name=self.kwargs["publisher"])
return Book.objects.filter(publisher=self.publisher)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["publisher"] = self.publisher
return context
模板
变量
{{ variable }}
过滤器
-
default
为 false 或者空变量提供默认值
{{ value|default:"nothing" }}default_if_none
如果(且仅当)value 为 None,则使用给定的默认值。{{ value|default_if_none:"nothing" }} -
length
返回值的长度。它对字符串和列表都起作用。
{{ value|length }} -
filesizeformat
格式化为'人类可读'文件大小单位(即'13 KB',4.1 MB','102 bytes'等)。
{{ value|filesizeformat }} -
add
把 add 后的参数加给 value。
{{ value|add:"2" }} # 4->6 {{ first|add:second }} # first=[1, 2, 3],second=[4, 5, 6], 将会输出[1, 2, 3, 4, 5, 6]. -
addslashes
在引号前面加上斜杆。
{{ value|addslashes }} -
capfirst
大写变量的第一个字母。 如果第一个字符不是字母,该过滤器将不会生效。
{{ value|capfirst }} -
lower
将字符串转换为全部小写。
{{ value|lower }} -
title
将所有单词的首字母大写,其它字母小写。
{{ value|title }} -
upper
将字符串转换为全部大写的形式:
{{ value|upper }} -
center
在给定的宽度范围内居中.
{{ value|center:"15" }} -
ljust
给定宽度下左对齐。
{{ value|ljust:"10" }} -
rjust
右对齐给定宽度字段中的值。
{{ value|rjust:"10" }} -
cut
移除 value 中所有的与给定参数相同的字符串。
{{ value|cut:" " }} -
date
根据给定格式对一个日期变量进行格式化。
{{ value|date:"D d M Y" }} {{ value|time:"H:i" }} -
time
根据给定的格式,格式化时间。
{{ value|time:"H:i" }} -
timesince
将日期格式设为自该日期起的时间(例如:4 天)。
{{ blog_date|timesince:comment_date }} -
timeuntil
类似于 timesince,它测量从现在开始直到给定日期或日期时间的时间。
{{ conference_date|timeuntil:from_date }} -
make_list
将对象转换为字符的列表。对于字符串,直接拆分为单个字符的列表。对于整数,在创建列表之前将参数强制转换为 unicode 字符串。
{{ value|make_list }}如果 value 是字符串"Joel",输出将是列表['J', 'o' , 'e', 'l']。
如果 value 为 123,输出为列表['1', '2', '3']。 -
dictsort
接受一个包含字典元素的列表,并返回按参数中给出的键排序后的列表。
{{ value|dictsort:"name" }} # dictsort 也可以按指定索引对多维列表进行排序 {% for book in books|dictsort:"author.age" %} {{ book.title }} ({{ book.author.name }}) {% endfor %} {{ value|dictsort:0 }} -
dictsortreversed
dictsort 的反序功能。
-
divisibleby
如果 value 可以被参数整除,则返回 True。
{{ value|divisibleby:"3" }} -
escape
转义字符串的 HTML。
-
escapejs
转义用于 JavaScript 字符串的字符。确保在使用模板生成 JavaScript/JSON 时避免语法错误。
{{ value|escapejs }} -
first
返回列表中的第一项。
{{ value|first }}如果 value 是列表['a', 'b', 'c'] ,输出将为'a'。
-
last
返回列表中的最后一个项目。类似 first 过滤器。
{{ value|last }} -
random
返回给定列表中的随机项。
{{ value|random }} -
floatformat
当不使用参数时,将浮点数舍入到小数点后一位,但前提是要显示小数部分。
{{ value | floatformat }}- 34.23234 -> 34.2
- 34.00000 -> 34
- 34.26000 -> 34.3
如果与数字整数参数一起使用,将数字四舍五入为小数位数。
{{ value | floatformat:3 }}- 34.23234 -> 34.232
- 34.00000 -> 34.000
- 34.26000 -> 34.260
传递 0 作为参数,它将使 float 浮动到最接近的整数。
{{ value | floatformat:"0" }}- 34.23234 -> 34
- 34.00000 -> 34
- 39.56000 -> 40
传递给 floatformat 的参数为负,则会将一个数字四舍五入到小数点后的位置
{{ value | floatformat:"-3" }}- 34.23234 -> 34.232
- 34.00000 -> 34
- 34.26000 -> 34.260
-
get_digit
给定一个整数,返回所请求的数字,1 表示最右边的数字,2 表示第二个最右边的数字,以此类推。
{{ value|get_digit:"2" }}如果 value 为 123456789,则输出 8。
-
iriencode
将 IRI(国际化资源标识符)转换为适合包含在 URL 中的字符串。
{{ value|iriencode }}如果 value 是?test=1&me=2,输出则是?test=1&me=2。
-
urlencode
转义要在 URL 中使用的值。
{{ value|urlencode }} -
join
使用字符串连接列表,类似 Python 的 str.join(list)
{{ value|join:" // " }}如果 value 是列表['a', 'b', 'c'] ,输出为 a // b // c。
-
pluralize
如果值不是 1,则返回一个复数形式,通常在后面添加's'表示。
message
{{ num_messages|pluralize }}cherr
{{ num_cherries|pluralize:"y,ies" }} -
linebreaks
替换纯文本中的换行符为
标签。
{{ value|linebreaks }}如果 value 是 Joel\nis a slug,输出将为
Joel
。
is a slug -
linebreaksbr
替换纯文本中的换行符为
标签。{{ value|linebreaksbr }}如果 value 是 Joel\nis a slug,输出将为 Joel
is a slug。 -
linenumbers
显示带行号的文本。
{{ value|linenumbers }} -
safe
将字符串标记为安全,不需要转义。
-
safeseq
将 safe 过滤器应用于序列的每个元素。 与对序列进行其他过滤操作(例如 join)一起使用时非常有用。
{{ some_list|safeseq|join:", " }} -
slice
返回列表的一部分。也就是切片,与 Python 的列表切片相同的语法。
{{ some_list|slice:":2" }}# 如果 some_list 是['a', 'b', 'c'] ,输出将为['a', 'b']。 -
slugify
转换为 ASCII。空格转换为连字符。删除不是字母数字,下划线或连字符的字符。转换为小写。还会去除前导和尾随空格。
{{ value|slugify }}如果 value 是 Joel is a slug,输出为 joel-is-a-slug。
-
stringformat
根据参数,格式化变量。
{{ value|stringformat:"E" }}如果 value 为 10,输出将为 1.000000E+01。
-
striptags
尽可能的去除 HTML 中的标签。
{{ value|striptags }} -
truncatechars
如果字符串包含的字符总个数多于指定的字符数量,那么会被截断掉后面的部分。截断的字符串将以“...”结尾。
{{ value|truncatechars:9 }} -
truncatechars_html
类似于 truncatechars,但是会保留 HTML 标记。
{{ value|truncatechars_html:9 }} -
truncatewords
在一定数量的字数后截断字符串。与 truncatechars 不同的是,这个以字的个数计数,而不是字符计数。
{{ value|truncatewords:2 }} -
truncatewords_html
类似于 truncatewords,但是保留 HTML 标记。
{{ value|truncatewords_html:2 }} -
urlize
将文字中的网址和电子邮件地址转换为可点击的链接。
{{ value|urlize }} -
urlizetrunc
将网址和电子邮件地址转换为可点击的链接,就像 urlize,但截断长度超过给定字符数限制的网址。
{{ value|urlizetrunc:15 }} -
wordcount
返回单词的个数。
{{ value|wordcount }} -
wordwrap
以指定的行长度,换行单词。
{{ value|wordwrap:5 }} -
yesno
将 True,False 和 None,映射成字符串‘yes’,‘no’,‘maybe’。
{{ value|yesno:"yeah,no,maybe" }}也可以自定义返回的字符串,比如:
{{ value|yesno:"man,woman,ladyboy" }}
标签
-
for 循环标签
{% for athlete in athlete_list %} <li>{{ athlete.name }}</li> {% endfor %} {% for athlete in athlete_list reversed %} <li>{{ athlete.name }}</li> <li>{{ forloop.counter }}</li> # 循环的当前索引值,从 1 开始计数; <li>{{ forloop.counter0 }}</li> # 循环的当前索引值,从 0 开始计数; <li>{{ forloop.revcounter }}</li> #循环结束的次数(从 1 开始) <li>{{ forloop.revcounter0 }}</li> #循环结束的次数(从 0 开始) <li>{{ forloop.first }}</li> # 判断当前是否循环的第一次 <li>{{ forloop.last }}</li> # 判断当前是否循环的最后一次 <li>{{ forloop.parentloop }}</li> #对于嵌套循环,返回父循环所在的循环次数。 {% endfor %} {% for athlete in athlete_list %} <li>{{ athlete.name }}</li> {% empty %} <li>Sorry, no athletes in this list.</li> {% endfor %} -
if,elif 和 else 标签
{% if athlete_list %} Number of athletes: {{ athlete_list|length }} {% elif athlete_in_locker_room_list %} Athletes should be out of the locker room soon! {% else %} No athletes. {% endif %} -
csrf_token
{% csrf_token %} -
cycle
{% for o in some_list %} <tr class="{% cycle 'row1' 'row2'%}"> ... </tr> {% endfor %} ''' <tr> <td class="row1">...</td> <td class="row1">...</td> </tr> <tr> <td class="row2">...</td> <td class="row2">...</td> </tr> ''' -
block
block 标签可以被子模板覆盖。
-
extends
表示当前模板继承自一个父模板。
-
filter
通过一个或多个过滤器对内容过滤。需要结束标签 endfilter。
{% filter force_escape|lower %} This text will be HTML-escaped, and will appear in all lowercase. {% endfilter %} -
firstof
输出第一个不为 False 参数。 如果传入的所有变量都为 False,就什么也不输出。
{% firstof var1 var2 var3 %}
-
ifchanged
检查一个值是否在上一次的迭代中被改变了
{% ifchanged %}标签通常用在循环里。它有两个用处:检查已经渲染过的内容的当前状态。并且只会显示发生改变的内容。{% for match in matches %} <div style="background-color: {% ifchanged match.ballot_id %} {% cycle "red" "blue" %} {% else %} gray {% endifchanged %} ">{{ match }}</div> {% endfor %} -
include
加载指定的模板并以标签内的参数渲染
{% include "foo/bar.html" %} {% include "name_snippet.html" with person="Jane" greeting="Hello" %} {% include "name_snippet.html" with greeting="Hi" only %} -
load
加载自定义模板标签。
{% load foo bar from somelibrary %} -
lorem
这个标签是用来在模版中提供文字样本以供测试用的。
{% lorem %} # 将输出常见的“lorem ipsum”段落。 {% lorem 3 p %} # 输出常用的“lorem ipsum”段落和两个随机段落,每段包裹在 HTML`<p>`标签中。 {% lorem 2 w random %} # 将输出两个随机拉丁字。 -
regroup
用对象间共有的属性重组列表。
cities = [ {'name': 'Mumbai', 'population': '19,000,000', 'country': 'India'}, {'name': 'Calcutta', 'population': '15,000,000', 'country': 'India'}, {'name': 'New York', 'population': '20,000,000', 'country': 'USA'}, {'name': 'Chicago', 'population': '7,000,000', 'country': 'USA'}, {'name': 'Tokyo', 'population': '33,000,000', 'country': 'Japan'}, ] {% regroup cities by country as country_list %} <ul> {% for country in country_list %} <li>{{ country.grouper }} <ul> {% for city in country.list %} <li>{{ city.name }}: {{ city.population }}</li> {% endfor %} </ul> </li> {% endfor %} </ul> ''' India Mumbai: 19,000,000 Calcutta: 15,000,000 USA New York: 20,000,000 Chicago: 7,000,000 Japan Tokyo: 33,000,000 ''' -
resetcycle
重置先前的循环,以便在下一次循环时从其第一个项目重新启动。
如果没有参数,{% resetcycle %}将重置最后一个{% cycle %}。{% for coach in coach_list %} <h1>{{ coach.name }}</h1> {% for athlete in coach.athlete_set.all %} <p class="{% cycle 'odd' 'even' %}">{{ athlete.name }}</p> {% endfor %} {% resetcycle %} {% endfor %} ''' <h1>José Mourinho</h1> <p class="odd">Thibaut Courtois</p> <p class="even">John Terry</p> <p class="odd">Eden Hazard</p> <h1>Carlo Ancelotti</h1> <p class="odd">Manuel Neuer</p> <p class="even">Thomas Müller</p> ''' {% for item in list %} <p class="{% cycle 'odd' 'even' as stripe %} {% cycle 'major' 'minor' 'minor' 'minor' 'minor' as tick %}"> {{ item.data }} </p> {% ifchanged item.category %} <h1>{{ item.category }}</h1> {% if not forloop.first %}{% resetcycle tick %}{% endif %} {% endifchanged %} {% endfor %}在这个例子中,我们有交替的奇数/偶数行和每五行出现一次的'major'行。当类别更改时,只有五行周期被重置。 -
spaceless
删除 HTML 标签之间的空白,包括制表符和换行。仅会删除 tags 之间的空格,不会删除标签和文本之间的。
{% spaceless %} <p> <a href="foo/">Foo</a> </p> {% endspaceless %} # <p><a href="foo/">Foo</a></p> -
with
使用一个简单地名字缓存一个复杂的变量,当你需要使用一个代价较大的方法(比如访问数据库)很多次的时候这是非常有用的。
{% with total=business.employees.count %} {{ total }} employee{{ total|pluralize }} {% endwith %} #可以分配多个变量: {% with alpha=1 beta=2 %} ... {% endwith %} -
url
返回与给定视图和可选参数匹配的绝对路径引用(不带域名的 URL)
{% url 'some-url-name' arg1=v1 arg2=v2 %}{% url 'some-url-name' v1 v2 %} -
now
显示当前的日期或时间。可以指定显示的格式。
{% now "jS F Y H:i" %}
注释
{# greeting #}hello # hello
{% comment "Optional note" %}
<p>Commented out text with {{ create_date|date:"c" }}</p>
{% endcomment %}
模板继承
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css" />
<title>{% block title %}My amazing site{% endblock %}</title>
</head>
<body>
<div id="sidebar">
{% block sidebar %}
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
{% endblock %}
</div>
<div id="content">{% block content %}{% endblock %}</div>
</body>
</html>
blog_index.html
{% extends "base.html" %}
{% block title %}My amazing blog{% endblock %}
{% block content %}
{% for entry in blog_entries %}
<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}
自动转义
-
单个变量
{{ data }}自动转义后输出到页面上
{{ data|safe }}关闭变量上的自动转义
-
模板块
{% autoescape off %} Hello {{ name }} {% endautoescape %}
表单
Django 会处理涉及表单的三个不同部分:
- 准备并重组数据,以便下一步的渲染
- 为数据创建 HTML 表单
- 接收并处理客户端提交的表单及数据
Django 的 Form 类
Django 表单系统的核心组件是 Form 类。它与 Django 模型描述对象的逻辑结构、行为以及它呈现给我们内容的形式的方式大致相同, Form 类描述一张表单并决定它如何工作及呈现。
类似于模型类的字段映射到数据库字段的方式,表单类的字段会映射到 HTML 表单的 <input> 元素。 ModelForm 通过 Form 映射模型类的字段到 HTML 表单的 <input> 元素,Django admin 就基于此。
表单字段本身也是类;他们管理表单数据并在提交表单时执行验证。
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label="Your name", max_length=100)
字段的最大长度由 max_length 来定义。它做了两件事情。首先它在 HTML 的 <input> 上增加了 maxlength="100" 。其次它还会在 Django 收到浏览器传过来的表单时,对数据长度进行验证(也就是服务器端验证)。
<label for="your_name">Your name: </label> <input id="your_name" type="text" name="your_name" maxlength="100" required />
视图
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import NameForm
def get_name(request):
if request.method == "POST":
form = NameForm(request.POST) # 绑定数据到表单
if form.is_valid():
data=form.cleaned_data() # 通过验证的表单数据
pass
return HttpResponseRedirect("/thanks/")
else:
form = NameForm()
return render(request, "name.html", {"form": form})
模板
<form action="/your-name/" method="post">
{% csrf_token %} {{ form }}
<input type="submit" value="Submit" />
</form>
所有的表单字段及其属性都将通过 Django 模板语言从 {{ form }} 中被解包成 HTML 标记。
内置 Field 类
-
BooleanField
空值:False,如果字段有 required=True,则验证该值是否为 True
-
CharField
字符串
具有以下可选的验证参数:
-
max_length
-
min_length
-
strip
如果 True (默认),该值将被去掉前导和尾部的空白。
-
empty_value
用来表示“空”的值。默认为空字符串。
-
-
DateField
可选的参数:
- input_formats
-
DateTimeField
可选的参数:
- input_formats
-
TimeField
可选的参数:
- input_formats
-
IntegerField
可选参数:
- max_value
- min_value
- step_size
-
DecimalField
可选参数:
-
max_value
-
min_value
-
max_digits
值中允许的最大位数(小数点前的数字加上小数点后的数字,去掉前导零)。
-
decimal_places
允许的最大小数位数。
-
step_size
限制有效输入为 step_size 的整数倍。如果还提供了 min_value,则将其添加为偏移量以确定步长是否匹配。
-
-
FloatField
可选参数:
- max_value
- min_value
- step_size
-
DurationField
-
EmailField
-
URLField
-
UUIDField
接受作为 UUID 构造函数的 hex 参数的任何字符串格式。
-
FileField
可选的验证参数:
-
max_length
文件名的长度
-
allow_empty_file
文件内容可为空
-
-
ImageField
在字段被清理和验证后,UploadedFile 对象将具有一个额外的 image 属性,其中包含 Pillow 的 Image 实例,用于检查文件是否为有效的图像。Pillow 在验证图像后关闭底层文件描述符,因此虽然可以访问非图像数据属性,如 format、height 和 width,但不能在不重新打开文件的情况下使用访问底层图像数据的方法,比如 getdata() 或 getpixel()。
-
FilePathField
额外的参数;只有 path 是必须的。
-
path
你想要列出的内容的目录的绝对路径。该目录必须存在。
-
recursive
如果 False (默认),只提供 path 的直接内容作为选择。如果 True,目录将被递归递进,所有的子目录将被列为选择。
-
match
正则表达式模式;只允许将名称与此表达式相匹配的文件作为选择。
-
allow_files
可选。 可选 True 或 False。 默认值是 True。 指定是否应该包含指定位置的文件。 此项或 allow_folders 必须为 True。
-
allow_folders
可选。 可选 True 或 False。 默认为 False。 指定是否应包括指定位置的文件夹。 此项或 allow_files 必须为 True。
-
-
GenericIPAddressField
可选的参数:
-
protocol
将有效输入限制为指定协议。接受的值是 both (默认)、IPv4 或 IPv6。匹配是不区分大小写的。
-
-
SlugField
可选的参数:
-
allow_unicode
一个布尔值,指示该字段除了接受 ASCII 字母外,还接受 Unicode 字母。默认值为 False。
-
empty_value
用来表示“空”的值。默认为空字符串。
-
-
ChoiceField
额外的参数:
-
choices
此参数接受与模型字段的 choices 参数相同的格式。
-
-
JSONField
-
MultipleChoiceField
-
NullBooleanField
-
RegexField
核心字段参数
-
required
默认情况下,每个 Field 类都假定该值是必需的,因此如果传递一个空值 -- 无论是 None 还是空字符串("")-- 那么 clean() 将引发一个 ValidationError 异常:
-
label
指定该字段的“人类友好”标签
-
label_suffix
覆盖表单的 label_suffix
-
initial
指定在未绑定的 Form 中渲染这个 Field 时要使用的初始值
-
widget
指定一个 Widget 类,以便在渲染这个 Field 时使用。
-
help_text
指定描述性文本
-
error_messages
覆盖字段将引发的默认错误消息
-
validators
提供一个验证函数列表
-
localize
本地化
-
disabled
disabled 布尔参数设置为 True 时,使用 disabled HTML 属性禁用表单字段,使其不能被用户编辑。即使用户篡改了提交给服务器的字段值,也会被忽略,而采用表单初始数据的值。
验证器
自定义验证器
def validate_gte_18(value):
if value < 18:
raise ValidationError({'age': '年龄小于 18 岁'})
指定验证器
class MyModel(models.Model):
age = models.IntegerField(validators=[validate_gte_18])
class MyForm(forms.Form):
age = forms.IntegerField(validators=[validate_gte_18])
模型的验证器不会在调用 save()方法的时候自动执行
表单的验证器会在调用 save()方法的时候自动执行
from django.core.exceptions import ValidationError
try:
article.full_clean()
except ValidationError as e:
print(e.message_dict)
内置验证器
- RegexValidator
- EmailValidator
- URLValidator
- validate_email
- validate_slug
- validate_unicode_slug
- validate_ipv4_address
- validate_ipv6_address
- validate_ipv46_address
- validate_comma_separated_integer_list
- int_list_validator
- MaxValueValidator
- MinValueValidator
- MaxLengthValidator
- MinLengthValidator
- DecimalValidator
- FileExtensionValidator
- validate_image_file_extension
Django 管理站点
Django 最强大的部分之一是自动管理界面。它从你的模型中读取元数据,提供一个快速的、以模型为中心的界面,受信任的用户可以管理你网站上的内容。管理的推荐使用范围仅限于一个组织的内部管理工具。它不打算用于围绕你的整个前端构建。
ModelAdmin
ModelAdmin 类是管理界面中模型的表示。通常,这些都存储在你的应用程序中一个名为 admin.py 的文件中。
from django.contrib import admin
from myapp.models import Author
class AuthorAdmin(admin.ModelAdmin):
pass
admin.site.register(Author, AuthorAdmin)
register 装饰器
用于注册你的 ModelAdmin 类
from django.contrib import admin
from .models import Author
@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
pass
ModelAdmin 选项
-
list_display
指定哪些字段显示在管理的变更列表页面
class PersonAdmin(admin.ModelAdmin): list_display = ["upper_case_name",'Age'] @admin.display(description="Name") def upper_case_name(self, obj): return f"{obj.first_name} {obj.last_name}".upper() -
list_display_links
控制 list_display 中的字段是否以及哪些字段应该被链接到对象的 “更改” 页面。
-
list_editable
设置为模型上允许在更改列表页上编辑的字段名称列表。也就是说,在 list_editable 中列出的字段将作为表单部件显示在变更列表页上,允许用户一次编辑和保存多行。
list_editable 中的任何字段都必须在 list_display 中。
同一字段不能同时列在 list_editable 和 list_display_links 中 。 -
list_filter
设置 list_filter 以在管理员的更改列表页面右侧边栏上激活过滤器。
在最简单的情况下,list_filter 接受一个字段名称的列表或元组以激活过滤 -
list_max_show_all
控制 “全部显示” 的管理员更改列表页面上可以出现多少个项目。只有当总结果数小于或等于此配置时,管理才会在更改列表中显示 “全部显示” 链接。默认情况下,这个配置为 200。
-
list_per_page
控制每个分页的管理变更列表页面上出现多少个项目。默认情况下,设置为 100。
-
list_select_related
告诉 Django 在检索管理变更列表页的对象列表时使用 select_related()。这样可以省去一堆数据库查询。
该值应是布尔值、列表或元组。默认值是 False。 -
ordering
指定对象列表在 Django 管理视图中的排序方式。
-
search_fields
设置 search_fields,在管理更改列表页面上启用搜索框。这应该被设置为字段名的列表,每当有人在该文本框中提交搜索查询时,就会被搜索到。
-
search_help_text
设置 search_help_text,为搜索框指定一个描述性文本,显示在它的下面。
-
sortable_by
默认情况下,变更列表页面允许按 list_display 中指定的所有模型字段进行排序。
-
actions
指定要在变更列表页上提供的动作列表。
-
date_hierarchy
将 date_hierarchy 设置为你的模型中 DateField 或 DateTimeField 的名称,变化列表页将包括一个基于日期的向下扩展。
date_hierarchy = "pub_date" -
empty_value_display
指定覆盖记录字段为空(None、空字符串等)的默认显示值。默认值是 - (破折号)。
-
exclude
指定要从表单中排除的字段名列表。
-
fields
使用 fields 选项在 “添加” 和 “更改” 页面的表单中进行简单的布局修改,比如只显示可用字段的子集,修改它们的顺序,或者将它们分成几行。
fields = [("url", "title"), "content"]
url 和 title 字段将显示在同一行,content 字段将显示在它们下面的一行
如果 fields 或 fieldsets 选项都不存在,Django 将默认在一个单一的字段集中显示每个非 AutoField 且有 editable=True 的字段,顺序与模型中定义的字段相同。 -
fieldsets
设置 fieldsets 来控制管理员 “添加” 和 “更改” 页面的布局。
fieldsets 是一个包含多个 2-元组的列表,每个 2-元组表示管理员表单页面上的一个<fieldset>
这些 2-元组的格式是 (name, field_options),其中 name 是表示 fieldset 标题的字符串,而 field_options 是关于 fieldset 的信息的字典,包括要在其中显示的字段列表。 -
filter_horizontal
显示一个可搜索的
<select multiple>的 ManyToManyField。未选择和选择的选项并排出现在两个框中。 -
filter_vertical
与 filter_horizontal 相同,但使用垂直显示过滤界面,未选择的选项框出现在选择选项框的上方。
-
form
指定自定义的 ModelForm
-
formfield_overrides
覆盖一些 Field 选项
from django.contrib import admin from django.db import models from myapp.models import MyModel from myapp.widgets import RichTextEditorWidget class MyModelAdmin(admin.ModelAdmin): formfield_overrides = { models.TextField: {"widget": RichTextEditorWidget}, } -
inlines
-
preserve_filters
默认情况下,在创建、编辑或删除对象后,应用的过滤器会被保存在列表视图中。您可以通过将此属性设置为 False 来清除过滤器。
-
radio_fields
默认情况下,Django 的管理对于 ForeignKey 或设置了 choices 的字段使用选择框界面(
<select>)。如果字段存在于 radio_fields 中,Django 将使用单选按钮接口代替。 -
autocomplete_fields
自动完成输入
-
raw_id_fields
默认情况下,Django 的管理员对 ForeignKey 的字段使用选择框接口(
<select>)。
raw_id_fields 是你想改变为 ForeignKey 或 ManyToManyField 的 Input 部件的字段列表。
raw_id_fields 部件在字段旁边显示一个放大镜按钮,允许用户搜索和选择一个值。 -
readonly_fields
该选项中的任何字段将按原样显示其数据,不可编辑
-
save_as
设置 save_as,在管理更改表格时启用 “另存为新” 功能。
-
save_as_continue
当 save_as=True 时,保存新对象后默认重定向到该对象的变更视图。如果设置 save_as_continue=False,则重定向到变更列表视图。
默认情况下,save_as_continue 被设置为 True。 -
save_on_top
设置 save_on_top 来在你的管理更改表格的顶部添加保存按钮。
通常情况下,保存按钮只出现在表格的底部。如果设置 save_on_top,按钮将同时出现在顶部和底部。
默认情况下,save_on_top 被设置为 False。
浙公网安备 33010602011771号