ORM之视图层

小白必会三板斧

## 视图函数必须返回一个HttpResponse对象

from django.shortcuts import HttpResponse,render,redirect

分析:为什么说视图函数必须返回一个HttpResponse对象

HttpResponse # 返回普通字符串(不能返回文件)
class HttpResponse: # 查看源码,HttpResponse是一个类,加括号调用实例化出一个对象
       pass
   
render # 查看源码(调用render函数,返回HttpResponse(...))
def render(...):
       return HttpResponse(...)

redirect
def redirect(...)
  # redirect_class是HttpResponse子类
  return redirect_class(...)
   

JsonResponse(前后端数据交互)

将数据在后端转成json格式再提交到前端

# 不同编程语言之间如何交互???
json格式数据
   'jaso格式的标志双引号'
   
"""
前后端不分离
django写项目(前端直接使用模板层及模板语法)
前后端分离
django写项目(前端使用其他框架和语言)

python中如何序列化反序列化
dumps()
loads()
js中如何序列化反序列化
JSON.stringfy()
JSON.parse()
"""

在python中我们可以使用json模块将数据转成json格式(json格式支持其他语言)
import json

d = {'username': 'jason老师', 'pwd': 123, 'hobby': [111, 222, 333]}
json_str = json.dumps(d)  
print(json_str) # 序列化默认会对中文字符做转码
{"username": "jason\u8001\u5e08", "pwd": 123, "hobby": [111, 222, 333]}

我们可以查看dumps源码文件,将ensure_ascii参数改为False(默认为True),就不会对中文字符进行处理
json_str = json.dumps(d,ensure_ascii=False)  # 这样就可以正常显示了
{"username": "jason老师", "pwd": 123, "hobby": [111, 222, 333]}



--------------------------------------------------------------------

   
# 在django项目中,django给我们提供了更加简便的方法,不需要我们自己序列化

from django.http import JsonResponse

d = {'username': 'jason老师', 'pwd': 123, 'hobby': [111, 222, 333]}
l = [111,2232,454,555,666]


def index(request):
   return JsonResponse(d) # 序列化默认会对中文字符做转码(这里也会出现转码问题)
   # 查看源码                  
return JsonResponse(d, json_dumps_params={'ensure_ascii': False})
                       
   # 列表序列化,直接传会报错,需要修改一个默认参数safe=False
   return JsonResponse(l,safe=False)
                       

form表单提交文件

# 前提条件
<form action="" method="post" enctype="multipart/form-data" >

</form>
'''
action=""方法,
1.不填会将post请求直接转到当前界面
2.可以填后缀,会自动拼接ip和端口
3.全填

method="post" 请求方式

'''
1.method必须是post
2.enctype参数必须是multipart/form-data

request.POST无法获取到文件类型的数据(只能获取普通键值对数据)
   request.FILES获取文件类型的数据

前端获取文件数据
<input type="file" name="file">  只能获取一个(上传)
   <input type="file" name="file" multiple>  可以一次性获取多个

后端获取文件数据
request.FILES.get()   # 默认获取最后一个数据
   request.FILES.getlist()    #获取全部数据
   
   
-----------------------------------------------------------------------------------------

简单逻辑代码

# 后端
def get_file(request):
   if request.method == "POST":
       data = request.FILES.get("file")
       with open(data.name, 'wb') as f:
           for line in data :
               f.write(line)

   return render(request,'get_file.html')

# 前端

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
   <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
   <div class="container">
       <form action="" method="post" enctype="multipart/form-data">
           <input type="file" name="file">

           <p>
              <input type="submit">
           </p>
       </form>

   </div>

</body>
</html>

FBV与CBV

FBV 基于函数的视图
def index(request):
       return HttpResponse(...)
   
CBV 基于类的视图
# 视图函数即可以是函数也可以是类
from django.views import View
   class MyLogin(View):
       def get(self, request):
           return HttpResponse('get请求')
       def post(self, request):
           return HttpResponse('post请求')
   url(r'^login/', views.MyLogin.as_view())
   """CBV会自动判断当前请求方法并自动匹配类中的方法执行"""

CBV源码剖析

"""
函数名或者方法名遇到括号执行优先级最高

对象查找属性或方法的顺序
永远都是先从自己身上找
然后去产生对象的类中找
再去类的父类中找 如果都没有才会报错

闭包函数
定义在函数内部并且使用了外层函数名称空间中的名字

回去记得复习面向对象反射
"""

-----------------------------------------------------------------------------------------


FBV与CBV在路由匹配上本质其实是一样的
都是正则表达式对应函数名
url(r'^login/', views.MyLogin.as_view())
   
   着手点
   '''
  MyLogin是我们自定义的类,看到类名.()的方式(MyLogin.as_view()),我们可以猜测as_view要么是绑定给类的方法,要么是静态方法,我们可以通过查看源码的方式进行分析
  '''
    @classonlymethod # 绑定给类的方法,相当于@classmethod,类来调用会将本身当做第一个参数自动传入
   def as_view(cls, **initkwargs):
        def view(request, *args, **kwargs):
           # cls使我们自定义的类 MyLogin
           self = cls(**initkwargs)  # 产生一个MyLogin类的对象 obj
           return self.dispatch(request, *args, **kwargs)
        return view
# 这时候views.MyLogin.as_view()就相当于views.view,这就跟我们熟悉的比较相似了
   
   def view(request, *args, **kwargs):
       return self.dispatch(request, *args, **kwargs)
   
       
   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)
           # getattr = (自己定义类的对象,‘请求方式’,前面两个没找到,才会走第三个)
           # handler = 'get' #getattr反射,通过字符串操作对应的函数
       else:
           handler = self.http_method_not_allowed
       return handler(request, *args, **kwargs)

模板语法传值

如何给html文件传值
# 两种方式
1.字典挨个指名道姓(以字典的形式)
  节省系统资源
   2.locals()全部传递
  节省人力资源  # 学习阶段就使用这种方式
 
1.python基本数据类型全部支持模板语法传值

2.在django中模板语法取值只能使用一种方式(句点符.) #数据的类型可以看作是字典套列表
# 相较于jinja2模块取值方式
  1.dict.get('name'
       2.dict['name']
       3.dict.name
       在django中模板语法取值只支持第三种
       
3.针对函数名模板语法传值之后会自动加括号执行将返回值渲染到页面上
# 将函数名传到前端会直接加括号调用函数

4.针对类名和对象名模板语法传值之后都会先尝试加括号调用
类名加括号会产生对象
   对象加括号不符合正常的调用方式 还是对象本身
  但是会触发产生该对象类中的__call__方法(建议不要书写__call__方法)
   
"""
小总结
django模板语法不支持函数传参
当需要引用变量名的时候使用双大括号 {{}}
"""
接收值的两种方式
{{}}  # 跟变量名相关
{%%}  # 跟功能逻辑相关

模板语法之过滤器

# 相当于python的内置函数

{#<p>过滤器:(|) 将管道符左边的数据当做第一个参数传入过滤器中如果需要第二个参数 则名称后冒号</p>#}
   
<p>统计长度:{{ l|length }}</p>
   
<p>加法运算:{{ i|add:123 }}</p>
   
<p>默认值:{{ b|default:'布尔值为False' }}</p>
   
<p>时间格式:{{ ctime|date:'Y-m-d H:i:s' }}</p>
   
<p>截取字符(包含三个点):{{ ss|truncatechars:10 }}</p>
   
<p>截取单词(不包含三个点,以空格为分隔符):{{ ss|truncatewords:3 }}</p>
   
<p>文件大小(格式化文件大小):{{ file_size|filesizeformat }}</p>
   
# 如何在后端传值是采用前端文件格式,且能够被前端识别
   # 两种方式
   1.前端转义
<p>转义:{{ s1|safe }}</p>
   # 后端用前端格式传值,需要前端在接收数据时添加safe参数进行转义,才能够被识别

2.在后端转义(使用模块)
   from django.utils.safestring import mark_safe
   s2 = "<script>alert(123)</script>"
   res = mark_safe(s2)
   
   两种范式效果都是一样的

模板语法之标签

<p>标签:其实就是流程控制 if判断  for循环</p>  # django支持写关键字按tab键补全
   
'''
forloop只有第一次循环和最后一次循环时是Ture,用来标志第一次循环和最后一次循环,其他都是False
'''
   
{% for foo in s %}
  {% if forloop.first %}
       <p>这是第一次循环</p>
  {% elif forloop.last %}
       <p>这是最后一次</p>
  {% else %}
       <p>继续!!!</p>
  {% endif %}
  {% empty %}
       <p>传递过来的数据是空的</p>
{% endfor %}

 

posted @ 2021-12-07 19:29  一叶松  阅读(110)  评论(0编辑  收藏  举报