DAY3
【知识回顾】过滤器
作用: 对变量进行过滤。在真正渲染出来之前,过滤器会根据功能处理好变量,然后得出结果后再替换掉原来的变量展示出来。
语法:{{fruits|lower}}
管道符号进行链式调用,比如实现一个功能,先把所有字符变成小写,把第一个字符转换成大写。
语法:{{fruits|lower|capfirst}}
使用参数:过滤器可以使用参数,在过滤器名称后面使用冒号”:”再加上参数,比如要把一个字符串中所有的空格去掉,则可以使用cut过滤器,
语法如下: {{fruits|cut:” “}}
注意:
使用参数的时候,冒号和参数之间不能有任何空格,一定要紧挨着
常用标签
什么是标签?
在模板渲染的过程中提供任意逻辑;
这个定义是刻意模糊的。 例如,一个标签可以输出内容,作为控制结构,例如“if”语句或“for”循环从数据库中提取内容,甚至可以访问其他的模板标签;
标签语法: 由%}和 {%来定义的,例如:
{%tag%} {%endtag%};
常用标签
【补充】子应用的创建
1,在该路径激活虚拟环境—-Scripts下
C:\Users\tylor\Documents\项目管理\duplicate\tzblog\Scripts>activate
2, 创建子应用的路径—-项目路径下
C:\Users\tylor\Documents\项目管理\duplicate\tzblog\Scripts\tzlook>tree /f
3,在tzlook/settings.py下注册app
【注意】在settings下配置apps的名字,可以从子应用的app下找到
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth', # 用户与权限认证应用
'django.contrib.contenttypes', # 为Model提供更高层次抽象接口应用,被auth依赖
'django.contrib.sessions', # 保存用户状态的会话应用
'django.contrib.messages', # 消息应用
'django.contrib.staticfiles',
'look.apps.LookConfig',
'book.apps.BookConfig',
]
模板的继承
【组件】
三个HTML文件:base, indexx, ss
【代码】
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %} 这是默认标题{% endblock %}</title>
</head>
<body>
{% block content %}
这是默认内容
{% endblock %}
{% block demo %}
这是默认演示
{% endblock %}
</body>
</html>
indexx.html
{% extends 'base.html' %}
{% block title %}主页{% endblock %}
{% block content %}
这是通过blocksuper继承的父类:{{block.super}}<br>
{% endblock %}
{% block demo %}
这是通过include 引用的其他模板的内容:{% include 'ss.html' %}
{% endblock %}
ss.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>内容</title>
</head>
<body>
潭州教育python学院 Djano框架班
</body>
</html>
【效果展示】
【】
【】
模板的引用
步骤:
首先在tzlook/template创建名为look的HTML5文件
然后在tzlook/urls.py中导入tzlook/book.urls路径
其次在tzlook/book/urls中调用book/views视图
【注意】需要导入应用的views文件
在book/views中书写类,同时调用html5文件
【注意】需要在视图函数中导入渲染器;
总结
【tips】location : django/template/base.py
【source code】—- example of using template
The Template class is a convenient wrapper that takes care of template
compilation and rendering.
Usage:
The only thing you should ever use directly in this file is the Template class.
Create a compiled template object with a template_string, then call render()
with a context. In the compilation stage, the TemplateSyntaxError exception
will be raised if the template doesn't have proper syntax.
Sample code:
>>> from django import template
>>> s = '<html>{% if test %}<h1>{{ varvalue }}</h1>{% endif %}</html>'
>>> t = template.Template(s)
(t is now a compiled template, and its render() method can be called multiple
times with multiple contexts)
>>> c = template.Context({'test':True, 'varvalue': 'Hello'})
>>> t.render(c)
'<html><h1>Hello</h1></html>'
>>> c = template.Context({'test':False, 'varvalue': 'Hello'})
>>> t.render(c)
'<html></html>'
"""
【source code】definition of template
class Template:
def __init__(self, template_string, origin=None, name=None, engine=None):
# If Template is instantiated(illustrate) directly rather than from an Engine and
# exactly one Django template engine is configured, use that engine.
# This is required to preserve backwards-compatibility[兼容性] for direct use
# e.g. Template('...').render(Context({...}))
if engine is None:
from .engine import Engine
engine = Engine.get_default()
if origin is None:
origin = Origin(UNKNOWN_SOURCE)
self.name = name
self.origin = origin
self.engine = engine
self.source = template_string
self.nodelist = self.compile_nodelist()
def __iter__(self):
for node in self.nodelist:
yield from node
def _render(self, context):
return self.nodelist.render(context)
def render(self, context):
"Display stage -- can be called many times"
with context.render_context.push_state(self):
if context.template is None:
with context.bind_template(self):
context.template_name = self.name
return self._render(context)
else:
return self._render(context)
def compile_nodelist(self): # Nodelist is similar as array
"""
Parse and compile the template source into a nodelist. If debug
is True and an exception occurs during parsing, the exception is
is annotated with contextual line information where it occurred in the
template source.
"""
if self.engine.debug:
lexer = DebugLexer(self.source) # lexer---词法分析程序
else:
lexer = Lexer(self.source)
tokens = lexer.tokenize()
parser = Parser(
tokens, self.engine.template_libraries, self.engine.template_builtins,
self.origin,
)
try:
return parser.parse()
except Exception as e:
if self.engine.debug:
e.template_debug = self.get_exception_info(e, e.token)
raise
def get_exception_info(self, exception, token):
"""
Return a dictionary containing contextual line information of where
the exception occurred in the template. The following information is
provided:
message
The message of the exception raised.
source_lines
The lines before, after, and including the line the exception
occurred on.
line
The line number the exception occurred on.
before, during, after
The line the exception occurred on split into three parts:
1. The content before the token that raised the error.
2. The token that raised the error.
3. The content after the token that raised the error.
total
The number of lines in source_lines.
top
The line number where source_lines starts.
bottom
The line number where source_lines ends.
start
The start position of the token in the template source.
end
The end position of the token in the template source.
"""
start, end = token.position
context_lines = 10
line = 0
upto = 0
source_lines = []
before = during = after = ""
for num, next in enumerate(linebreak_iter(self.source)):
if start >= upto and end <= next:
line = num
before = escape(self.source[upto:start])
during = escape(self.source[start:end])
after = escape(self.source[end:next])
source_lines.append((num, escape(self.source[upto:next])))
upto = next
total = len(source_lines)
top = max(1, line - context_lines)
bottom = min(total, line + 1 + context_lines)
# In some rare cases exc_value.args can be empty or an invalid
# string.
try:
message = str(exception.args[0])
except (IndexError, UnicodeDecodeError):
message = '(Could not get exception message)'
return {
'message': message,
'source_lines': source_lines[top:bottom],
'before': before,
'during': during,
'after': after,
'top': top,
'bottom': bottom,
'total': total,
'line': line,
'name': self.origin.name,
'start': start,
'end': end,
}
【technique】How to read specific source code
【definition of Context】location: django/template/context.py
class RenderContext(BaseContext):
"""
A stack container for storing Template state.
RenderContext simplifies the implementation【执行】 of template Nodes by providing a
safe place to store state between invocations【d】 of a node's `render` method.
The RenderContext also provides scoping rules that are more sensible for
'template local' variables. The render context stack is pushed before each
template is rendered, creating a fresh scope with nothing in it. Name
resolution fails if a variable is not found at the top of the RequestContext
stack. Thus, variables are local to a specific template and don't affect the
rendering of other templates as they would if they were stored in the normal
template context.
"""
template = None
def __iter__(self):
yield from self.dicts[-1]
def __contains__(self, key):
return key in self.dicts[-1]
def get(self, key, otherwise=None):
return self.dicts[-1].get(key, otherwise)
def __getitem__(self, key):
return self.dicts[-1][key]
【Context_processor】definition
"""
A set of request processors that return dictionaries to be merged into a
template context. Each function takes the request object as its only parameter
and returns a dictionary to add to the context.
These are referenced from the 'context_processors' option of the configuration
of a DjangoTemplates backend and used by RequestContext.
"""
import itertools
from django.conf import settings
from django.middleware.csrf import get_token
from django.utils.functional import SimpleLazyObject, lazy
def csrf(request):
"""
Context processor that provides a CSRF token, or the string 'NOTPROVIDED' if
it has not been provided by either a view decorator or the middleware
"""
def _get_val():
token = get_token(request)
if token is None:
# In order to be able to provide debugging info in the
# case of misconfiguration, we use a sentinel[哨兵] value
# instead of returning an empty dict.
return 'NOTPROVIDED'
else:
return token
return {'csrf_token': SimpleLazyObject(_get_val)}
def debug(request):
"""
Return context variables helpful for debugging.
"""
context_extras = {}
# 当前的项目处于DEBUG模式且请求的IP地址位于INTERNAL_IPS中
if settings.DEBUG and request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
# 用于标记当前处于DEBUG模式
context_extras['debug'] = True
from django.db import connections
# 数据库的查询记录
# Return a lazy reference that computes connection.queries on access,
# to ensure it contains queries triggered after this function runs.
context_extras['sql_queries'] = lazy(
lambda: list(itertools.chain.from_iterable(connections[x].queries for x in connections)),
list
)
# sql_queries是列表,记录一次清酒发生的SQL查询和每次查询的耗时
return context_extras
def i18n(request):
from django.utils import translation
return {
'LANGUAGES': settings.LANGUAGES,
'LANGUAGE_CODE': translation.get_language(),
'LANGUAGE_BIDI': translation.get_language_bidi(),
}
def tz(request):
from django.utils import timezone
return {'TIME_ZONE': timezone.get_current_timezone_name()}
def static(request):
"""
Add static-related context variables to the context.
"""
return {'STATIC_URL': settings.STATIC_URL}
def media(request):
"""
Add media-related context variables to the context.
"""
return {'MEDIA_URL': settings.MEDIA_URL}
def request(request):
return {'request': request}
【supplement】
backup
<a href="#">{{name|cut:" "}}约么?</a>
<a href="#">{{protagonist}}约</a>
<a href="#">{{name}}去哪里?</a>
<h1>这部分代码将要演示模板变量</h1>
这个变量是字符串对象:{{books_name}}<br>
这个变量是函数对象:{{hello}}<br>
这个变量是类方法对象:{{fruit.name}}<br>
这个变量是类对象,访问类对象的属性: {{fruit.say}}<br>
这个变量是列表对象:{{ list }}<br>
这个变量是列表对象,访问列表的元素{{list.1 }}<br>
这个变量是字典对象:{{dict}}<br>
这个变量是字典对象,访问字典的键{{dict.a }}<br>
【匿名用户】
# PermWrapper[权限包装器] and PermLookupDict[权限查看字典] proxy the permissions system into objects that
# the template system can understand.
class PermLookupDict:
def __init__(self, user, app_label):
self.user, self.app_label = user, app_label
def __repr__(self):
return str(self.user.get_all_permissions())
def __getitem__(self, perm_name):
return self.user.has_perm("%s.%s" % (self.app_label, perm_name))
def __iter__(self):
# To fix 'item in perms.someapp' and __getitem__ interaction we need to
# define __iter__. See #18979 for details.
raise TypeError("PermLookupDict is not iterable.")
def __bool__(self):
return self.user.has_module_perms(self.app_label)
class PermWrapper:
def __init__(self, user):
self.user = user
def __getitem__(self, app_label):
return PermLookupDict(self.user, app_label)
def __iter__(self):
# I am large, I contain multitudes.
raise TypeError("PermWrapper is not iterable.")
def __contains__(self, perm_name):
"""
Lookup by "someapp" or "someapp.someperm" in perms.
"""
if '.' not in perm_name:
# The name refers to module.
return bool(self[perm_name])
app_label, perm_name = perm_name.split('.', 1)
return self[app_label][perm_name]
def auth(request):
"""
Return context variables required by apps that use Django's authentication
system.
If there is no 'user' attribute in the request, use AnonymousUser (from
django.contrib.auth).
"""
if hasattr(request, 'user'):
user = request.user
else:
from django.contrib.auth.models import AnonymousUser[匿名用户]
user = AnonymousUser()
return {
'user': user,
'perms': PermWrapper(user),
}