django框架之视图系统和路由系统

内容回顾:

    1. tags
        1. for循环
            {% for name in name_list %}
                {{ name }}
            {% endfor %}
            
            {% for name in name_list %}
                {{ name }}
            {% empty %}
                空空如也
            {% endfor %}
            
            forloop   {  }
                forloop.counter      当前循环的索引值 从1开始
                forloop.counter0     当前循环的索引值 从0开始
                forloop.revcounter   当前循环的索引值(倒序) 到1结束
                forloop.revcounter0  当前循环的索引值(倒序) 到0结束
                forloop.first         单前循环是否是第一次循环  布尔值
                forloop.last         单前循环是否是最后一次循环  布尔值
                forloop.parentloop   当前循环的外层循环
                
            上台阶,可以一次上1个台阶,可以上2个台阶,可以上3个台阶。问有n个台阶,有多少种走法?
        2. if判断
            {% if 条件 %}
                操作
            {% endif %}
            
            {% if 条件 %}
                操作
            {% else %}
                其他操作
            {% endif %}
            
            {% if 条件 %}
                操作
            {% elif 条件 %}
                不同操作
            {% else %}
                其他操作
            {% endif %}
            注意事项:
                1. 不能连续判断 a > b > C   用and连接
                2. 不支持算数运算  +-*/ 用filter
        3. csrf_tokrn
            使用:在form表单中使用
            效果:添加了一个隐藏的input标签,标签名叫csrfmiddlewaretoken 值:随机字符串
            作用:提交POST请求
        4. 注释  {# 注释部分 #}
        
    2. 母板和继承
        1.为什么要用母板和继承:
            很多页面有重复或相似的代码,减少代码的重复和修改方便才用母板和继承
        2.具体步骤:
            1. 创建一个母板,‘base.html‘ 将多个页面的重复代码提取出来
            2. 在母板中定义多个block,来区分不同页面的不同内容
            3. 在子页面中继承母板  {% extends ‘base.html‘ %}
            4. 在block中写自己页面独特的内容
            
        3. 注意事项
            1. {% extends ‘base.html‘ %} 写在第一个行
            2. {% extends ‘base.html‘ %}  base.html加上引号  不然当做是变量
            3. 通常定义多个block,还有一个page-css 和 page-js
    3. 组件
        将一小部分的HTML代码写在一个模板中。———》 组件
        在其他的页面中 {% include ‘nav.html‘ %}
        
    4. 静态文件的内容
        {% load static %}
        "{% static ‘css/mycss.css‘ %}"    ——》 /static/css/mycss.css
        
        {% get_static_prefix %}  —— 》  /static/
        
        "{% get_static_prefix %}css/mycss.css"
            
            
    5. 自定义simple_tag 和 inclusion_tag

今日内容:

视图系统

视图:

一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。

响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。

简单的说我们通常在views写的就是视图。只不过我们写的是基于函数的视图,即FBV。把视图写成基于类的,就是CBV啦。

这是FBV

def add_publisher(request):
    new_name = ‘‘
    err_msg = ‘‘
    if request.method == ‘POST‘:
        new_name = request.POST.get(‘publisher_name‘)
        if new_name:
            publisher_obj_list = models.Publisher.objects.filter(name = new_name)
            if not publisher_obj_list:
                models.Publisher.objects.create(name = new_name)
                return redirect(‘/publisher/‘)
            else:
                err_msg = ‘数据已存在‘
        else:
            err_msg = ‘数据不能为空‘
    return render(request, ‘add_publisher.html‘, {‘old_name‘: new_name, ‘err_msg‘: err_msg})

改成这样就是CBV啦:

from django.views import View
class Addpublisher(View):
    def get(self,request):
        return render(request, ‘add_publisher.html‘)
    def post(self,request):
        new_name = request.POST.get(‘publisher_name‘)
        publisher_obj_list = models.Publisher.objects.filter(name=new_name)
        if not publisher_obj_list:
            models.Publisher.objects.create(name=new_name)
            return redirect(‘/publisher/‘)
        else:
            err_msg = ‘数据已存在‘
            return render(request, ‘add_publisher.html‘,{‘err_msg‘:err_msg})

往深入的讲,他其实是实现了View中的dispatch方法,所以这个dispatch我们可以自己定义:让他去执行父类的dispatch方法:

from django.views import View
class Addpublisher(View):
    def dispatch(self, request, *args, **kwargs):      print(‘处理请求之前‘)
        ret = super().dispatch(self, request, *args, **kwargs)
        print(‘处理请求之后‘)

def get(self,request):     print(‘这是get请求‘)
        return render(request, ‘add_publisher.html‘)
    def post(self,request):
        new_name = request.POST.get(‘publisher_name‘)
        publisher_obj_list = models.Publisher.objects.filter(name=new_name)
        if not publisher_obj_list:
            models.Publisher.objects.create(name=new_name)
            return redirect(‘/publisher/‘)
        else:
            err_msg = ‘数据已存在‘
            return render(request, ‘add_publisher.html‘,{‘err_msg‘:err_msg})

其实这个dispatch相当于装饰器的作用。

简版的流程:
                AddPublisher.as_view()   ——》 view 函数
                当请求来的时候才执行view
                view中执行:
                    1. 先实例化AddPublisher,给self
                    2. 执行self.dispatch()  
                        self 有dispatch 就执行自己的
                             没有就是执行 父类(View)的dispatch方法
                    3. dispatch中执行:
                        先通过反射获取到AddPublisher中定义get或者post方法。
                        执行get或者post方法 返回httpresponse对象
                    4. view接收到dispatch的返回值——httpresponse对象
                    5. view返回httpresponse对象

接下来我们给视图加上装饰器:

  装饰器的作用是在函数之前或者之后做一些操作,并且不改变函数的调用方式。

  

def wrapper(func):
    def inner(*args,**kwargs):
        now = time.time()
        ret = func(*args,**kwargs)
        print(‘函数执行的时间是{}‘.format(time.time()-now))
        return ret
    return inner
#增加出版社
@wrapper
def add_publisher(request):
    new_name = ‘‘
    err_msg = ‘‘
    if request.method == ‘POST‘:
        new_name = request.POST.get(‘publisher_name‘)
        if new_name:
            publisher_obj_list = models.Publisher.objects.filter(name = new_name)
            if not publisher_obj_list:
                models.Publisher.objects.create(name = new_name)
                return redirect(‘/publisher/‘)
            else:
                err_msg = ‘数据已存在‘
        else:
            err_msg = ‘数据不能为空‘
    return render(request, ‘add_publisher.html‘, {‘old_name‘: new_name, ‘err_msg‘: err_msg})

接下来我们给CBV加上装饰器:

from django.views import View
from django.utils.decorators import method_decorator
class Addpublisher(View):
    # def dispatch(self, request, *args, **kwargs):
    #     return super().dispatch(self, request, *args, **kwargs)

    @method_decorator(wrapper)  #为get请求加上装饰器
    def get(self,request):
        return render(request, ‘add_publisher.html‘)
    def post(self,request):
        new_name = request.POST.get(‘publisher_name‘)
        publisher_obj_list = models.Publisher.objects.filter(name=new_name)
        if not publisher_obj_list:
            models.Publisher.objects.create(name=new_name)
            return redirect(‘/publisher/‘)
        else:
            err_msg = ‘数据已存在‘
            return render(request, ‘add_publisher.html‘,{‘err_msg‘:err_msg})

给dispatch方法加上装饰器,get和post请求就都加上装饰器了。

如果要在类上加装饰器,就要这样写@method_decorator(wrapper,name=‘get‘)

                @method_decorator(wrapper,name=‘post‘)

 request对象:

    request属性:
            request.method  请求方式 GTE POST
            request.GET      ——》 字典  URL上传的参数
            request.POST     ——》 字典  form表单传的参数

    request.FILES    上传的文件

   request.path_info     返回用户访问url,不包括域名

    request.body            请求体,byte类型 request.POST的数据就是从body里面提取到的(gest请求没有请求体)

  我们来写一个上传的实例

views中的代码:

def upload(request):
    if request.method == ‘POST‘:
        print(request.FILES)
        upload_obj = request.FILES[‘file_name‘]
        with open(upload_obj.name,‘wb‘)as f:
            for chunk in upload_obj.chunks():
                f.write(chunk)
    return render(request,‘upload.html‘)

html的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action=""method="post" enctype="multipart/form-data">
    {% csrf_token %}
    <input type="file" name="file_name" >
    <button>提交</button>
</form>
</body>
</html>

request方法:

  request.path_info        url路径不包含url参数和域名

  request.get_full_path()  url路径包含url参数

  request.get_host()    获取ip和端口

Response对象

response方法:

1. HttpResponse 类  字符串
            2. render        返回一个HTML页面
            3. redirect     跳转  重定向  Location:/index/

response属性:

  HttpResponse.content:响应内容

  HttpResponse.charset:响应内容的编码

  HttpResponse.status_code:响应的状态码

  

JsonResponse对象:

我们先写一个json数据:

def json_data(request):
    import json
    data = {‘name‘:‘alex‘,‘age‘:73}
    return HttpResponse(json.dumps(data))

然后我们在试一试django为我们提供的方法:

from django.http import JsonResponse
def json_data(request):
    # import json
    data = {‘name‘:‘alex‘,‘age‘:73}
    # return HttpResponse(json.dumps(data))
    return  JsonResponse(data)

我们来说一说这两者的区别:

  如果浏览器拿到的是JsonResponse的格式会自动帮你解析。而且JsonResponse只会返回字典,如果要返回列表,JsonResponse(data,safe=False)

路由系统:

基本格式:

urlpatterns = [
     url(正则表达式, views视图,参数,别名),]
urlpatterns = [
    url(r‘^articles/2003/$‘, views.special_case_2003),
    url(r‘^articles/([0-9]{4})/$‘, views.book),
    url(r‘^articles/([0-9]{4})/([0-9]{2})/$‘, views.book),
    url(r‘^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$‘, views.book),

]
我们匹配的时候加上小括号就是分组了,他就会将小括号里的内容以参数的形式传给views中的函数,而views中的函数就需要参数来接受。
def book(request,*args):
    print(args)
    return HttpResponse(‘o98k‘)

我们把这样的匹配叫做无名分组

注意事项

  1. urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
  2. 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
  3. 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
  4. 每个正则表达式前面的‘r‘ 是可选的但是建议加上。
分组命名匹配: 在Python的正则表达式中,分组命名正则表达式组的语法是(?P<name>pattern),其中name是组的名称,pattern是要匹配的模式。

我们也可以在分组的时候加上名字,比如:
url(r‘^book/(?P<year>[0-9]{4})/[0-9]{2}‘,views.book),

这样views中的book函数在接受的时候就需要一个同名的参数来接受不然就会报错。
def book(request,year):
    print(year)
    return HttpResponse(‘o98k‘)

这就是命名分组!

一个公司会有不同的业务,也会有不同的app,这样我们在写url的时候就可能会有重复。

我们在项目名下的urls.py文件里可以这样写:

from django.conf.urls import url,include
from app01 import urls
urlpatterns = [
    url(r‘app01/‘,include(urls))
]

剩下的就交给app01来做了。

我们现在app01建一个urls.py文件,在文件中这样写:

from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r‘^book/(?P<year>[0-9]{4})/[0-9]{2}‘,views.book),
]

然后再views的文件中写book函数:

def book(request,year):
    print(year)
    return HttpResponse(‘o98k‘)

同样我们也可以有多个app文件。

项目名的urls.py文件下这样写:

from django.conf.urls import url,include
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
    url(r‘app01/‘,include(app01_urls)),
    url(r‘app02/‘,include(app02_urls))
]

在app01创建一个urls的py文件写:

from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r‘^book/(?P<year>[0-9]{4})/[0-9]{2}‘,views.book),
]

在app02创建一个urls的py文件写:



from django.conf.urls import url
from app02 import views
urlpatterns = [
    url(r‘^book/(?P<year>[0-9]{4})/[0-9]{2}‘,views.book),
]

然后分别写好app01和app02下的book函数。

命名URL和URL反向解析:

我们在 url后面加上一个名字,name属性,这样:

url(r‘^json_data/‘,views.json_data,name=‘data‘),就可以在views的函数中进行向解析  print(reverse(‘data‘))具体代码就是这样的:
url(r‘^json_data/‘,views.json_data,name=‘josn_data‘),
在views函数中:
def json_data(request):
    print(reverse(‘ison_data‘))
    data = {‘name‘:‘alex‘,‘age‘:73}
    return  JsonResponse(data)

打印出来的结果就是:/json_data/。

在模板里面可以这样引用:

{% url ‘jaon_data‘ %}

说的简单点就是在url起一个名字,然后reverse通过这个名字反向解析拿到url地址。

参数是这样传的:无名传参:url(r‘^book/([0-9]{4})/[0-9]{2}‘,views.book,name=‘book‘)  函数中的参数:  reverse(‘book‘,args=(‘1995‘))  模板中的参数:  {%url ‘book‘ ‘1995‘%}

 命名传参:

url(r‘^book/(?<Pmouth>[0-9]{4})/[0-9]{2}‘,views.book,name=‘book‘)
  函数中的参数:  reverse(‘book‘,kwargs={‘mouth‘:‘1995‘})  模板中的参数:  {%url ‘book‘ mouth=‘1995‘%}
 namespace:如果说qpp01下和app02下有相同name的url,那么在视图中反向解析的时候找的会是谁的url呢?这就需要在项目名下的include里加一个参数namespace=‘app01‘,namespace=‘app02‘,然后再视图中reverse(‘app01:index‘)                           reverse(‘app02:index‘)                     在模板中也是一样{%url ‘app01:index‘%}

举个例子:


project中的urls.py


from django.conf.urls import url, include

urlpatterns = [
    url(r‘^app01/‘, include(‘app01.urls‘, namespace=‘app01‘)),
    url(r‘^app02/‘, include(‘app02.urls‘, namespace=‘app02‘)),
]


app01中的urls.py


from django.conf.urls import url
from app01 import views

app_name = ‘app01‘
urlpatterns = [
    url(r‘^(?P<pk>\d+)/$‘, views.detail, name=‘detail‘)
]


app02中的urls.py


from django.conf.urls import url
from app02 import views

app_name = ‘app02‘
urlpatterns = [
    url(r‘^(?P<pk>\d+)/$‘, views.detail, name=‘detail‘)
]


现在,我的两个app中 url名称重复了,我反转URL的时候就可以通过命名空间的名称得到我当前的URL。


语法:


‘命名空间名称:URL名称‘


模板中使用:



{% url ‘app01:detail‘ pk=12 %}

views中的函数中使用



v = reverse(‘app01:detail‘, kwargs={‘pk‘:11})
 这样即使app中URL的命名相同,我也可以反转得到正确的URL了。
 
 

原文地址:https://www.cnblogs.com/yb635238477/p/9404179.html

时间: 2024-10-29 13:06:16

django框架之视图系统和路由系统的相关文章

ASP.NET Web API路由系统:路由系统的几个核心类型

虽然ASP.NET Web API框架采用与ASP.NET MVC框架类似的管道式设计,但是ASP.NET Web API管道的核心部分(定义在程序集System.Web.Http.dll中)已经移除了对System.Web.dll程序集的依赖,实现在ASP.NET Web API框架中的URL路由系统亦是如此.也就是说,ASP.NET Web API核心框架的URL路由系统与ASP.NET本身的路由系统是相对独立的.但是当我们采用基于Web Host的方式(定义在程序集System.Web.H

Django框架之视图

Django框架之视图层 什么是视图函数 视图函数,属于Django的视图层,默认定义在views.py文件中,是用来处理web请求信息以及返回响应信息的函数.并且这里的视图函数并不仅仅指代函数,也包括类. 请求对象 Django将http协议请求报文中的请求行.首部信息.内容主体封装到了HttpRequest对象中.将HttpRequest对象当做参数传给视图函数中去,在视图函数中,通过访问该对象的属性便可以提取http协议的请求数据 常用属性 method 获取请求方式 GET 获取GET请

drf框架 6 视图集与路由组件(开发最常用、最高级) 三大认证原理 RBAC认证规则

准备工作 models.py from django.db import models # 基类:是抽象的(不会完成数据库迁移),目的是提供共有字段的 class BaseModel(models.Model): is_delete = models.BooleanField(default=False) updated_time = models.DateTimeField(auto_now_add=True) class Meta: abstract = True # 必须完成该配置 cla

Django框架之templates(模板)系统

一.什么是模板? 只要是在html里面有模板语法就不是html文件了,这样的文件就叫做模板. 二.常用语法 只需要记两种特殊符号: {{  }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 变量 在Django的模板语言中按此语法使用:{{ 变量名 }}. 当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身.(可以理解为模板页面中先进行  “{{  }}和 {% %}”  中对应的数据的替换) 点(.)在模板语言中有特殊的含义,用来获取对象的相应属性值. 内置Fil

Django框架1——视图和URL配置

三个命令 1.创建一个django项目 在cmd中:django-admin.py startproject project_name D:\python\django_site>django-admin startproject first_site 2.创建应用 python manage.py startapp app_name D:\python\django_site\first_site>python manage.py startapp app001 3.运行django项目 p

Django框架之类视图

所谓类视图就是用类定义的视图,其主要支持客户端在用不同的请求方式发起的HTTP请求. 首先,我们需要明确一下类视图的好处: 1.代码可读向高: 2.相对于视图函数具有更高的代码复用性: 3.便于维护. 类视图的定义格式如下: # 1. 导入视图模块from django.views.generic import View class ObjectView(View): """2. 定义一个类视图""" # 3.编写视图函数 def get(sel

Django框架之---视图

视图 视图的功能 视图负责接受Web请求HttpRequest,进行逻辑处理,返回Web响应HttpResponse给请求者. 使用视图的过程 视图就是一个python函数,被定义在"应用/views.py"文件中. 使用视图时需要进行两方面操作,两个操作不分先后. 1)在"应用/views.py"中定义视图. 在booktest/views.py中定义视图函数index: def index(request): return HttpResponse("

Django 框架之视图函数(Views)

http请求中产生的两个核心对象: http请求: HttpRequest对象 http响应: HttpResponse对象 所在位置: django.http HttpRequest 对象的属性和方法: path: 请求页面的全路径,不包括域名; method: 请求中使用的HTTP方法的字符串表示(全大写表示,例如:GET,POST); GET: 包含所有HTTP GET参数的类字典对象; POST: 包含所有HTTP POST参数的类字典对象; COOKIES:包含所有cookies的标志

Django框架学习----视图与模板(最新文章实现)

剩下的就是我们的最后一个功能了,最新文章的跳转 我们先在view.py里面定义一个接受最新五篇文章的变量 top5_article_list,并映射到index页面里面 最后只需要在index.html文件里面吧之前的所有文章的变量换成我们刚刚定义的top5_article_list就可以了 就此django入门结束了 原文地址:https://www.cnblogs.com/humiao-0626/p/12662994.html