django路由分发、名称空间、虚拟环境、视图层之FBV与CBV及模板层

路由分发

django支持每个应用都可以有自己独立的路由层、静态文件、模板层。基于该特性多人开发项目就可以完全解耦合,之后利用路由分发还可以整合到一起

多个应用都有很多路由与视图函数的对应关系 这个时候可以拆分到各自的路由层中

使用路由分发之前 总路由直接干路由与视图函数的匹配
	path('index/', index)
使用路由分发之后 总路由只按照应用名分配匹配方向
	path('app01/', include('app01.urls'))

代码:

创建2个app,分别是app01和app02,并注册到settings.py里面.
app01:
urls.py:
from django.urls import path
from app01 import views
urlpatterns = [
    path('index/',views.index)
]
views.py:
from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
    return HttpResponse('from app01 index view')


app02:
urls.py:
from django.urls import path
from app02  import views
urlpatterns = [
    path('index/',views.index)
]
views.py:
from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
    return HttpResponse('from app02 index view')

django项目:
urls.py:
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    #路由分发
    path('app01/',include('app01.urls')),
    path('app02/',include('app02.urls')),
]

验证:
image
image

名称空间

路由分发之后 针对相同的别名能否自动反向解析出不同的应用前缀
	默认情况下是无法直接识别应用前缀的

如果想要正常识别区分有两种方式
	方式1:名称空间
 		总路由
    path('app01/', include(('app01.urls', 'app01'), namespace='app01')),
    path('app02/', include(('app02.urls', 'app02'), namespace='app02')),
    	反向解析(后端views.py)
        reverse('app01:index_view')
        reverse('app02:index_view')

	方式2:别名不冲突即可
     	多个应用别名不冲突可以用应用名作为别名的前缀
      	  path('index/', views.index, name='app01_index_view')
          path('index/', views.index, name='app02_index_view')

虚拟环境

项目1需要使用:django1.11 								 python38
项目2需要使用:django2.22 pymysql requests			      python38
项目3需要使用:django3.22 request_html flask urllib3		 python38
实际开发项目中我们只会给项目配备所需的环境,不需要的一概不配!!!

虚拟环境:能够针对相同版本的解释器创建多个分身 每个分身可以有自己独立的环境

pycharm创建虚拟环境:(每创建一个虚拟环境就相当于重新下载了一个全新的解释器)
命令行的方式: python -m venv pyvenv38

注意:python命令此处不支持多版本共存的操作 python27 python36 python38
    激活
        activate
    关闭
        deactivate

pip install --index-url http://mirrors.aliyun.com/pypi/simple/ django==1.11.11 --trusted-host mirrors.aliyun.com

视图层之必会三板斧

用来处理请求的视图函数都必须返回HttpResponse对象   完全正确
class HttpResponse:
    pass
return HttpResponse()

def render():
    return HttpResponse()
return render()

def redirect():
    redirect_class = 类(祖先有个类是HttpResponse)
    return redirect_class()
return redirect()

JsonResponse对象

from django.http import JsonResponse
# Create your views here.
def index_func(request):
    # 返回给浏览器一个json格式的字符串
    user_dict = {'name':'jason老师','age':18}
	return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
ps:以后写代码很多时候可能需要参考源码及所学知识扩展功能
class JsonResponse(HttpResponse):
	 def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs):
	     data = json.dumps(data, cls=encoder, **json_dumps_params)

JsonResponse主要序列化字典 针对非字典的其它可以被序列化的数据需要修改safe参数为False
代码:
项目urls.py
from app01 import views
 path('index/',views.index_func),

app01.views.py
from django.http import JsonResponse
# Create your views here.
def index_func(request):
    # 返回给浏览器一个json格式的字符串
    user_dict = {'name':'jason老师','age':18}
    # import json  #手动json序列化
    # user_json = json.dumps(user_dict,ensure_ascii=False)
    # return HttpResponse(user_json)
    return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})

image
image
image

视图层之request对象获取文件

form表单携带文件类型的数据需要做到以下几点
	1.method必须是post
	2.enctype必须是multipart/form-data
django后端需要通过request.FILES获取文件类型的数据

验证:

views.py:
def index_func(request):
    if request.method == 'POST':
        file_obj = request.FILES.get('file')
        print(file_obj.name)  # 获取文件名称
        print(file_obj)
        with open(r'%s' % file_obj.name,'wb') as f:
            for line in file_obj:  # 文件对象支持for循环一行行读取内容
                f.write(line)
    return render(request,'indexPage.html')

indexPage.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
    <h1>获取数据</h1>
    <form action="" method="post" enctype="multipart/form-data">
        <p>username:
            <input type="text" name="username">
        </p>
        <p>hobby:
            <input type="checkbox" name="hobby" value="basketball">篮球
            <input type="checkbox" name="hobby" value="football">足球
            <input type="checkbox" name="hobby" value="doublecolorball">双色球
        </p>
        <p>file:
            <input type="file" name="file">
        </p>
        <input type="submit" value="选我">
        <button>点我</button>
    </form>
</body>
</html>

image
image

视图层之FBV与CBV

FBV
	基于函数的视图
	def index(request):return HttpResponse对象

CBV
	基于类的视图
	 from django import views
  	 class MyLoginView(views.View):
        def get(self, request):
            return HttpResponse('from CBV get function')

        def post(self, request):
            return HttpResponse('from CBV post function')
	path('login/', views.MyLoginView.as_view())
	会自动根据请求方法的不同自动匹配对应的方法并执

urls:
# CBV
path('login/',views.MyLoginView.as_view())

# views.py
from django import views

class MyLoginView(views.View):
    def get(self,request):
        return HttpResponse('from CBV get function')

    def post(self,request):
        return HttpResponse('from CBV post function')

CBV源码剖析(重点)

1.从CBV的路由匹配切入
	path('login/',views.MyLoginView.as_view())
		1.类名点名字(名字的查找问题,先从当前对象找,找不到到对象所在类->父类)
		2.类名点名字并加括号调用(静态方法、绑定给类的方法)
2.函数名加括号执行优先级最高,项目一启动就会自动执行as_view方法
	path('login/',views.view) # CBV路由本质还是FBV
	#views.MyLoginView.as_view()--》views.view
3.浏览器地址访问login路由需要执行view函数
	1.产生我们自己编写类的对象
	2.对象调用dispatch方法(注意查找顺序)
4.研究父类中的dispatch方法
	获取当前请求方法并转小写 之后利用反射获取类中对应的方法并执行

1.首先在项目启动时就会执行一次as_view方法,通过对as_view方法源码的查看,我们可以得知是返回一个闭包函数名view。
'''
源码
@classonlymethod
    def as_view(cls, **initkwargs):
          ......
          def view(request, *args, **kwargs):
              ......
			  return self.dispatch(request, *args, **kwargs)
			  # self是我们自己定义的类产生的对象
    return view
'''
那么此时的urls.py文件中的配置就相当于,url('login/',views.MyLoginView.as_view()),这也说明了CBV与FBV在路由匹配本质是一样的。
2.在路由匹配成功后,会执行view函数会return self.dispatch(request, *args, **kwargs),也就是会执行dispatch函数。
'''
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            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)
'''
3.dispatch():中  通过 getattr 反射 拿到 子类的 get 或post 方法   给到handler 再返回执行,
          1.判断请求方法 是否存在于  http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

          2. 如果存在 就执行子类 中对应的方法(get,post.......)

          3.handler = getattr(self, request.method.lower(), self.http_method_not_allowed) 

               此时handler 就是一个 方法    return  handler (request ,*args,**kwargs) 加括号执行

'''
    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.
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)
 
 handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
 self:对象
 request.method.lower():字符串,对象属性
 self.http_method_not_allowed:默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError
'''

image

模板层(需要多练习理解)

"""
{{}}:主要与数据值相关
{%%}:主要与逻辑相关(循环、判断)

django的模板语法是自己写的 跟jinja2不一样
1.针对需要加括号调用的名字 django模板语法会自动加括号调用你只需要写名字就行
2.模板语法的注释前端浏览器是否无法查看的(##)
"""
1.模板语法传值
传值方式1:指名道姓的传  适用于数据量较少的情况       节省资源
return render(request, 'damo02.html', {'n1':name,'a1':age})
传值方式2:打包传值  适用于数据量较多的情况(偷懒)     浪费资源
  '''locals() 将当前名称空间中所有的名字全部传递给html页面'''
  return render(request, 'damo02.html', locals())

2.模板语法传值特性
	1.基本数据类型正常展示
	2.文件对象也可以展示并调用方法
	3.函数名会自动加括号执行并将返回值展示到页面上(不支持额外传参)
	4.类名也会自动加括号调用
	5.对象则不会
	ps:针对可以加括号调用的名字模板语法都会自动加括号调用

3.模板语法之过滤器(内置函数)
| 过滤器          | 用法                                     | 代码                            |
| --------------- | ---------------------------------------- | ------------------------------- |
| last            | 获取列表/元组的最后一个成员              | {{liast \| last}}               |
| first           | 获取列表/元组的第一个成员                | {{list\|first}}                 |
| length          | 获取数据的长度                           | {{list \| length}}              |
| defualt         | 当变量没有值的情况下, 系统输出默认值,    | {{str\|default="默认值"}}       |
| safe            | 让系统不要对内容中的html代码进行实体转义 | {{htmlcontent\| safe}}          |
| upper           | 字母转换成大写                           | {{str \| upper}}                |
| lower           | 字母转换成小写                           | {{str \| lower}}                |
| title           | 每个单词首字母转换成大写                 | {{str \| title}}                |
| date            | 日期时间格式转换                         | `{{ value| date:"D d M Y" }}`   |
| cut             | 从内容中截取掉同样字符的内容             | {{content \| cut:"hello"}}      |
| list            | 把内容转换成列表格式                     | {{content \| list}}             |
| add             | 加法                                     | {{num\| add}}                   |
| filesizeformat  | 把文件大小的数值转换成单位表示           | {{filesize \| filesizeformat}}  |
| `join`          | 按指定字符拼接内容                       | {{list\| join("-")}}            |
| `random`        | 随机提取某个成员                         | {list \| random}}               |
| `slice`         | 按切片提取成员                           | {{list \| slice:":-2"}}         |
| `truncatechars` | 按字符长度截取内容                       | {{content \| truncatechars:30}} |
| `truncatewords` | 按单词长度截取内容                       | 同上                            |

代码

urls.py:
path('func/', views.func),
views.py:
def func(request):
    # python基本数据类型
    f = 1.11
    i = 666
    s = 'hello ja son big ha'
    l = [11, 22, 33, 44, 55]
    d = {'name': 'jason', 'age':18}
    t = (11, 22, 33, 44)
    se = {11, 22, 33, 44}
    b = True
    # 文件对象
    f_obj = open(r'D:\pythonProject\djangoday04\djangoday04\wsgi.py','rb')
    # 函数
    def func1():
        print('上午很好 下午很好')
        return '真的很好'
    # 类
    class MyClass(object):
        def get_obj(self):
            return '绑定给对象的方法'
        @classmethod
        def get_cls(cls):
            return '绑定给类的方法'
        @staticmethod
        def get_static():
            return '静态方法'
    obj = MyClass()
	from datetime import datetime
	ctime=datetime.today()
    return render(request,'funcPage.html',locals())
	

funcPage.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
</head>
<body>
    <P>{{ f }}</P>
    <P>{{ i }}</P>
    <P>{{ s }}</P>
    <P>{{ l }}</P>
    <P>{{ d }}</P>
    <P>{{ se }}</P>
    <P>{{ b }}</P>
    <P>{{ t }}</P>
    <P>{{ f_obj }}</P>
    <P>{{ func1 }}</P>
    <p>{{ obj }}</p>
    <p>{{ obj.get_obj }}</p>
    <p>{{ obj.get_cls }}</p>
    <p>{{ obj.get_static }}</p>
    <P>{{ MyClass }}</P>
	<p>{{ i|add:10 }}</p>
    <p>{{  s|add:'baby'}}</p>
    <p>{{ l|length }}</p>
    <p>{{ s|truncatechars:5 }}</p>
    <p>{{ s|truncatewords:3 }}</p>
    <p>{{ ctime|date:'Y-m-d H:i:s' }}</p>

</body>
</html>

image
image

posted @   悠悠-winter  阅读(184)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示