Django框架4

Django框架4


一.render简单实现

from django.shortcuts import render,HttpResponse
from django.template import Template, Context

def db_render(request):
    temp = Template("<h1>{{user_dic}}{{user_dic.username}}{{user_dic.password}}</h1>")
    user_dict = Context(
        {
            'user_dic': {
                'username': 'jason',
                'password': 1123,
            }
        }
    )
    res = temp.render(user_dict)

    return HttpResponse(res)

结果展示:

二.CBV与FBV

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

fbv: 基于函数的视图

cbv: 基于类的视图

cbv基本的写法:

from django.views import View


class MyLogin(View):

    def get(self, request):
        return render(request, 'login_cbv.html')

    def post(self, request):
        return HttpResponse('我是类里面的post方法')

前端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.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>
</head>
<body>
    <h2 class="text_center">这里是login_cbv页面</h2>
    <form action="" method="post">
        <p>
            提交 <input type="submit" class="btn btn-primary">
        </p>
    </form>
</body>
</html>

朝着login_cbv提交get请求时会自动执行MyLogin里面的get方法

而提交post请求也会自动执行MyLogin里面的post方法

为什么MyLogin针对不同的请求方法能够自动执行对应的方法,引入cbv源码

三.CBV源码

研究源码的突破口:
url(r'^login_cbv', view.MyLogin.as_view())

​ 猜想

​ as_view要么是类里面定义的普通函数 @staticmethod

​ 要么是类里面定义的绑定给类的方法 @classmethod

看到源码发现是类的绑定方法

详细步骤注释图解:

流程详情:

fbv与cbv在路由匹配上本质是一样的

# 首先MyLogin是我们自己创建的类,里面写了get与post方法
# 然后这个类继承了View类,所以调用了View里面的as_view方法
# as_view方法返回的是View类里的闭包函数view的地址值
# 所以url(r'^login/',views.MyLogin.as_view())就相当于:url(r'^login/',views.view)
# 正则匹配到login后,调用view函数,首先生成了一个我们自己创建的类的对象,self,接着给self对象添加属性,再通过对象.属性调用方法dispatch方法,对象以及产生对象的类中没有这个方法,所有调用了父类中的dispatch方法
# 在displatch中首先判断请求的请求方式是否在默认的八大请求方式中,再在对象中找到对应的请求方法post或get,display返回的是请求方式()就是执行了请求方法
所以:
	朝着login_cbv提交get请求时会自动执行MyLogin里面的get方法

而提交post请求也会自动执行MyLogin里面的post方法

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(...)  # 执行获取到的方法

四.基于django settings 源码应用到自己的项目中

​ django暴露给用户一个可以自定义的配置,但是内部也有一个默认的配置

​ 用户配置了就用用户的, 用户没有配置就用默认的

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文件

​ 函数与类:

​ 函数和类会自动添加括号执行

​ 函数得到的是函数的返回值,而类得到的是它的对象

​ 模板语法不支持传参

后端给html文件传递数据的两种方式:

1.指名道姓

​ return render(request, 'index.html', {'n':n, 'm':m})

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>

六.过滤器

|... 格式要规范,不可乱加空格

过滤器 |左边的会当做过滤器的第一个参数 过滤器名右边的会当做过滤器的第二个参数

求数据长度:
<p>
    {{ s|length }}
</p>

加法运算:
<p>
    {{ n|add:12 }},	两个整型是相加求和
    {{ s|add:'da'}}	两个字符串是拼接 如果一个是字符串一个是整型会报错
</p>

默认值(判断值是否为空):	如果前面的值是空,则返回:后面的,如果前面的值不为空,则返回:前面的
<p>
    {{ b|default:'这个b布尔值是true'}},
    {{ ff|default:'这个ff布尔值是false'}}
</p>

截取字符(截取5个字符 三个点也算):
<p>
   {{ s|truncatechars:8 }}, 
</p>
截取单词 (截取4个单词 三个点不算): 以空格为一个单词结束
<p>
    {{ ss|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>

转义:直接传前端语法,为防止恶意脚本,传过去并不执行,
除非后端用mark_safe()来包装一下
或者前端用|safe来表示安全
<p>
    {{ res|safe }}, {{res1}},{{res2}}
</p>
ps:前端代码不一定非要在前端页面写,可以在后端写好传递给前端页面使用,这样就可以利用到后端更加多的逻辑语法

七.标签

逻辑相关的

{% for foo in l %}
	{% if forloop.first %}
		<p>第一次</p>
	{% elif forloop.last %}
		<p>最后一次</p>
	{% else %}
		<p>
            {{foo}}
</p>
	{% endif %}
	{% empty %}
	<p>
        for循环的对象内部没有值
</p>
{% endfor %}

八.自定义过滤器及标签

标签 inclusion_tag

先完成以下前期准备工作

​ 1.在应用名下新建一个名字必须叫templatetags文件夹

​ 2.在该文件内新建一个任意名称的py文件夹(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('test.html', name='myin')
def index1(n):
    l=[]
    for i in range(n):
        l.append(i)
    return {'l':l}

使用方法

自定义过滤器的使用
{% load mytag %}
<p>
    {{ 10|my_sum:90 }}
</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 %}
自定义inclusion_tag的使用
<p>
    {% load mytag %}
    {% myin 5 %}
</p>

总结
页面上想要使用他们 要统一导入
{% load mytag %}

九.模板的继承

​ 某一个页面大部分区域是公用的 那这个页面就可以作为模板页面

当别人继承这个页面之后 再修改对应的区域

先在模板页面上通过block实现划定区域
	{% block content %}
		模板页面的内容
	{% endblock %}

子页面中先导入整个模块
	{% extends '模板页面.html' %}
	修改特定的区域 通过实现划定好的区域名称
	{% block content %}
		子页面内容
	{% endblock %}

通常情况下 模板页面应该起码有三块区域
	{% block css %}
		模板页面内容
	{% endblock %}

	{% block content %}
		模板页面内容
	{% endblock %}

	{% block js %}
		模板页面内容
	{% endblock %}

	# 模板的block块越多 可扩展性越高
	
	还支持子页面调用父页面对应区域的内容 并且可以无限次调用
		{{ block.super }}

十.模板的导入

​ 将hml页面当做模块来使用 哪里需要倒哪里 这个html页面通常都不是完整的 只是一个局部样式

{% include 'left.html' %}

posted @ 2020-01-07 23:25  godlover  阅读(148)  评论(0编辑  收藏  举报