FBV与CBV

  视图函数并不只是指函数,也可以是类

FBV:基于函数的视图,类似面向函数式编程

CBV:基于类的视图,类似面向对象编程

研究解析render源码:

  render:返回html页面;并且能够给该页面传值

分析:FBV视图原理

from django.shortcuts import render,HttpResponse

# Create your views here.

from django.template import  Template,Context
# FBV解析
def index(request):
temp = Template('<h1>{{ user }}</h1>')
con = Context({"user":{"name":'gets','password':''}})
res =temp.render(con)
print(res)
return HttpResponse(res)

print的结果:

可以分析出利用关键字:Context 先获取数据格式,通过con = Context({"user":{"name":'gets','password':''}})转成字典形式传给前端显示

分析CBV视图原理:类方法

问题:基于CBV的视图函数,get请求来就会走类里面get方法,post请求来就会走类里面post方法 为什么???

为什么会自动分布请求类中的get/post方法呢?有什么在自动识别?

验证请求方式的get/post的执行

#CBV视图
from django.views import View
from django.conf import settings
class MyLogin(View):
def get(self,request):
print("from MyLogin get方法") 为什么会走get/post
return render(request,'login.html')
def post(self,request):
return HttpResponse("from MyLogin post方法")

CBV对应的路由层:url

  由于函数名加括号执行优先级最高,所以这一句话一写完会立刻执行as_view()方法

1、从url入手分析这一现象的存在:分析as_view源码解析结果:

分析步骤:

点击view方法查看:

点击view继承的父类dispatch方法

再次查看源码部分内容分析:

源码解析:

@classonlymethod
def as_view(cls, **initkwargs): # cls就是我们自己的写的类 MyLogin
def view(request, *args, **kwargs):
self = cls(**initkwargs) # 实例化产生MyLogin的对象 self = MyLogin(**ininkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
# 上面的几句话都仅仅是在给对象新增属性
return self.dispatch(request, *args, **kwargs) # dispatch返回什么 浏览器就会收到什么
# 对象在查找属性或者方法的时候 你一定要默念 先从对象自己这里找 然后从产生对象的类里面找 最后类的父类依次往后
return view

通过源码发现url匹配关系可以变形成

url(r'^login/',views.view)  # FBV和CBV在路由匹配上是一致的 都是url后面跟函数的内存地址

2、当浏览器中输入login,会立刻触发view函数的运行

第二部分分析源码:

def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
# 我们先以GET为例
if request.method.lower() in self.http_method_names: # 判断当前请求方法是否在默认的八个方法内
# 反射获取我们自己写的类产生的对象的属性或者方法
# 以GET为例 handler = getattr(self,'get','取不到报错的信息')
# handler = get(request)
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) # 直接调用我们自己的写类里面的get方法
# 源码中先通过判断请求方式是否符合默认的八个请求方法 然后通过反射获取到自定义类中的对应的方法执行

通过路由层url中的.re_view方法,解析源码分析得出实现get/post请求分发的原理,是什么请求就走什么方法

Django settings 源码解析:

 前提:

1、diango除了暴露给用户一个settings.py配置的文件之外,自己内部还有一个全局的配置文件(只是展示了部分信息的settnigs)。

2、我们在使用配置文件的时候,可以直接导入暴露给用户的settings.py也可以使用django全局的配置问的文件

需要导入的模块:from django.conf import settings

点击settings 查看源码配置文件

3、django的启动入口是manage.py

分析为什么在settings配置文件中的变量名都是大写的?为什么写小写的就不行了呢?

基于以上分析源码后,分析实现seettings的功能,受限变量名必须写大写

import os
import sys if __name__ == "__main__":
# django在启动的时候 就会往全局的大字典中设置一个键值对 值是暴露给用户的配置文件的路径字符串
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day54.settings") class Settings(object):
def __init__(self, settings_module): # settings_module = 'day54.settings'
# update this dict from global settings (but only for ALL_CAPS settings)
or setting in dir(global_settings): # django全局配置文件
# dir获取django全局配置文件中所有的变量名
if setting.isupper(): # 判断文件中的变量名是否是大写 如果是大写才会执行/生效
setattr(self, setting, getattr(global_settings, setting)) # 给settings对象设置键值对
# 给settings对象设置键值对 settings[配置文件中大写的变量名] = 配置文件中大写的变量名所对应的值 # store the settings module in case someone later cares
self.SETTINGS_MODULE = settings_module # 'day54.settings' mod = importlib.import_module(self.SETTINGS_MODULE) # mod = 模块settings(暴露给用户的配置文件)
for setting in dir(mod): # for循环获取暴露给用户的配置文件中所有的变量名
if setting.isupper(): # 判断变量名是否是大写
setting_value = getattr(mod, setting) # 获取大写的变量名所对应的值
setattr(self, setting, setting_value) # 给settings对象设置键值对
"""
d = {}
d['username'] = 'jason'
d['username'] = 'egon'
用户如果配置了就用用户的
用户如果没有配置就用系统默认的
其实本质就是利用字典的键存在就是替换的原理 实现了用户配置就用用户的用户没配置就用默认的
"""

class settings 实现必须书写大写的精髓部分:

继承的类分析:

class LazySettings(LazyObject):
def _setup(self, name=None):
# os.environ你可以把它看成是一个全局的大字典
settings_module = os.environ.get(ENVIRONMENT_VARIABLE) # 从大字典中取值键为DJANGO_SETTINGS_MODULE所对应的值:day54.settings
# settings_module = 'day54.settings'
self._wrapped = Settings(settings_module) # Settings('day54.settings') settings = LazySettings()  # 单例模式 

实现功能的核心代码块:

作业:
  参考django settings源码 实现自己的项目也能够做到 用户配置了就用用户的 用户没有配置 就用全局的

__init__.py文件下:

import os
import importlib
from lib.conf import global_settings class Settings(object):
def __init__(self):
# 先for循环获取全局配置文件中所有的变量名
for name in dir(global_settings):
# 判断是否是大写
if name.isupper():
#给settings对象设置键值对
setattr(self,name,getattr(global_settings,name))
path = os.environ.get('xxx')
module = importlib.import_module(path)
#再循环暴露给用户的文件中所有的变量名
for name in dir(module):
if name.isupper():
k=name
v=getattr(module,name)
setattr(self,k,v)
settings=Settings()

start.py文件

import os
import sys BASE_DIR = os.path.dirname(__file__)
sys.path.append(BASE_DIR) if __name__ == '__main__':
# 在项目中的全局一个大字典
os.environ.setdefault('xxx','conf.settings')
from lib.conf import settings
print(settings.NAME)

Django模板层

  模板语法

1、为模板传值

只需要记两种特殊符号:
{{ }}和 {% %}
变量相关的用{{}},逻辑相关的用{%%}。

两种给前端传值的区别

 给模板传值的方式 方式1
# 通过字典的键值对 指名道姓的一个个的传
return render(request,'reg.html',{'n':n,'f':f})
方式2
# locals会将它所在的名称空间中的所有的名字全部传递给前端
# 该方法虽然好用 但是在某些情况下回造成资源的浪费 # return render(request, 'reg.html', locals())

<p>传函数名,会自动加括号调用该函数,前端展示的是函数调用之后的返回值:{{ index }}

注意:如果函数需要参数的话  那么不好意思 模板语法不支持

变量
在Django的模板语法中按此语法使用{{变量名}}.
当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。 变量的命名包括任何字母数字以及下划线 ("_")的组合。 变量名称中不能有空格或标点符号 标签与过滤器
Filters(过滤器)
在Django的语法中,通过使用过滤器来改变变量的显示.

过滤器的语法: {{ value|filter_name:参数 }}

使用管道符"|"来应用过滤器。

{#<h1>模板语法之标签:内部原理(会将|前面的当做第一个参数传入标签中)</h1>#}

注意事项:

1、过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
2、过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
3、过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:', ' }}
4、'|'左右没有空格没有空格没有空格

Django的模板语言中常用的内置过滤器有:

default:如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值

一些常用的过滤器的详解:

length

返回值的长度,作用于字符串和列表。

{{ value|length }}

返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.

filesizeformat

将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB''4.1 MB''102 bytes', 等等)。例如:

{{ value|filesizeformat }}

如果 value 是 123456789,输出将会是 117.7 MB。

slice

切片

{{value|slice:"2:-1"}}

date

格式化

{{ value|date:"Y-m-d H:i:s"}}

safe

Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义

比如:

value = "<a href='#'>点我</a>"

{{ value|safe}}

前后端取消转义

 也就意味着前端的html代码 并不单单只能在html文件中书写
    你也可以在后端先生成html代码 然后直接传递给前端(**)

前端

  |safe

后端

from django.utils.safestring import mark_safe
mark_safe("<a href='url'>xxx</a>")

truncatechars

  如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。

参数:截断的字符数

{{ value|truncatechars:9}}

truncatewords

在一定数量的字后截断字符串。

{{ value|truncatewords:9}}

cut

移除value中所有的与给出的变量相同的字符串

{{ value|cut:' ' }}

如果value为'i love you',那么将输出'iloveyou'.

join

使用字符串连接列表,例如Python的str.join(list)

timesince

将日期格式设为自该日期起的时间(例如,“4天,6小时”)。

采用一个可选参数,它是一个包含用作比较点的日期的变量(不带参数,比较点为现在)。

例如,如果blog_date是表示2006年6月1日午夜的日期实例,并且comment_date是2006年6月1日08:00的日期实例,则以下将返回“8小时”:

{{ blog_date|timesince:comment_date }}

分钟是所使用的最小单位,对于相对于比较点的未来的任何日期,将返回“0分钟”。

timeuntil

似于timesince,除了它测量从现在开始直到给定日期或日期时间的时间。 例如,如果今天是2006年6月1日,

而conference_date是保留2006年6月29日的日期实例,则{{ conference_date | timeuntil }}将返回“4周”。

使用可选参数,它是一个包含用作比较点的日期(而不是现在)的变量。 如果from_date包含2006年6月22日,则以下内容将返回“1周”:

{{ conference_date|timeuntil:from_date }}

标签:逻辑相关 {%%}

for循环可用的一些参数:

Variable Description
forloop.counter 当前循环的索引值(从1开始)
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(从1开始)
forloop.revcounter0 当前循环的倒序索引值(从0开始)
forloop.first 当前循环是不是第一次循环(布尔值)
forloop.last 当前循环是不是最后一次循环布尔值)
forloop.parentloop 本层循环的外

if判断

if,elif和else

结合使用:

if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。

with

定义一个中间变量,多用于给一个复杂的变量起别名。

注意等号左右不要加空格。

针对字典形式的取值:

自定义过滤器和标签

适应场景:例如Django提供的过滤器或标签不能够处理一些特殊的数据时,可以自定义写

使用注意事项:

1、先在应用名下的文件夹中新建一个名字必须叫做templatetags文件夹(必须是这个名字)

2、在该文件夹内新建一个任意名称的.py文件

3、在该py文件中,必须先写以下两句代码

from django import template

register = template.Library()

前端的使用:

自定义标签

总结:

from django import template

register = template.Library()

# 自定义过滤器
@register.filter(name='mysum')
def mysum(a,b)
retunr a + b # 自定义标签
@register.simple_tag(name='myplus')
def myplus(a,b,c,d,e):
return None # 自定义inclusion_tag
@register.inclusion_tag('mytag.html')
def mytag(n):
...
# return {'l':l}
return locals()

在html上使用需要先导入后使用

{% load py文件名 %}
{{ 2|mysum:1}}
{% myplus 1 2 3 5 5 %}
{% mytag 10 %}

模板的继承与导入

使用的场景:当多个HTML页面需要使用相同的HTML代码的时候,可以考虑使用继承

搭页面:

首先需要你在模板html代码中 通过block块儿划定后续想要修改的区域
   {%block content%}
   {%endblock%}

一般情况下 模板html文件内应该有三块区域 css,content,js

模板一般情况下
应该至少有三个可以被修改的区域
{ % block
css %}
子页面自己的css代码
{ % endblock %} { % block
content %}
子页面自己的html代码
{ % endblock %} { % block
js %}
子页面自己的js代码
{ % endblock %} 

实际应用到html:

简单的结构介绍:

模板的导入
{% extends '模板的名字'%}
{%block content%}
修改模板中content区域的内容
{{ block.super }}重新复用模板的html样式
{%endblock%} 模板的导入
{% include '你想要导入的html文件名'%}

模板的导入:关键字:include 路由分发:也是用这个关键字,联想记忆

模型层的单表查询

创建表:

create_time = models.DateField()
关键性的参数
.auto_now:每次操作数据 都会自动刷新当前操作的时间
2.auto_now_add:在创建数据的时候 会自动将创建时间记录下来 后续的修改不会影响该字段

简单创建一张表:

创建表后记得更新表的迁移操作:两条命令

编写测试脚本:

  在django中 你可以写一个单独测试某一个py文件的测试脚本 不需要再频繁的走web请求

单表的操作: 增  删  改  查

import os
import sys if __name__ == '__main__':
# django 在启动的时候 就会往全局的大字典一个键值对,值时暴露给用户的
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Djangoday54.settings") import django
django.setup() from app01 import models
models.Book.objects.all()
book_obj = models.Book.objects.create(title="百年孤独",price=199.99,create_time=2019-11-20)
print(book_obj.title) # from datetime import datetime
# ctime = datetime.now()
# book_obj = models.Book(title='围城',price=200.99,create_time=ctime)
# book_obj.save()
#查
print(models.Book.objects.all())
print(models.Book.objects.get(id=2)) # 自动查找到当前的数据主键字段 # 改 update
models.Book.objects.filter(pk=1).update(title='百年孤独')
book_obj =models.Book.objects.get(pk=1)
book_obj.price = 66.34
book_obj.save() # 删除 delete()
models.Book.objects.filter(pk=1).delete()

单表的增删改查

  单表查询必会的13个方法:

返回QuerySet对象的方法有

all()

filter()

exclude()

order_by()

reverse()

distinct()

特殊的QuerySet

values()       返回一个可迭代的字典序列

values_list() 返回一个可迭代的元祖序列

返回具体对象的

get()

first()

last()

返回布尔值的方法有:

exists()

返回数字的方法有

count()

 < 1 > all(): 查询所有结果
< 2 > filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
< 3 > get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象)
< 4 > exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
print(models.Book.objects.exclude(pk=1)) # 只要pk不是1的数据全部查询出来 < 5 > order_by(*field): 对查询结果排序('-id') / ('price')
print(models.Book.objects.order_by('price')) # 默认是升序
print(models.Book.objects.order_by('-price')) # 加负号就是降序 # < 6 > reverse(): 对查询结果反向排序 >> > 前面要先有排序才能反向
# print(models.Book.objects.order_by('price').reverse())
# < 7 > count(): 返回数据库中匹配查询(QuerySet)
# print(models.Book.objects.count()) # 对查询出来的结果进行一个计数 # < 8 > first(): 返回第一条记录
# print(models.Book.objects.filter(pk=1).first())
# < 9 > last(): 返回最后一条记录
# print(models.Book.objects.all())
# print(models.Book.objects.all().last()) # < 10 > exists(): 如果QuerySet包含数据,就返回True,否则返回False
# print(models.Book.objects.filter(pk=1000))
# print(models.Book.objects.filter(pk=1000).exists()) # < 11 > values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
# model的实例化对象,而是一个可迭代的字典序列
# print(models.Book.objects.values('title','price')) # 得到的结果是列表套字典 # < 12 > values_list(*field): 它与values()
# print(models.Book.objects.values_list('title','price')) # 得到的结果是列表套元组 # 非常相似,它返回的是一个元组序列,values返回的是一个字典序列
# < 13 > distinct(): 从返回结果中剔除重复纪录
"""
去重的前提是 一定要有完全重复的数据 才能去重
"""
# print(models.Book.objects.filter(title='三国演义').distinct())
# print(models.Book.objects.values('title','price','create_time').distinct())

其他方法的使用

  

  


  

Django的View(视图)-settings源码的解析-模板层-模板语法的更多相关文章

  1. Django Rest Framework----ModelViewSet视图 ModelViewSet源码分析

    一.视图类 #bookview是一个视图类,继承自ModelViewSet class BookView(ModelViewSet): throttle_classes = [VisitThrottl ...

  2. android2.3 View视图框架源码分析之一:android是如何创建一个view的?

    View是所有控件的一个基类,无论是布局(Layout),还是控件(Widget)都是继承自View类.只不过layout是一个特殊的view,它里面创建一个view的数组可以包含其他的view而已. ...

  3. django 之csrf、auth模块及settings源码、插拔式设计

    目录 基于django中间件拷贝思想 跨站请求伪造简介 跨站请求伪造解决思路 方式1:form表单发post请求解决方法 方式2:ajax发post请求解决方法 csrf相关的两个装饰器 csrf装饰 ...

  4. 跨站请求伪造(csrf),django的settings源码剖析,django的auth模块

    目录 一.跨站请求伪造(csrf) 1. 什么是csrf 2. 钓鱼网站原理 3. 如何解决csrf (1)思路: (2)实现方法 (3)实现的具体代码 3. csrf相关的装饰器 (1)csrf_p ...

  5. Django对中间件的调用思想、csrf中间件详细介绍、Django settings源码剖析、Django的Auth模块

    目录 使用Django对中间件的调用思想完成自己的功能 功能要求 importlib模块介绍 功能的实现 csrf中间件详细介绍 跨站请求伪造 Django csrf中间件 form表单 ajax c ...

  6. Django的settings源码分析

    Django其实有两个配置文件,一个是暴露给用户的可以自定义的配置,一个是项目默认的配置,用户如果配置了就用用户的,没有配置就用默认的. 首先需要在settings文件中导入,然后查看settings ...

  7. Django settings源码解析

    Django settings源码 Django中有两个配置文件 局部配置:配置文件settings.py,即项目同名文件夹下的settings.py文件 全局配置:django内部全局的配置文件se ...

  8. Django学习——Django settings 源码、模板语法之传值、模板语法之获取值、模板语法之过滤器、模板语法之标签、自定义过滤器、标签、inclusion_tag、模板的导入、模板的继承

    Django settings 源码 """ 1.django其实有两个配置文件 一个是暴露给用户可以自定义的配置文件 项目根目录下的settings.py 一个是项目默 ...

  9. DRF框架(一)——restful接口规范、基于规范下使用原生django接口查询和增加、原生Django CBV请求生命周期源码分析、drf请求生命周期源码分析、请求模块request、渲染模块render

    DRF框架    全称:django-rest framework 知识点 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件 ...

随机推荐

  1. 安装Linux系统Centos6版本

    1.下载VMware软件 2.下载Centos6文件 http://archive.kernel.org/centos-vault/6.8/isos/x86_64/CentOS-6.8-x86_64- ...

  2. JS高级学习笔记(6)- 事件循环

    参考文章:深入理解JS引擎的执行机制        JavaScript 异步.栈.事件循环.任务队列 我的笔记:ES系列之Promise async 和 await Event Loop 前提 js ...

  3. Swift实现iOS录音与播放音频功能

    作用AVPLayer:可以用来播放在线及本地音视频AVAudioSession:音频会话,主要用来管理音频设置与硬件交互使用时需要导入 #import <AVFoundation/AVFound ...

  4. Android进阶——Crash异常捕获并发送到服务器

    在项目中,我们常常会遇到Crash的现象,也就是程序崩溃的时候,这个时候最常看到的就是这个界面 如果你的项目已经发布到市场上了,这样的崩溃对于开发人员是看不到的,所以我们得想方法将崩溃信息发送到服务器 ...

  5. App基本界面组件案例

    今天的收获颇大呀,我发现了一个更高效快速的学习方法,如果真的是因为学习内容太多,无从下手的话,不妨去别人或者自己崇拜的大佬里的博客园里面转一转,你就会有意外的收获,不仅给你学习的压力,还更直观的给介绍 ...

  6. Idea的类中使用实体类(有@Data注解)的Get/Set方法报错

    今天从svn上面下了一个maven项目,导入到Idea中之后,发现有的类会使用实体类的Set/Get方法(全报错),导致该问题的原因就是因为实体类中没有这个方法,代码类似如下: @Data publi ...

  7. JetBrains系列-插件

       插件官网:http://plugins.jetbrains.com   注意:网站有时不稳定,会造成打不开,属正常现象或许下一秒就好了,可以选择去git等方式下载 1.安装说明:   打开fil ...

  8. elastic启动脚本

    #!bin/bash export JAVA_HOME=/usr/java/jdk1.8.0_144 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH ...

  9. mint linux的几个问题

    刚开机登录时, 键盘不停的输入同一个字符 发现在虚拟机里安装的系统没有问题, 因此怀疑配置有冲突, 新建一个用户果然能解决问题 解决方法: 把 主目录下, 隐藏的配置目录删除, 重新登录后再配置. 4 ...

  10. iview checkbox demo(文档改写)

    <template> <div class="content"> <div style="border-bottom: 1px solid ...