Django补充3

发布时间 2023-11-29 20:47:08作者: 拆尼斯、帕丁顿

Django分了很多层

  路由曾

  视图层 请求对象和响应对象

  模板曾

  模型层:orm:表单,多表,各种查询

  ajax forms组件  分页器  cookie session   中间件  auth

——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————视图层响应对象

  响应本质都是HttpReponse

  HttpReponse---字符串

  render-------放个模板   模板渲染是在后端完成的

  js代码实在客户端浏览器里执行的   

  模板语法是在后端执行的

  redirect---------重定向

  -字符串参数部分是空的

  状态码是  3开头   status=201

  JsonResponse   json格式数据

    return JsonResponse({name:lqz,age:19})

      本质是把传入的字典或列表(必须指定safe =False),使用 json序列化得到 json格式字符串----最终做成 HttpResponse返回给前端----- 如果想给 json序列化的时候,传参数,必须使用  json_dumps_params字典传入

      如果想往响应头中写数据---需要传headers = {‘xx’:‘xx’}

 

    JsonResponse源码分析

    return JsonResponse({name:lqz,age:19})       注:如果是列表   那么safe要改成 False  否则会抛异常

触发 JSonResponse的__init__ ----------{name:lqz,age:19} 给了data  

def __init__(self, data, encoder=DjangoJSONEncoder,

safe=True,json_dumps_params=None, **kwargs):

   如果传入的四字典
   safe是True,后面是False,条件不符合,内部就不会走
  if safe and not isinstance(data, dict):
    raise TypeError(
      'In order to allow non-dict objects to be serialized set the '
      'safe parameter to False.'
    )
  if json_dumps_params is None: # 条件符合
    json_dumps_params = {}
     kwargs是字典---》setdefault--》有则修改,无则新增
    kwargs.setdefault('content_type', 'application/json')
     核心---》把字典转成json格式字符串,赋值给data
  data = json.dumps(data, cls=encoder, **json_dumps_params)
   super().__init__ 调用父类的 __init__ 完成实例化---》HttpResponse的对象
  return HttpResponse(data,**kwargs)
  super().__init__(content=data, **kwargs)

isinstance 

  isinstance(对象,类)判断这个对象,是不是这个类的对象

 

CBV和FBV

  FBV:基于函数的视图

        之前的都是FBV

    CBV写法 

  from django.views import View

  class UserView(View):

    写方法---跟请求方式同名的方法

  def get(self,request,*args,**kwargs)

      必须返回四件套

路由配置:

  path('index/', 视图类名.as_view())    as_view是类的绑定方法

 

执行流程--》源码分析
path('index/', index),--->请求来了,路由匹配成功会执行 index(request,)
path('index/', UserView.as_view()),
  1 入口:路由---》as_view来开始
  -请求来了,路由匹配成功---》执行---》UserView.as_view()(request)
  -需要看as_view()执行结果是什么--》view--》代码如下
    def view(request, *args, **kwargs): # 方法,可以加括号调用
      return self.dispatch(request, *args, **kwargs)
  -本质就是在执行 view(request)
  -本质在执行---》self.dispatch(request, *args, **kwargs)
  -去类(UserViwe类中找,找不到,去父类View)中找dispatch,代码如下
  def dispatch(self, request, *args, **kwargs):
     request当次请求的请求对象,取出请求方式【假设是get请求】,转成小写 'get'
     http_method_names = ['get', 'post', 'put']
     条件成立,执行if内部代码
    if request.method.lower() in self.http_method_names:
      getattr:反射---》通过字符串去对象中取属性或方法
       self是谁的对象? 是View这个类的对象,这个是视图类UserView的对象
       取出来的handler 是 UserView这个类的get方法
      handler = getattr(self, 'get')
    else:
      handler = self.http_method_not_allowed
     handler是 UserView这个类的get方法
     get(request)---》触发UserView这个类的get方法---》真正执行原来视图函数的内容
     最终返回
    return handler(request, *args, **kwargs)

 总结:写cbv,只需要在视图类中写跟请求方式同名的方法即可--》不同请求方式,就会执行不同的方法

 

关于类中self是谁的问题

  

class Animal:
  def run(self):
     这个self,是谁调用,就是谁
    print(type(self))
    print(self.name, '走路')


class Person(Animal):
  def __init__(self, name):
    self.name = name

class Dog(Animal):
  def __init__(self, name,age):
    self.name = name
    self.age=age
 p = Person('lqz')
 p.run() #

dog=Dog('小奶狗',6)
dog.run()

 self 是谁调用。self就是谁,不能只看是哪个类

 

上传文件

关于模板查找路径是配置文件中
TEMPLATES --->'DIRS': [os.path.join(BASE_DIR, 'templates')]


## python
class FileView(View):
  def get(self,request):
    return render(request,'file.html')
  def post(self,request):
     拿出文件对象
    my_file=request.FILES.get('myfile')
    print(type(my_file)) 

  

 my_file=request.FILS.egt('myfile')     

        通过 print(type('my_file'))查看类型

    #django.core.files.uploadedfile.InMemoryUploadedFile 跟之前用的文件对象不一样但是,它应该继承了文件
    from django.core.files.uploadedfile import InMemoryUploadedFile
   

     1 保存 2 取出文件名字
     my_file.save() #找了一顿,没有,所以不能使用(save)快捷保存方式,需要自己写保存
    print(my_file.name)    看neme属性是不是 这个文件的名字

    3-xxxxx.md
     自己写保存,放在项目根路径下
    with open(my_file.name,'wb') as f:
      for line in my_file:
        f.write(line)
    return HttpResponse('上传成功')

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>

</head>
<body>
<form action="" (默认当前地址)method="post" enctype="multipart/form-data"> --编码格式
  <input type="file" name="myfile">
  <br>
  <input type="submit" value="提交">  目前记得注掉 srf
</form>
</body>
</html>

此时点post提交 会报错

需要写  def post(self,request):

    拿出文件

    my_file=request.FILS.egt('myfile')     

        通过 print(type('my_file'))查看类型

 

模板 templease.html

模板在浏览器中运行不了,因为它有模板语法  浏览器解析不了模板语法

必须在后端渲染完成(替换完成) 变成纯粹的html,css,js

这种在后端会被渲染 类python语法 它叫模板语法   django中它又叫 dtl: django template  language

 

django模板修改的视图函数

了解####
# ================================django模板修改的视图函数
from django.template import Template,Context
now=datetime.datetime.now()
# 内部打开了这个模板---》读出所有内容,实例化得到了t对象
t=Template('<html><body>现在时刻是:<h1>{{current_date}}</h1></body></html>')
# #t=get_template('current_datetime.html')
c=Context({'current_date':str(now)})
html=t.render(c)
return HttpResponse(html)

 

另一种写法(推荐)
  import datetime
  now=datetime.datetime.now()
  return render(req, 'current_datetime.html', {'current_date':str(now)[:19]})


# 总结:咱们之前这么写
  render(request,'模板名字',context={key:value,key1:value})
  本质是:
  t=Template('<html><body>现在时刻是:<h1>{{current_date}}</h1></body></html>')
  c=Context({'current_date':str(now)})
  html=t.render(c) # 返回是字符串
  HttpResponse(html)

 

页面静态化#######
-把什么页面,做成静态化的?---》访问量高的页面
-目的:提高项目并发量,响应速度和效率就高了
-把首页静态化

def index(request):
# 1 判断 cache文件夹下有没有 index.html 纯静态页面
# 2 如果没有:干下面的事
# books = Book.object.all()
# t = Template('<html><body>现在时刻是:<h1>{{current_date}}</h1></body></html>')
# # #t=get_template('current_datetime.html')
# c = Context({'books':books})
# html = t.render(c)
#保存到某个文件中 cache文件夹下 index.html
# 3 如果有那个文件,打开文件---》HttpReponse
books=Book.object.all()
return render(request,'index.html',{books:books})

 

模板语法###
变量:{{ 变量名 }} 字典,列表,对象 通过.拿到属性或方法
字典:dic.name--->这不是python语法 dic['name'] dic.get('name')
列表:list.2--->这不是python语法 list[0]
对象:person.name---->是python语法
person.run---->不是python语法,会自动加括号,把run的返回值放在模板中 person.run()
不支持传参数

1 深度查询 用句点符
2 过滤器
3 标签:{{% % }}

 

 

内置过滤器####
# render(request,'index.html',{now:当前时间对象})
{{ now | date:"Y-m-d H:i:s" }}

safe 把标签字符串 渲染成标签
'<a href=""></a>'--->渲染成标签

dtl是不存在xss攻击的?跨站脚本攻击
# 后端:
s='
<script>
alert(1)
</script>
'
render(request,'index.html',{s:s})
#模板
{{s}} 不会渲染成标签,没有xss攻击
我们知道s是安全的,我们可以使用safe标签,把它渲染成 真正的标签

 

模板导入 include ,写好一段前端代码块,以后别的页面要用,直接 {% include 'little.html' %}
#### little.html 这个是以后要导入的代码块
<div>
  <h1>我是广告</h1>
  <p>亚洲最大同性交友平台</p>
  <p>名字是:{{ name }}---诚信交友</p>
</div>

#### 在index.html 或者 login.html中想用
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>

</head>
<body>

<div>
  {% include 'little.html' %} # 这个位置引入即可,但是如果little中有模板语法,需要如下
</div>
<hr>
<div>
  我是div222
</div>

</body>
</html>

### python代码:
def index(request):
return render(request, 'index.html', {'name': '彭于晏'})

-1 {{变量}} {{变量.取值}}
-2 {%for%}
-3 {%if%}
-5 内置过滤器 :data,length。。。
-6 include
-7 extends使用

————————————————————————————————————————————————————————————————————————————————————————————————

0 cbv执行流程,self问题(写代码试试) ---》整理到笔记中

cbv执行流程: 请求进入——进行路由匹配——如果匹配到对应的路由,内部就会执行XXXview.as_view()(request),因为XXXview中没有as_view()这个方法,所以去它的父类View中找,内部开始执行,View的as_view内部的view闭包函数,闭包函数执行了self.dispatch,这里的self是在XXXview类实例化的对象,在self.dispatch中通过反射找到同名的方法,然后执行,把request传入。

 



# 1 你自己写一个类,实现JsonResponse 功能,不需要传safe=False,无论字典或列表,都能完成序列化返回给前端


# 2 四种情况,在响应头返回数据 xx=xx

 

# 3 绑定给类的方法,类来调用,对象可以调用吗?如何用

类的绑定方法可以用对象来调用

class Person:
  def __init__(self,name,age):
    self.name = name
    self.age = age
@classmethod
def test(cls):
  print(cls)
  print('类的绑定方法')

p = Person('jiayi',20)
#对象可以调用类的绑定方法,也是把该对象的类传过去
p.test()

 

 

# 4 绑定给对象的方法,对象来调用,类可以调用吗?如何用

能来调用,只不过是方法中需要几个参数就要传递几个参数,包括self形参也需要自己传递


class Student():
school = 'SH'

def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender

"""绑定给对象来调用的"""

def tell_info(self, username, password):
print("name:%s age:%s gender:%s %s %s" % (self.name,
self.age, self.gender, username, password))

"""默认情况下,在类内部写方法是绑定给对象的,就有对象来调用,
就会自动来传递参数"""


stu = Student('ly', 20, 'male')
# 谁来调用方法就是谁,对象自己
stu.tell_info('kevin', 123)
# name:ly age:20 gender:male kevin 123

# 5 写个图片上传功能,图片保存在根路径media文件夹下,上传成功直接在前端显示出上传的图片
-开启media的访问


# 6 建个表---》插入100条数据---》写个页面,for循环把100条数据显示在页面上
-只要用户访问---》就会去查
-做成静态化


# 7 (能做就做)自定义一个过滤器---》实现
数据有个表---》content字段---》别人存入了一些敏感词

它**

高级一些:关键词放到一个列表中,可以随时增加,不需要重启项目---》数据可以放在数据库中