django 源码、模板的语法符号的使用

django 基础

render 原理

代码:

def ab_render(request):
    temp = Template("<h1>{{user_dict}}{{user_dict.username}}{{user_dict.password}}</h1>")
    user_dict = Context({'user_dict':{'username':'jason','password':123}})
    res = temp.render(user_dict)
    return HttpResponse(res)

视图函数并一定就是函数 也可以是类

FBV:基于函数的视图
CBV:基于类的视图

CBV基本写法

from django.views import View


	class MyLogin(View):
		def get(self,request):
			return render(request,'login.html')
		def post(self,request):
			return HttpResponse('我是类里面的post方法')
	
   urls.py
	url(r'^index/',views.MyClass.as_view())
	# 针对不同的请求方式 能够自动执行类中不同的方法

CBV源码(******)

CBV源码(******)
	MyClass.as_view()
	# 函数名加括号执行优先级最高
	@classonlymethod
	def as_view(...):
		def view(...):
			...
		return view
	# 变形
	url(r'^index/',views.view)  # CBV与FBV在路由匹配上本质是一样的
				
	def view(...):
		self = cls(...)  # 生成的是我们自己写的类的对象
			...
			return self.dispatch(...)
			"""
			当你看到self.属性或方法的时候 不要想当然 
			一定要遵循对象的属性和方法的查询顺序
			对象本身  产生对象的类  类的父类
					"""
	def dispatch(...):
			# 先判断当前请求方式是否在默认的八个合法请求方式内
			if request.method.lower() in ['get','post','delete','options'...]
				# 利用反射获取对象中对应的属性
				handler = getattr(self,request.method.lower(),报错信息)
					
			return handler(...)  # 执行获取到的方法

作用:

朝着login提交get请求会自动执行Mylogin里面的get方法
而提交post请求也会自动执行Mylogin里面的post方法

研究源码的突破口

url(r'^login/',views.MyLogin.as_view())

怎么看源码:

猜想
	as_view要么是类里面定义的普通函数 @staticmethod
	要么是类里面定义的绑定给类的方法  @classmethod
看源码发现是绑定给类的方法
		
看源码不需要每一句都看懂  只看自己能够看得懂

步骤如图:

第一步

第二步:

第三步:

第四步:

django settings源码

django其实有两个配置文件 一个是暴露给用户的可以自定义的配置 一个是项目默认的配置
		
用户配置了就用用户的 用户没有配就用默认的

必须先写入:

from django.conf import global_settings,settings
		
settings = LazySettings()

代码:

class LazySettings(...):
	def _setup(...):
		# 获取暴露给用户的配置文件字符串路径
		setting_module = os.environ.get(纯大写变量名)
		"""
		manage.py
		os.environ.setdefault(纯大写变量名,'暴露给用户的配置文件字符串路径')
		"""
				
		Settings(setting_module)
def Settings(...)
	# 先遍历全局默认的配置文件       给对象设置键值对
	for setting in dir(global_settings):
		if setting.isupper():
					setattr(self,setting,getattr(global_settings,setting))
					
	# 再遍历暴露给用户的配置文件     给对象设置键值对
	md = importlib.import_module(setting_module)
	for setting in dir(md):
		if setting.isupper():
			setattr(self,setting,getattr(md,setting))

注意:

利用的其实就是字典的键存在和不存在 下面语句的作用
dict[key] = value

模板的语法符号

{{}}  变量相关
{% %}  逻辑相关

模板层之模板传值

python基本数据类型全部支持传递给html文件
python所有基本数据类型均可

函数

模板语法会自动加括号调用 但是不支持传参

函数和对象会自动加括号
# 模板语法不支持传参

对象

后端给html文件传递数据的两种方式
1.指名道姓
	return render(request,'index.html',{'n':n,'f':f})

2.locals()  # 会将当前名称空间中所有的变量名全部传递给html页面
	return render(request,'index.html',locals())  
		
html页面上 如何获取到后端传递过来的数据 
	{{ 变量名 }}

取值

django模板语法取值 只有一种操作方式  句点符 .
点索引
点键
			
<p>{{ l.2 }}</p>
<p>{{ d.username }}</p>
<p>{{ d.password }}</p>
<p>{{ d.hobby.1.username.1 }}</p>

模板语法之过滤器 |

关键字的方法:

|length  :获取数据的长度
|add    :加法的运算
|default  :默认值(判断值是否为空)
|truncatechars :截取字符(截取5个字符 三个点也算)
|truncatewords :截取单词(截取8个单词 三个点不算)
|filesizeformat :文件的大小
|slice      : 切片的操作
|date       : 日期格式化
|safe       : 转义

使用方式

<p>过滤器  |左边的会当做过滤器的第一个参数 过滤器名右边的会当做过滤器的第二个参数</p>
<p>求数据长度:{{ s|length }}</p>
<p>加法运算:{{ n|add:10 }}、{{ s|add:13132 }}、{{ s|add:'DSB' }}</p>
<p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}、{{ ff|default:'这个ff布尔值是Flase' }}</p>
<p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}</p>
<p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}、{{ sss|truncatewords:4 }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<p>切片操作:{{ s|slice:'0:2' }}、{{ s|slice:"0:8:2" }}</p>
<p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}</p>
<p>转义:{{ res|safe }}、{{ res1 }}、后端直接标识安全:{{ res2 }}</p>

效果:

文件大小

效果:

前后端取消转义

前端

|safe

后端

from django.utils.safestring import mark_safe
res2 = mark_safe('<h1>你好啊</h1>')
可在后端直接使用mark_safe方法 使前端不用加 |safe 都可以直接运行res2

总结:

前端代码不一定非要在前端页面写,可以在后端写好传递给前端页面使用 这样的话 你就可以利用到后端更加多的逻辑语法

模板语法之标签 (逻辑相关)

{% for foo in l %}  <!--l = [1,2,3,4,5,6]-->
	{% if forloop.first %}
		<p>这是我的第一次</p>
	{% elif forloop.last %}
		<p>这是最后一次了啊~</p>
	{% else %}
		<p>{{ foo }}</p>
	{% endif %}
	{% empty %}
     <p>for循环的对象内部没有值</p>
{% endfor %}

添加描述信息后

效果:

1578396787243

没有相对参数时

效果:

for 循环



效果:

当一个值获取的步骤非常繁琐 但是又需要在很多地方用到 我们可以用起别名的方式来简化代码

效果:

自定义过滤器 标签 inclusion_tag

先完成以下前期准备工作:

1.在应用名下新建一个名字必须叫templatetags文件夹
2.在该文件夹内新建一个任意名称的py文件(eg:mytag)
3.在该文件内 必须先写以下两句代码
from django.template import Library
			
register = Library()

# 自定义过滤器
@register.filter(name='my_sum')
def index(a,b):
	return a + b


# 自定义标签
@register.simple_tag(name='my_baby')
def xxx(a,b,c,d):
	return '%s?%s?%s?%s'%(a,b,c,d)


# 自定义inclusion_tag
【‘//;/@register.inclusion_tag('demo.html',name='myin')
def index1(n):
	l = []
	for i in range(n):
		l.append(i)
	# 将列表传递给demo.html
	# return locals()
	return {'l':l}

使用方法:

		<p>自定义过滤器的使用</p>
		{% load mytag %}
		<p>{{ 10|my_sum:90 }}</p>

		<p>自定义标签的使用</p>
		{% load mytag %}
		<p>{% my_baby 1 2 3 'hello world' %}</p>


		<p>自定义的过滤器可以在逻辑语句中而自定义的标签不可以</p>
		{% if 10|my_sum:100 %}
			<p>条件成立</p>
		{% endif %}

		{% if my_baby 1 2 3 4 %}
			<p>条件成立</p>
		{% endif %}
			
		<p>自定义inclusion_tag的使用</p>
		{% load mytag %}
		{% myin 5 %}
		# 总结 页面上使用他们 统一先导入
			{% load mytag %}

代码:

<p>自定义过滤器的使用</p>
	{% load mytag %}
	<p>{{ 10|my_sum:90 }}</p>

效果:

代码:

效果:

自定义的过滤器可以在逻辑语句中而自定义的标签不可以

<p>自定义的过滤器可以在逻辑语句中而自定义的标签不可以</p>
{% if 10|my_sum:100 %}
<p>条件成立</p>
{% endif %}

{% if my_baby 1 2 3 4 %}
<p>条件成立</p>
{% endif %}

代码:

# 自定义inclusion_tag
@register.inclusion_tag('demo.html',name='myin')
def index1(n):
    l = []
    for i in range(n):
        l.append(i)
    # 将列表传递给demo.html
    # return locals()
    return {'l':l}

效果:

模板的继承

需求:某一个页面大部分区域都是公用的 那这个页面就可以作为模板页面
当别人继承这个页面之后 如何修改对应的区域
某一个页面大部分区域都是公用的 那这个页面就可以作为模板页面
当别人继承这个页面之后 如何修改对应的区域
		
先在模板页面上通过block实现划定区域
	{% block content %}	
		模板页面内容
	{% endblock %}
		
子页面中先导入整个模板
	{% extends '模板页面.html'%}
	修改特定的区域  通过实现划定好的区域名称
		{% block content %}
				子页面内容
		{% endblock %}
		
通常情况下 模板页面页面应该起码有三块区域
		{% block css %}	
			模板页面内容
		{% endblock %}
		{% block content %}	
			模板页面内容
		{% endblock %}
		{% block js %}	
			模板页面内容
		{% endblock %}
	# 模板的block块越多 可扩展性越高
		
	还支持子页面调用父页面对应区域的内容 并且可以无限次调用
			{{ block.super }}
		

先在模板页面上通过block实现划定区域

先去视图层建立 views.py

def mdzz(request):
    return render(request,'mdzz.html')

在去文件里写代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    {% block css %}

    {% endblock %}
</head>
<body>
<nav class="navbar navbar-inverse">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <form class="navbar-form navbar-left">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-3">
            <div class="list-group">
              <a href="/mdzz/" class="list-group-item active">
                首页
              </a>
              <a href="/register/" class="list-group-item">注册</a>
              <a href="/loginn/" class="list-group-item">登录</a>
              <a href="#" class="list-group-item">Porta ac consectetur ac</a>
              <a href="#" class="list-group-item">Vestibulum at eros</a>
            </div>
        </div>
        <div class="col-md-9">
            <div class="panel panel-primary">
              <div class="panel-heading">
                <h3 class="panel-title">Panel title</h3>
              </div>
              <div class="panel-body">
                {% block content %}
                <div class="jumbotron">
                  <h1>Hello, world!</h1>
                  <p>...</p>
                  <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
                </div>
                {% endblock %}
              </div>
            </div>
        </div>
    </div>
</div>

{% block js %}

{% endblock %}
</body>
</html>

子页面中先导入整个模板

登录页面

def loginn(request):
    return render(request,'loginn.html')

html文件代码:

{% extends 'mdzz.html' %}

{% block css %}
    <style>
        h2  {
            color: red;
        }
    </style>
{% endblock %}

{% block content %}
    {% include 'left.html' %}



<h2 class="text-center">登录页面</h2>
    <form action="">
        <p>username:
            <input type="text" class="form-control">
        </p>
    <p>password:
            <input type="text" class="form-control">
        </p>
        <input type="submit" class="btn btn-primary">
    </form>
    {{ block.super }}

{% endblock %}


{% block js %}
{#    <script>#}
{#        alert(123)#}
{#    </script>#}
{% endblock %}

1578402104426

通常情况下 模板页面页面应该起码有三块区域

注册页面

def register(request):
    return render(request,'reg.html')

html文件代码:

{% extends 'mdzz.html' %}

{% block css %}
    <style>
        h2 {
            color: green;
        }
    </style>
{% endblock %}


{% block content %}
<h2 class="text-center">注册页面</h2>
    <form action="">
        <p>username:
            <input type="text" class="form-control">
        </p>
    <p>password:
            <input type="text" class="form-control">
        </p>
        <input type="submit" class="btn btn-danger">
    </form>
    {{ block.super }}
    {{ block.super }}
    {{ block.super }}
    {{ block.super }}
    {{ block.super }}
    {{ block.super }}
    {{ block.super }}
{% endblock %}


{% block js %}
{#    <script>#}
{#        alert(666)#}
{#    </script>#}
{% endblock %}

1578402182198

### 基于django settings源码实现项目配置文件的 插拔式设计

原文地址:https://www.cnblogs.com/WQ577098649/p/12163756.html