创建项目
完成Django安装后可以创建一个项目
使用Django命令行创建项目
django-admin startproject [项目名]
例如创建名为mysite的项目,创建后的目录内容如下
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
这些目录和文件的用处是:
- 最外层的
mysite/
根目录只是你项目的容器, 根目录名称对Django没有影响,你可以将它重命名为任何你喜欢的名称。 -
manage.py
: 一个让你用各种方式管理 Django 项目的命令行工具。 - 里面一层的
mysite/
目录包含你的项目,它是一个纯 Python 包。它的名字就是当你引用它内部任何东西时需要用到的 Python 包名。 (比如mysite.urls
). -
mysite/__init__.py
:一个空文件,告诉 Python 这个目录应该被认为是一个 Python 包。 -
mysite/settings.py
:Django 项目的配置文件。 -
mysite/urls.py
:Django 项目的 URL 声明,就像你网站的“目录”。 -
mysite/asgi.py
:作为你的项目的运行在 ASGI 兼容的Web服务器上的入口。 -
mysite/wsgi.py
:作为你的项目的运行在 WSGI 兼容的Web服务器上的入口。
使用pycharm创建项目
菜单File -> New Project -> Django 创建项目并配置项目参数。
Location : 填项目路径和名字
Project Interpreter : 应该选择Existing interpreter,选择一个已安装和配置好的python,不要选择New envirnment using,这个可能不能正常使用。
-
More Settings : 这里创建Django项目其他可选内容
Template language 选择 Django
Template folder : 需要创建模板目录的话填写一个Template目录名字。
Application name : 需要创建App的话填写一个App名。
以下是使用pycharm创建一个名为untitled的项目的目录结构
untitled\.idea\inspectionProfiles\profiles_settings.xml
untitled\.idea\misc.xml
untitled\.idea\modules.xml
untitled\.idea\untitled.iml
untitled\.idea\workspace.xml
untitled\manage.py
untitled\untitled\asgi.py
untitled\untitled\settings.py
untitled\untitled\urls.py
untitled\untitled\wsgi.py
untitled\untitled\__init__.py
untitled\untitled\__pycache__\settings.cpython-39.pyc
untitled\untitled\__pycache__\__init__.cpython-39.pyc
untitled\templates\
untitled\webApp\admin.py
untitled\webApp\apps.py
untitled\webApp\migrations\__init__.py
untitled\webApp\models.py
untitled\webApp\tests.py
untitled\webApp\views.py
untitled\webApp\__init__.py
试运行项目
在命令行下可以使用以下命令来运行项目
py manage.py runserver
py manage.py runserver 8080
py manage.py runserver 0:8000
创建应用App
我们将在 manage.py 同级目录下创建应用。这样它就可以作为顶级模块导入,而不是 mysite 的子模块。
现在创建一个名字为polls的应用
py manage.py startapp polls
创建后会自动生成以下文件
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
通过pycharm创建应用,Tools -> Run manage.py Task , 会在窗口出现一个命令提示,输入 startapp polls。
在应用里创建一个视图内容
polls/views.py
from django.http import HttpResponse # 导入HttpResponse,用来生成响应信息
# 新增视图函数index
def index(request): # request信息必须有,封装用户请求的消息
return HttpResponse("Hello, world. You're at the polls index.")
#按django规则,需要通过HttpResponse来封装反回消息,不能直接回复字符串。
要看到这个视图还需要配置URL,建议在独立应用中建立URLconf文件urls.py,这样保持每个应用的独立,在项目URLconf中include()这个urls.py文件就可以。
创建一个polls/urls.py文件作为应用的URLconf
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
在项目mysite/urls.py中添加以下内容
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]
配置数据库
数据库由项目配置文件settings.py进行设备,这个配置文件使用 SQLite 作为默认数据库。Python 内置 SQLite,所以你无需安装额外东西来使用它。当你开始一个真正的项目时,你可能更倾向使用一个更具扩展性的数据库,例如 PostgreSQL,避免中途切换数据库这个令人头疼的问题。
DATABASES字段配置
ENGINE : 可选值有 'django.db.backends.sqlite3','django.db.backends.postgresql','django.db.backends.mysql',或 'django.db.backends.oracle'。
NAME : 数据库的名称。如果使用的是 SQLite,数据库将是你电脑上的一个文件,在这种情况下, NAME 应该是此文件的绝对路径,包括文件名。
如果你不使用 SQLite,则必须添加一些额外设置,比如 USER 、 PASSWORD 、 HOST 等等。
-
SQLite 以外的其它数据库
如果你使用了 SQLite 以外的数据库,请确认在使用前已经创建了数据库。你可以通过在你的数据库交互式命令行中使用 "CREATE DATABASE database_name;" 命令来完成这件事。
另外,还要确保该数据库用户中提供 mysite/settings.py 具有 "create database" 权限。这使得自动创建的 test database 能被以后的教程使用。
如果你使用 SQLite,那么你不需要在使用前做任何事——数据库会在需要的时候自动创建。
使用postgresql配置举例
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'mydatabaseuser',
'PASSWORD': 'mypassword',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
检查数据库配置
默认开启的某些应用需要至少一个数据表,所以,在使用他们之前需要在数据库中创建一些表。请执行以下命令
py manage.py migrate # 创建表结构,在数据模型进行修改后,通过makemigrations创建migrations,再用这个命令配置数据库
这个 migrate 命令检查 INSTALLED_APPS 设置,为其中的每个应用创建需要的数据表,至于具体会创建什么,这取决于你的 mysite/settings.py 设置文件和每个应用的数据库迁移文件(我们稍后会介绍这个)。这个命令所执行的每个迁移操作都会在终端中显示出来。如果你感兴趣的话,运行你数据库的命令行工具,并输入 \dt (PostgreSQL), SHOW TABLES; (MariaDB,MySQL), .schema (SQLite)或者 SELECT TABLE_NAME FROM USER_TABLES; (Oracle) 来看看 Django 到底创建了哪些表。
创建数据库模型
在 Django 里写一个数据库驱动的 Web 应用的第一步是定义模型 - 也就是数据库结构设计和附加的其它元数据。
polls/models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
每个模型被表示为 django.db.models.Model 类的子类。每个模型有许多类变量,它们都表示模型里的一个数据库字段。
每个字段都是 Field 类的实例 - 比如,字符字段被表示为 CharField ,日期时间字段被表示为 DateTimeField 。这将告诉 Django 每个字段要处理的数据类型。
每个 Field 类实例变量的名字(例如 question_text 或 pub_date )也是字段名,所以最好使用对机器友好的格式。你将会在 Python 代码里使用它们,而数据库会将它们作为列名。
你可以使用可选的选项来为 Field 定义一个人类可读的名字。这个功能在很多 Django 内部组成部分中都被使用了,而且作为文档的一部分。如果某个字段没有提供此名称,Django 将会使用对机器友好的名称,也就是变量名。在上面的例子中,我们只为 Question.pub_date 定义了对人类友好的名字。对于模型内的其它字段,它们的机器友好名也会被作为人类友好名使用。
定义某些 Field 类实例需要参数。例如 CharField 需要一个 max_length 参数。这个参数的用处不止于用来定义数据库结构,也用于验证数据,我们稍后将会看到这方面的内容。
Field 也能够接收多个可选参数;在上面的例子中:我们将 votes 的 default 也就是默认值,设为0。
注意在最后,我们使用 ForeignKey 定义了一个关系。这将告诉 Django,每个 Choice 对象都关联到一个 Question 对象。Django 支持所有常用的数据库关系:多对一、多对多和一对一。
激活模型
Django 应用是“可插拔”的。你可以在多个项目中使用同一个应用。除此之外,你还可以发布自己的应用,因为它们并不会被绑定到当前安装的 Django 上。
通过项目配置文件mysite/settings.py包含已创建的应用。
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
运行makemigrations命令Django 会检测你对模型文件的修改(在这种情况下,你已经取得了新的),并且把修改的部分储存为一次迁移。
py manage.py makemigrations polls # 让 Django 知道我们在我们的模型有一些变更
#你将会看到类似于下面这样的输出:
Migrations for 'polls':
polls/migrations/0001_initial.py
- Create model Question
- Create model Choice
迁移是 Django 对于模型定义(也就是你的数据库结构)的变化的储存形式 - 它们其实也只是一些你磁盘上的文件。如果你想的话,你可以阅读一下你模型的迁移数据,它被储存在 polls/migrations/0001_initial.py 里。别担心,你不需要每次都阅读迁移文件,但是它们被设计成人类可读的形式,这是为了便于你手动调整Django的修改方式。
Django 有一个自动执行数据库迁移并同步管理你的数据库结构的命令 - 这个命令是 migrate,我们马上就会接触它 - 但是首先,让我们看看迁移命令会执行哪些 SQL 语句。sqlmigrate 命令接收一个迁移的名称,然后返回对应的 SQL:
py manage.py sqlmigrate polls 0001
项目配置
创建管理员
需要先通过python manage.py migrate 创建数据库
再通过 python manage.py createsuperuser 创建管理用户
settings.py配置文件
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
#项目根目录
SECRET_KEY = '=#%d!j*=13+q%码赛克hwhnspp_@-&m$#=oj0-'
#项目安全码
#SECRET_KEY是在startproject时候生成的,最终引用的是上述代码,具体的你可以自己去源码查看。
DEBUG = False
#不要在实际生产中打开debug
ALLOWED_HOSTS = ['localhost', '127.0.0.1', '[::1]','www.example.com']
#ALLOWED_HOSTS列表为了防止黑客入侵,只允许列表中的ip地址访问,可以是域名,IP,或*号
INSTALLED_APPS = [
'django.contrib.admin', #管理员站点
'django.contrib.auth', #认证授权系统。
'django.contrib.contenttypes', #内容类型框架。
'django.contrib.sessions', #会话框架。
'django.contrib.messages', #消息框架。
'django.contrib.staticfiles', #管理静态文件的框架。
'webApp.apps.WebappConfig', #自建应用举例
]
#已安装的应用
#如果我们自己创建了应用需要把应用名添加到这个地方
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
#中间件(工具集)
ROOT_URLCONF = 'pyWeb.urls'
#url根文件
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
#模板配置
WSGI_APPLICATION = 'pyWeb.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
# 数据库配置
# 如果你不使用 SQLite,则必须添加一些额外设置,比如 USER 、 PASSWORD 、 HOST 等等。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
#其他数据库配置'django.db.backends.postgresql','django.db.backends.mysql',或 'django.db.backends.oracle'
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#'USER': 'mydatabaseuser',
#PASSWORD': 'mypassword',
#'HOST': '127.0.0.1',
#'PORT': '5432',
}
}
# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
#密码认证
LANGUAGE_CODE = 'zh-hans' #admin的语言为中文
TIME_ZONE = 'Asia/Shanghai' #采用东八区时间
USE_I18N = True
USE_L10N = True
USE_TZ = True #是否采用UTC时间
STATIC_URL = '/static/' #指定了静态资源的url
#静态文件地址
urls.py路由映射文件
编写视图
向 polls/views.py
里添加更多视图。这些视图有一些不同,因为他们接收参数:
def detail(request, question_id):
return HttpResponse("You're looking at question %s." % question_id)
def results(request, question_id):
response = "You're looking at the results of question %s."
return HttpResponse(response % question_id)
def vote(request, question_id):
return HttpResponse("You're voting on question %s." % question_id)
把这些新视图添加进 polls.urls
模块里,只要添加几个 url() 函数调用就行:
from django.urls import path
from . import views #新增引用
app_name = 'polls'
urlpatterns = [
# ex: /polls/
path('', views.index, name='index'),
# ex: /polls/5/
path('<int:question_id>/', views.detail, name='detail'), #用detail来命名URL名字,这样做的好处是去除模板中的硬编码
# ex: /polls/5/results/
path('<int:question_id>/results/', views.results, name='results'),
# ex: /polls/5/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
]
- URL作为变量传递给视图
然后看看你的浏览器,如果你转到 "/polls/34/" ,Django 将会运行 detail()
方法并且展示你在 URL 里提供的问题 ID。再试试 "/polls/34/vote/" 和 "/polls/34/vote/" ——你将会看到暂时用于占位的结果和投票页。
当某人请求你网站的某一页面时——比如说, "/polls/34/" ,Django 将会载入 mysite.urls
模块,因为这在配置项 ROOT_URLCONF 中设置了。然后 Django 寻找名为 urlpatterns
变量并且按序匹配正则表达式。在找到匹配项 'polls/'
,它切掉了匹配的文本("polls/"
),将剩余文本——"34/"
,发送至 'polls.urls' URLconf 做进一步处理。在这里剩余文本匹配了 '<int:question_id>/'
,使得我们 Django 以如下形式调用 detail()
:
detail(request=<HttpRequest object>, question_id=34)
question_id=34
由 <int:question_id>
匹配生成。使用尖括号“捕获”这部分 URL,且以关键字参数的形式发送给视图函数。上述字符串的 :question_id>
部分定义了将被用于区分匹配模式的变量名,而 int:
则是一个转换器决定了应该以什么变量类型匹配这部分的 URL 路径。
-
去除硬编码
如果我们在 polls/index.html 里编写投票链接时这要样写
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
就会有固定连接字段内容,由于在polls.urls中使用了name参数为URL定义了名字,可以使用 {% url %} 标签代替它
注:Django中{{ }}和{% %}的区别
{{变量}} 里面是变量代码
{% 代码段 %} 里面是逻辑代码
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
如果想改变URL连接为polls/specifics/12/,则不需要修改模板内容,只需要改polls.urls就可以。
... # the 'name' value as called by the {% url %} template tag path('<int:question_id>/', views.detail, name='detail'), ...
-
为URL使用命名空间
在根 URLconf 中使用app_name来使用命名空间,这样在polls/index.html模板就可以进行如下修改
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
函数
render()
用途:
「载入模板,填充上下文,再返回由它生成的 HttpResponse 对象」是一个非常常用的操作流程。于是 Django 提供了这个快捷函数
polls/views.py
from django.shortcuts import render
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
get_object_or_404()
使用get()函数获取一个对象,如果不存在就抛出 Http404 错误也是一个普遍的流程。Django 也提供了一个快捷函数
如果不使用这个快捷函数时polls/views.py内容如下
from django.http import Http404
from django.shortcuts import render
from .models import Question
# ...
def detail(request, question_id):
try:
question = Question.objects.get(pk=question_id)
except Question.DoesNotExist:
raise Http404("Question does not exist")
return render(request, 'polls/detail.html', {'question': question})
使用快捷函数后polls/views.py修改为这样
from django.shortcuts import get_object_or_404, render
from .models import Question
# ...
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
数据库模型
字段类型
字段名 | 字段说明 |
---|---|
AutoField | 自增长类型,映射到数据库中是11位的整数,使用此字段时,必须传递primary_key=True,否则在生成迁移脚本文件时,就会报错,一个模型不能有两个自增长字段。一般情况下我们用不到这个字段,如果不定义主键,django会自动的为我们生成id字段作为主键 |
BigAutoField | 自增长类型,用法同AutoField。映射到数据库中会成为20位的bigint类型 |
BigIntegerField | 大整型,只要用于存储整型的数据 |
BinaryField | 主要是存储原始的二进制数据 |
BooleanField | 布尔类型(True/False),映射到数据库中会变成长度只有1位的tinyint类型,这个Field不接受null参数,要想使用可以为null的布尔类型的字段,就要使用NullBooleanField |
CharField | 字符串类型,映射到数据库中会转换成varchar类型,使用时必须传入max_length属性以定义该字符串的最大长度,如果超过254个字符,就不建议使用CharField了,此时建议使用TextField。 |
DateField | 主要存储日期类型的数据类型 |
DateTimeField | 主要存储时间相关的数据类型 |
DecimalField | 主要存储固定精度的十进制数据 |
EmailField | 在数据库底层也是一个varchar类型,默认最大长度是254个字符,当然也可以自己传递max_length参数,这个Field在数据库层面不会限制一定要传递符合email条件的字符串,只是以后在使用ModelForm表单验证时,会起作用 |
FileField | 存储文件类型的数据 |
FilePathField | 存储文件路径的数据 |
FloatField | 存储浮点型数据 |
ImageField | 存储图片型数据 |
IntegerField | 存储整型数据 |
GenericIPAddressField | 存储IP地址信息数据 |
NullBooleanField | 可以存储布尔值数据,也可以存储空null数据 |
PositiveIntegerField | 主要存储正整数数据 |
SmallIntegerField | 小整型,主要用于存储整型的数据 |
TextField | 存储文章内容信息数据,存储比较长的文本信息 |
TimeField | 存储时间信息 |
URLField | 类似于CharField,在数据库底层也是一个varchar类型,只不过只能用来存储url格式的字符串。并且默认的max_length是200,同EmailField |
注:数值类型说明
integer_field_ranges = {
'SmallIntegerField': (-32768, 32767),
'IntegerField': (-2147483648, 2147483647),
'BigIntegerField': (-9223372036854775808, 9223372036854775807),
'PositiveSmallIntegerField': (0, 32767),
'PositiveIntegerField': (0, 2147483647),
}
字段参数
字段名 | 字段值 | 说明 |
---|---|---|
null | True or False | 设置为True时,django用Null来存储空值。日期型、时间型和数字型字段不接受空字符串。 |
blank | True or False | True表示允许空,django的 Admin 中添加数据时是否可允许空值 |
choices | ||
db_column | 数据库中的字段名称 | |
db_index | 数据库索引 | |
db_tablespace | ||
default | 默认值 | |
editable | 在Admin里是否可编辑 | |
error_messages | 错误提示 | |
help_text | 在Admin中提示帮助信息 | |
max_length | 最大长度 | |
primary_key | 主键,对AutoField设置主键后,就会代替原来的自增 id 列 | |
unique | 不允许重复 | |
unique_for_date | ||
unique_for_month | ||
unique_for_year | ||
verbose_name | Admin中字段的显示名称 | |
validators | 验证 | |
auto_now | True or False | 日期字段使用,自动创建---无论添加或修改,都是当前操作的时间 |
auto_now_add | True or False | 日期字段使用,自动创建---数据创建时的时间 |
关联关系字段
ForeignKey
ManyToManyField
OneToOneField
操作数据库表
# 增--3种方法
# 第1种方法
models.tb.objects.create(c1='xx', c2='oo')
# 第2种方法
obj = models.tb(c1='xx', c2='oo')
obj.save()
# 第3种方法--可以接受字典类型数据 **kwargs
dic = {'c1':'xx','c2':'oo'}
models.tb.objects.create(**dic)
# 查
models.tb.objects.get(id=123) #获取单条数据,不存在则报错(不建议)
models.tb.objects.all() #获取全部数据
models.tb.objects.all().first() #获取全部数据的第1条数据
models.tb.objects.filter(name='seven') #1个参数,获取指定条件的数据
models.tb.objects.filter(name='seven',password='123') #2个参数,获取指定条件的数据
dic = {'name':'seven','password':'123'}
models.tb.objects.filter(**dic) #参数可以是字典形式,获取指定条件的数据
# 删
models.tb.objects.filter(name='seven').delete() # 删除指定条件的数据
dic = {'name':'seven','password':'123'}
models.tb.objects.filter(**dic).delete() #参数是字典形式
# 改
# 第1种方法
models.tb.objects.filter(name='seven').update(password='123') #将指定条件的数据更新
# 第2种方法
obj = models.tb.objects.get(id=1)
obj.c1 = '111'
obj.save() # 修改单条数据
# 第3种方法--字典参数
dic = {'name':'seven','password':'123'}
models.tb.objects.filter(**dic).update(**dic) #参数是字典形式
通用视图
官方文档Built-in class-based views API
DetailView
属性
content_type
context_object_name [get_context_object_name()]
extra_context
http_method_names
model
pk_url_kwarg
queryset [get_queryset()]
response_class [render_to_response()]
slug_field [get_slug_field()]
slug_url_kwarg
template_engine
template_name [get_template_names()]
template_name_field
template_name_suffix
方法
as_view()
dispatch()
get()
get_context_data()
get_object()
head()
http_method_not_allowed()
render_to_response()
setup()
ListView
属性
allow_empty [get_allow_empty()]
content_type
context_object_name [get_context_object_name()]
extra_context
http_method_names
model
ordering [get_ordering()]
paginate_by [get_paginate_by()]
paginate_orphans [get_paginate_orphans()]
paginator_class
queryset [get_queryset()]
response_class [render_to_response()]
template_engine
template_name [get_template_names()]
template_name_suffix
方法
as_view()
dispatch()
get()
get_context_data()
get_paginator()
head()
http_method_not_allowed()
paginate_queryset()
render_to_response()
setup()
内置标签
Django中{{ }}和{% %}的区别
{{变量}} 里面是变量代码
{% 代码段 %} 里面是逻辑代码
标签 | 说明 |
---|---|
autoescape | 自动转义开关 |
block | 块引用 |
comment | 注释 |
csrf_token | CSRF令牌 |
cycle | 循环对象的值 |
debug | 调试模式 |
extends | 继承模版 |
filter | 过滤功能 |
firstof | 输出第一个不为False的参数 |
for | 循环对象 |
for … empty | 带empty说明的循环 |
if | 条件判断 |
ifequal | 如果等于 |
ifnotequal | 如果不等于 |
ifchanged | 如果有变化,则.. |
include | 导入子模版的内容 |
load | 加载标签和过滤器 |
lorem | 生成无用的废话 |
now | 当前时间 |
regroup | 根据对象重组集合 |
resetcycle | 重置循环 |
spaceless | 去除空白 |
templatetag | 转义模版标签符号 |
url | 获取url字符串 |
verbatim | 禁用模版引擎 |
widthratio | 宽度比例 |
with | 上下文变量管理器 |