python学习-Day53-django
目录
django
作业讲解
1.数据展示 2.给按钮附加功能 3.如何明确用户到底想要编辑哪条数据 在路由匹配中就应该获取到用户想要编辑的数据主键值 4.点击编辑按钮 应该展示当前数据的编辑页面 通过无名或者有名分组获取到用户想要编辑的数据主键值 获取对应的数据对象传递给页面 展示给用户看并提供编辑功能 5.编写删除功能 路由设计跟编辑功能一致
代码
def home(request): data_queryset = models.User.objects.filter() # [obj1,obj2,obj3] return render(request,'home.html',{'data_queryset':data_queryset}) def edit_data(request,edit_id): # 获取用户编辑的数据对象 edit_obj = models.User.objects.filter(id=edit_id).first() if not edit_obj: return HttpResponse('当前用户编号不存在') if request.method == 'POST': # 获取新的数据 username = request.POST.get('username') password = request.POST.get('password') # 修改原数据 方式1 # models.User.objects.filter(id=edit_id).update(name=username,pwd=password) # 修改原数据 方式2 edit_obj.name = username edit_obj.pwd = password edit_obj.save() # 重定向到展示页 return redirect('home_view') # 括号内也可以直接写反向解析的别名 不适用于无名有名反向解析 # 将待编辑的数据对象传递给页面展示给用户看 return render(request,'edit.html',{'edit_obj':edit_obj}) def delete_data(request,delete_id): # 获取想要删除的对象数据 edit_queryset = models.User.objects.filter(id=delete_id) if not edit_queryset: return HttpResponse(用户编号不存在) edit_queryset.delete() return redirect('home_view')
虚拟环境和django版本
虚拟环境
应用于多个项目,每个项目需要应用不同的模块、版本。
'虚拟环境就类似于一个纯净的python解释器环境,就类似于你重新下载一个python解释器' 在正常开发中 我们会给每一个项目配备一个该项目独有的解释器环境,该环境内只安装项目所需要的功能模块,项目用不到的一概不装,来避免加载资源时的消耗。
我们可以同时拥有多个虚拟环境
django版本区别
路由匹配不同
django1.X路由层使用的是url方法,而django2.X 和3.X版本中路由层使用的是path方法 # url()第一个参数支持正则 # path()第一个参数是不支持正则的 写什么就匹配什么 如果你习惯使用正则匹配那么也给你提供了其它方法 from django.urls import path, re_path ## 第一种re_path from django.conf.urls import url ## 第二种导入1.X的url re_path(r'^index/',index), url(r'^login/',login) '2.X和3.X里面的re_path就等价于1.X里面的url'
path内部的五种转换器
path('index/<int:id>/',index) # 将第二个路由里面的内容先转成整型然后以关键字的形式传递给后面的视图函数 def index(request,id): print(id,type(id)) return HttpResponse('index') str: 匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式 int: 匹配正整数,包含0。 slug: 匹配字母、数字以及横杠、下划线组成的字符串。 uuid: 匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。 path: 匹配任何非空字符串,包含了路径分隔符(/)(不能用?) '''除了有默认的五个转换器之外 还支持自定义转换器''' ## app01 path_converts.py class MonthConverter: regex='\d{2}' # 属性名必须为regex def to_python(self, value): return int(value) def to_url(self, value): return value # 匹配的regex是两个数字,返回的结果也必须是两个数字 ## app01 urls.py from django.urls import path,register_converter from app01.path_converts import MonthConverter # 先注册转换器 register_converter(MonthConverter,'mon') from app01 import views urlpatterns = [ path('articles/<int:year>/<mon:month>/<slug:other>/', views.article_detail, name='aaa'), ] ## app01 views.py from django.shortcuts import render,HttpResponse,reverse def article_detail(request,year,month,other): print(year,type(year)) print(month,type(month)) print(other,type(other)) print(reverse('xxx',args=(1999,04,'hello'))) # 反向解析结果/articles/1999/04/hello/ return HttpResponse('xxxx')
orm不同之处
模型层里面1.X外键默认都是级联更新删除的 但是到了2.X和3.X中需要你自己手动配置参数 models.ForeignKey(to='Publish',on_delete=models.CASCADE...)
视图层
视图函数返回值
注意:视图函数必须要返回一个HttpResponse对象
因为 :HttpResponse、render(其实继承的是HttpResponse)、redirect(其实继承的是HttpResponse)
# 视图函数必须返回一个HttpResonse对象 HttpResponse class HttpResponse(...): pass render def render(...): return HttpResponse(...) redirect def redirect(...): # 多继承
json序列化
'json格式的数据用于跨语言传输,编码就是把不用语言转成二进制,解码就是把二进制在转成各种不同的语言' 序列化就是通过json把python的语言转换成json字符串, 反序列化就是通过json把json字符串转换成python格式 # 后端中的序列化和反序列化: 序列化:json.dumps 反序列化:json.loads # 前端中的序列化和反序列化: 序列化:JSON.stringify() 反序列化:JSON.parse() # 注意: 前后端分离的项目,需要用到json格式的数据 混合项目开发项目,用不到json格式的数据
django框架通过对json进一步封装,方便了我们实现数据的序列和反序列化
JsonResponse对象
from django.http import JsonResponse def xxx(request): user_dict = {'username': '我好喜欢你!', 'password': '123'} l = [1, 2, 3, 4, 5, 6, 7, 8, 9, ] return JsonResponse(user_dict, json_dumps_params={ 'ensure_ascii': False}) # 当不写json_dumps_params={'ensure_ascii':False},汉字会被编码成unicode二进制 'json_dumps_params 表示 的是字典' return JsonResponse(l, safe=False) # 当不写safe=False时 ,汉字会被编码成unicode二进制。因为:safe默认序列化字典
import json from django.http import JsonResponse, HttpResponse class JsonResponse(HttpResponse): def __init__(self, data, json_dumps_params=None, **kwargs): data = json.dumps(data, **json_dumps_params)
为什么使用JsonResponse还不是原始的json模块 django对json序列化的数据类型的范围做了扩充
普通json对象
import json def xxx(request): json_str = json.dumps(user_dict,ensure_ascii=False) #ensure_ascii 默认的是True,当不写ensure_ascii=False时,汉字会被编码成unicode二进制 return HttpResponse(json_str)
form表单上传文件
form表单上传的数据中如果含有文件 那么需要做以下几件事 1.method必须是post 2.enctype必须修改为multipart/form-data 默认是application/x-www-form-urlencoded 3.后端需要使用request.FILES获取 # django会根据数据类型的不同自动帮你封装到不同的方法中
request其他方法
request.method request.POST request.GET request.FILES request.body 存放的是接收过来的最原始的二进制数据 request.POST、request.GET、request.FILES这些获取数据的方法其实都从body中获取数据并解析存放的 request.path 获取路径 request.path_info 获取路径 request.get_full_path() 获取路径并且还可以获取到路径后面携带的参数
FBV与CBV
CBV和FBV是一个概念的东西
FBV:function base views,顾名思义,基于视图的函数(views.py中的函数) CBV:class base views,同理,基于视图的类(views.py中的类)
FBV:基于函数的视图 url(r'^index/',函数名) CBV:基于类的视图 from django import views class MyLoginView(views.View): def get(self, request): return HttpResponse(from CBV get view) def post(self, request): return HttpResponse(from CBV post view) url(r'^ab_cbv/', views.MyLoginView.as_view()) 如果请求方式是GET 则会自动执行类里面的get方法 如果请求方式是POST 则会自动执行类里面的post方法
CBV源码剖析
1.切入点:路由匹配 类名点属性as_view并且还加了括号 as_view可能是普通的静态方法 as_view可能是绑定给类的方法 2.对象查找属性的顺序 先从对象自身开始、再从产生对象的类、之后是各个父类 MyLoginView.as_view() 先从我们自己写的MyLoginView中查找 没有再去父类Views中查找 3.函数名加括号执行优先级最高 url(r'^ab_cbv/', views.MyLoginView.as_view()) 项目已启动就会执行as_view方法 查看源码返回了一个闭包函数名view def as_view(cls): def view(cls): pass return view url(r'^ab_cbv/', views.view) # CBV与FBV在路由匹配本质是一样的!!! 4.路由匹配成功之后执行view函数 def view(): self = cls() return self.dispatch(request, *args, **kwargs) 5.执行dispatch方法 需要注意查找的顺序!!! def dispatch(): handler = getattr(self, request.method.lower()) return handler(request, *args, **kwargs) 查看源码也可以修改 但是尽量不要这么做 很容易产生bug
模板语法传值
django提供的模板语法只有两个符号 {{}}:主要用于变量相关操作(引用) {%%}:主要用于逻辑相关操作(循环、判断) 1.传值的两种方式 # 传值方式1:指名道姓的传 适用于数据量较少的情况 节省资源 # return render(request, 'ab_temp.html', {'name':name}) # 传值方式2:打包传值 适用于数据量较多的情况(偷懒) 浪费资源 '''locals() 将当前名称空间中所有的名字全部传递给html页面''' return render(request, 'ab_temp.html', locals()) 2.传值的范围 基本数据类型都可以 函数名 模板语法会自动加括号执行并将函数的返回值展示到页面上 不支持传参(模板语法会自动忽略有参函数) 文件名 直接显示文件IO对象 类名 自动加括号实例化成对象 对象名 直接显示对象的地址 并且具备调用属性和方法的能力 # django模板语法针对容器类型的取值 只有一种方式:句点符 既可以点key也可以点索引 django内部自动识别 {{ data1.info.pro.3.msg }}