视图层函数返回数据方式:
1.HttpResponse # 返回字符串
2.render # 返回一个html页面 还可以给模板传值
from django.template import Template,Context
def index(request):
res = Template("<h1> {{ user }} </h1>")
con = Context({'user':{'username':'jason','pwd':'123'}})
ret = res.render(con)
print(ret)
return HttpResponse(ret)
3.redirect # 重定向
JsonResponse
返回json格式数据
#为什么要给前端返回json格式字符串?
前后端分离 就是基于json格式传输数据,后端就专门写接口,前端调用你这个接口 就能够拿到一个,json格式的字符串
然后前端利用序列化反序列转换成前端对应的数据类型
#js常用数据类型
数值类型
字符类型
数组 []
自定义对象 {}
undefined与null
布尔值 true false
symbol
JS中:
JSON.stringify 序列化 >>> json.dumps
JSON.parse 反序列 >>> json.loads
# def index(request):
# res = Template("<h1> {{ user }} </h1>")
# con = Context({'user':{'username':'jason','pwd':'123'}})
# ret = res.render(con)
# print(ret)
# return HttpResponse(ret)
import json
from django.http import JsonResponse
def index(request):
# user = {'username':'jason真帅 我好喜欢哦~','pwd':'123'}
# json_str = json.dumps(user,ensure_ascii=False)
# return HttpResponse(json_str)
# return JsonResponse(user,json_dumps_params={'ensure_ascii':False}) #如果包含中文,需要将ensure_ascii设置为False
l = [1,2,3,4,5,5,6]
return JsonResponse(l,safe=False)
# JsonResponse默认只支持序列化字典 如果你想序列化其他类型(json能够支持的类型) 你需要将safe参数由默认的True改成False
form表单上传文件
注意事项
1.提交方式必须是post
2.enctype参数必须有默认的urlencoded变成formdata
<form action="" method="post" enctype="multipart/form-data">
<input type="text" name="username">
<input type="file" name="myfile">
<input type="submit">
</form>
def up(request):
if request.method == 'POST':
print(request.POST)
print(request.FILES)
# 获取文件对象
file_obj = request.FILES.get('myfile')
print(file_obj.name) # 获取文件名
with open(file_obj.name,'wb') as f:
# for line in file_obj: # file_obj你可以直接看成文件句柄f
for chunk in file_obj.chunks(): # file_obj你可以直接看成文件句柄f
f.write(chunk)
return render(request,'up.html')
CBV
FBV(Function Based View) 基于函数的视图
CBV(Class Based View) 基于类的视图
你在类中写了两个方法 一个叫get一个叫post,为什么前端get请求来就会触发get方法,post请求来就会触发post方法 如何实现的???
# CBV路由
url(r'^reg/',views.MyReg.as_view())
#CBV源码分析
@classonlymethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
self = cls(**initkwargs) # cls就是我们自己的写的MyReg类
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)
# 对象在查找属性或方法的时候 顺序是什么? 先从自己找 再从产生对象的类中找 再去类的父类中找...
"""也就意味着你在看源码的时候 你一定要牢记上面的话"""
return view
# views.py
from django.views import View
class MyReg(View):
def get(self,request):
return render(request,'reg.html')
def post(self,request):
return HttpResponse("我是MyReg类中post方法")
"""CBV最精髓的部分"""
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names: # 判断当前请求方式在不在默认的八个请求方式中
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
# handler = getattr(自己写的类产生的对象,'小写的请求方法(getpost)','获取不到对应的方法就报错')
# handler就是我们自己定义的跟请求方法相对应的方法的函数内存地址
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) # 在调用获取到的方法
django settings源码分析及实际应用(你可以不掌握 但是我希望你掌握思路)
django的配置文件有两个:
一个是暴露给用户可以自定义配置的
一个是默认的全局配置文件
用户指定了就用用户的
用户没有指定就用默认的
from django.conf import settings
settings = LazySettings()
class LazySettings(LazyObject):
def _setup(self, name=None):
# os.environ你可以把它看成是一个全局的大字典
settings_module = os.environ.get(ENVIRONMENT_VARIABLE) # 从大字典中取值
# settings_module = 'day59.settings'
self._wrapped = Settings(settings_module) # Settings('day59.settings')
class Settings(object):
def __init__(self, settings_module): # settings_module = 'day59.settings'
for setting in dir(global_settings): # 循环获取global_settings文件中所有的名字
if setting.isupper(): # 在判断名字是否是大写
# 如果是大写 利用反射 获取到大写的名字所对应的值 不停地添加到对象中
setattr(self, setting, getattr(global_settings, setting))
# store the settings module in case someone later cares
self.SETTINGS_MODULE = settings_module
mod = importlib.import_module(self.SETTINGS_MODULE) # 'day59.settings'
# from day59 import settings
# mod 指代的就是暴露给用户的配置文件模块名
for setting in dir(mod): # 循环获取暴露给用户配置文件中所有的名字
if setting.isupper(): # 判断是否是大写
setting_value = getattr(mod, setting) # 如果是大写 获取大写的变量名所对应的值
setattr(self, setting, setting_value) # 不停的给对象设置值
模板传值
def login(request):
n = 123
f = 12.12
s = '你妹的 真难'
l = [1,2,3,4,5,6]
d = {'username':'jason','password':[123,222,444]}
t = (1,2,3,4,5)
se = {1,2,3,4}
b = True
ctime = datetime.now()
file_size = 342384234234
w = '奥术 大师件 大事肯德 基按 实际对 拉 螺栓空当接 龙'
w1 = 'asdash ashd jkh sadas asdjjs had sjklad j a kjkjdsklas dkjsakldj dlsjakld '
w2 = 'he llow ord wqe asdsad sadsadsa dsadasds adasds adsadsadsada sdsad'
def func(xxx):
print(xxx)
print('嘿嘿嘿')
return '你妹的~'
class MyClass(object):
@classmethod
def get_cls(cls):
return 'cls'
@staticmethod
def get_func():
return 'func'
def get_self(self):
return 'self'
obj = MyClass()
sss = "<h1>下午上课 一脸懵逼</h1>"
sss1 = "<script>alert(123)</script>"
sss2 = "<a href='http://www.xiaohuar.com'>下午上课 需要激情</a>"
res = mark_safe(sss2) #从后端向前端传前端语句
xo = '123213213'
xo1 = 222
yyy = {'user_list':[1,'22',{'username':['jason','egon']}]}
return render(request,'login.html',locals())
#{#模板语法取值#}
{#<p>{{ n }}</p>#}
{#<p>{{ f }}</p>#}
{#<p>{{ s }}</p>#}
{#<p>{{ l }}</p>#}
{#<p>{{ d }}</p>#}
{#<p>{{ se }}</p>#}
{#<p>{{ t }}</p>#}
{#<p>{{ b }}</p>#}
{#<p>如果传递给前端一个函数名 会直接加括号调用 将函数的返回值展示到前端#}
{# 如果函数有参数 不好意思 django的模板语法 不支持给函数传参#}
{# {{ func }}#}
{#</p>#}
{##}
{##}
{#方法都不能传参#}
{#<p>{{ obj }}</p>#}
{#<p>{{ obj.get_cls }}</p>#}
{#<p>{{ obj.get_func }}</p>#}
{#<p>{{ obj.get_self }}</p>#}
{#<p>{{ l.1 }}</p>#}
{#<p>{{ l.3 }}</p>#}
{##}
{#<p>{{ d.username }}</p>#}
{#<p>{{ d.password }}</p>#}
{#<p>{{ d.password.1 }}</p>#}
传函数名的时候 会自动加括号调用函数 将函数的返回值展示在html页面上
注意:
django模板语法不支持函数传参
django模板语法在获取容器类型内部元素的值的时候 统一只采用 句点符(.)
#{#过滤器 #}
{#特点 会将|左边的当做过滤器的第一个参数 |右边的当前过滤器第二个参数#}
{#<p>{{ n|add:100 }}</p>#}
{#<p>{{ n|add:'abc' }}</p>#}
{#<p>{{ s|add:'sasahhdasda' }}</p>#}
{#<p>{{ l|length }}</p>#}
{#<p>{{ d|length }}</p>#}
{#<p>{{ file_size|filesizeformat }}</p>#}
{#<p>截取10个字符 三个点也算{{ w1|truncatechars:10 }}</p>#}
{#<p>截取10个字符 三个点也算{{ w|truncatechars:10 }}</p>#}
{#<p>安装空格截取单词 三个点不算{{ w1|truncatewords:6 }}</p>#}
{#<p>安装空格截取单词 三个点不算{{ w|truncatewords:6 }}</p>#}
{#<p>安装空格截取单词 三个点不算{{ w2|truncatewords:6 }}</p>#}
{#<p>{{ l|slice:'0:5' }}</p>#}
{#<p>{{ l|slice:'0:5:2' }}</p>#}
{#<p>{{ ctime|date:'Y-m-d' }}</p>#}
{#<p>{{ ctime|date:'Y年/m月' }}</p>#}
{#<p>{{ sss|safe }}</p>#}
{#<p>{{ sss1|safe }}</p>#}
{#<p>{{ res }}</p>#}
{#<p>{{ xo|default:'' }}#}
{#有值就拿值 没值就用后面默认的#}
{#</p>#}
(前端代码并不一定非要在前端写 你也可以在后端写好 传递给前端页面)
#前后端取消转义:
前端
|safe
后端
from django.utils.safestring import mark_safe
sss2 = "<a href='http://www.xiaohuar.com'>下午上课 需要激情</a>"
res = mark_safe(sss2)
模板语法的符号就两种:
{{}} 变量相关
{%%} 逻辑相关
#{#标签 if判断 for循环 等等#}
{#{% if xo %}#}
{# <p>xo有值</p>#}
{#{% else %}#}
{# <p>xo没有值</p>#}
{#{% endif %}#}
{#{% if xo %}#}
{# <p>xo有值</p>#}
{#{% elif xo1 %}#}
{# <p>xo1有值</p>#}
{#{% else %}#}
{# <p>去他大爷的</p>#}
{#{% endif %}#}
#for循环
内部提供了一个forloop对象
counter # 1开始
counter0 # 0开始
first
last
empty 当for循环对象是个空的时候 就会走empty下面的逻辑
{#{% for foo in l %}#}
{# {% if forloop.first %}#}
{# <p>这是我的第一次</p>#}
{# {% elif forloop.last %}#}
{# <p>这是最后一次了啊</p>#}
{# {% else %}#}
{# <p>嗨起来 大宝贝~</p>#}
{# {% endif %}#}
{#{% endfor %}#}
{#{% for foo in xo %}#}
{# <p>{{ forloop.counter }}:{{ foo }}</p>#}
{# {% empty %}#}
{# <p>你给我的对象是个空的没法进行for循环</p>#}
{#{% endfor %}#}
{#{% for foo in d.items %}#}
{# <p>{{ foo }}</p>#}
{#{% endfor %}#}
{##}
{#{% for foo in d.keys %}#}
{# <p>{{ foo }}</p>#}
{#{% endfor %}#}
{##}
{#{% for foo in d.values %}#}
{# <p>{{ foo }}</p>#}
{#{% endfor %}#}
{#<p>{{ yyy.user_list.2.username.1 }}</p>#}
{#{% with yyy.user_list.2.username.1 as dsb %}#} #起别名
{# <p>{{ dsb }}</p>#}
{# <p>{{ yyy.user_list.2.username.1 }}</p>#}
{#{% endwith %}#}
#自定义过滤器、标签
{% load my_tag %}
{#{{ 123|myplus:123 }}#}
{#只要思想不滑坡 方法总比困难多#}
{#{{ 123|myplus:'[1,2,3,4,5,6,7,8,]' }}#}
{#{% load my_tag %}#}
{% mysm 1 2 3 4 %}
{% if 0|myplus:123 %}
<p>有值</p>
{% endif %}
{% if mysm 1 2 3 4 %}
<p>有值</p>
{% endif %}
步骤:
1 在应用名下面新建一个templatetags文件夹(必须叫这个名字)
2 在该文件夹下 新建一个任意名称的py文件
3 在该py文件内 固定先写两行代码
from django.template import Library
register = Library()
#自定义的过滤器
@register.filter(name='myplus')
def index(a,b):
return a + b
#自定义的标签
@register.simple_tag(name='mysm')
def login(a,b,c,d):
return '%s/%s/%s/%s'%(a,b,c,d)
区别: 标签不能再if中使用
{% if 0|myplus:123 %} 可以用
<p>有值</p>
{% endif %}
{% if mysm 1 2 3 4 %} 不能用
<p>有值</p>
{% endif %}
模板的继承
#事先需要再模板中 通过block划定区域
{% block 区域名字 %}
{% endblock %}
#子板中使用
{% extends '模板的名字'%}
{% block 区域名字 %}
<h1>登录页面</h1>
{% endblock %}
#一个页面上 block块越多 页面的扩展性越高
通常情况下 都应该有三片区域
{% block css %}
{% endblock %}
{% block content %}
{% endblock %}
{% block js %}
{% endblock %}
子板中还可以通过
{{ block.super }} 来继续使用母版的内容
模板的导入
当你写了一个特别好看的form表单 你想再多个页面上都使用这个form表单
你就可以将你写的form表单当作模块的形式导入 导入过来之后 就可以直接展示
{% include 'good_page.html' %}