Django高级视图

Django限制请求method

限制请求装饰器

  1. django.views.decorators.http import require_http_methods:这个装饰器需要传递一个允许访问的方法的列表。比如只能通过GET的方式访问,那么示例代码:
from django.views.decorators.http import require_http_methods

@require_http_methods
def my_view(request):
    pass
  1. django.view.decorators.http.require_GET: 这个装饰器相当于是require_http_methods(['GET'])的简写形式,只允许使用GETmethod来访问视图;示例代码如下:
from django.views.decorators.http import require_GET

@require_GET
def my_view(request):
    pass
  1. django.views.decorators.http import require_POST:这个装饰器只允许post的方式来访问method视图,示例代码如下:
from django.views.decorators.http import require_POST

@require_POST
def my_view(request):
     pass
  1. django.views.decorators.http.require_safe:这个装饰器相当于是require_http_methods(['GET','HEAD'])的简写形式,只允许使用相对安全的方式来访问视图。因为GET和HEAD不会对服务器产生增删改的行为。因此是一种相对安全的请求方式。示例代码如下:
from django.views.decorators.http import require_safe

@require_safe
def my_view(request):
    pass

重定向

  • 永久重定向: http的状态码是301,多用于旧网站被废弃了要转到一个姓的网址确保用户访问
  • 暂时性重定向:http的状态码是302,表示页面的暂时性跳转。比如访问一个需要权限的网址,如果当用户没有登录,应该重定向到登陆页面,这种情况就应该用暂时性重定向。

在Django中,重定向是使用redirect(to,*args,permanent=False, **kwargs)来实现。to是一个url,permanent代表的是重定向是否是一个永久的重定向,默认false,关于重定向的使用:

from django.shortcuts import reverse,redirect
def profile(request):
    if requst.GET.get("username"):
        return HttpResponse("%s,欢迎来到个人中心页面!")
    else:
        return redrect(reverse("urer:login"))

HttpRequest对象

WSGIRequest对象

  1. is_secure():是否是采用https协议。
  2. is_ajax():是否采用ajax发送的请求。原理就是判断请求头中是否存在X-Requested-With:XMLHttpRequest。
  3. get_host():服务器的域名。如果在访问的时候还有端口号,那么会加上端口号。比如www.baidu.com:9000。
  4. get_full_path():返回完整的path。如果有查询字符串,还会加上查询字符串。比如/music/bands/?print=True。
  5. get_raw_uri():获取请求的完整url。

QueryDict对象:

  1. get方法:用来获取指定key的值,如果没有这个key,那么会返回None。
  2. getlist方法:如果浏览器上传上来的key对应的值有多个,那么就需要通过这个方法来获取。

HttpResponse对象

常用属性

  1. content: 返回内容
  2. status_code:返回的http响应状态码
  3. content_type: 返回的数据的MIME类型,默认为text/htm
  4. 设置响应头:通过设置字典的方式设置响应头,例如我们可以设置一些csrftoken相关的验证信息到响应头:response[‘X-Access-Token’] = ‘xxxx’,我们也可以在response生成csv或者Excel文件时,设置相应的响应头来描述生成的文件信息:response[‘Content-Disposition’] = ‘attachment;filename=“abc.xls”’

常用方法

  1. set_cookie: 用来设置cookie信息。
  2. delete_cookie: 用来删除cookie信息。
  3. write: HttpResoponse是一个类似于文件的对象,可以用来写入数据到数据体(content)中
def index(request):
    response = HttpResponse('

知了课堂

', content_type="text/plain; charset=utf-8") # content_type设置格式 response.status_code = 400 # 设置状态码 response['password'] = 'zhishao' # 设置响应头 response.write('alsd') return response

JsonResponse类

  • 用来对象dump成json字符串,然后返回将json字符串封装成response对象返回给浏览器。并且它的conten_type是application/json

def jsonresponse(request):
    person = {
        'username': 'zhiliao',
        'age': 18,
        'height': 180
    }
    # 不使用JsonResponse的代码
    # person_str = json.dumps(person)
    # response = HttpResponse(person_str, content_type='application/json')
    # return response
    
    # 使用JsonResponse的代码
    response = JsonResponse(person)
    return response
# 默认情况下sonResponse只能对字段进行dump,如果相对非字典的数据进行JsonResponse,那么需要传递一个`safe=False`参数。
person = [1,2,3,4,5]
return HttpResponse(person, safe=false)

生成csv文件

def csv1(request):
    response = HttpResponse(content_type='text_csv')
    # 指定下载文件名
    response['Content-Disposition'] = "attacgment;filename = 'abc.csv'"
    writer = csv.writer(response)  # 往writer写入就会写入response
    writer.writerow(['username', 'age'])
    writer.writerow(['zhiliao', 18])
    return response


def template_csv(request):
    response = HttpResponse(content_type='text/csv')
    # 指定下载文件名
    response['Content-Disposition'] = "attachment;filename ='abc.csv'"
    context = {
        'rows': [
            ['username', 'age'],
            ['zhiliao', 18],
        ]
    }
    template = loader.get_template('abc.txt')
    csv_template = template.render(context)
    response.content = csv_template
    return response

类视图

在写视图的时候,Django除了使用函数作为视图,也可以使用类作为视图。使用类视图可以使用类的一些特性,比如继承等。

View:

  1. from django.views.generic.base import View是主要的类视图,所有的类视图都是基础自他。如果写自己的类视图,也可以继承自它。然后再根据当前请求的method,来实现不同的方法。比如这个视图只能使用get方式来请求,那么就可以在这个类中定义get(self,request,*args,**kwargs)方法。以此类推,如果只需要实现post方法,那么就只需要在类中实现post(self,request,*args,**kwargs),示例代码如下:
class DefineClassview(View):
    """演示类视图的定义和使用"""

    def get(self, request,*args,**kwargs):
        """处理GET请求业务逻辑"""
        return HttpResponse('GET请求业务逻辑')

    def post(self, request,*args,**kwargs):
        """处理POST请求业务逻辑"""
        return HttpResponse('POST请求业务逻辑')

    def put(self, request):
        pass

在配置路由时,需要使用类视图的as_view()l来注册添加:


urlpatterns = [
    # 视图函数:注册
    # url(r'^register/$', views.register, name='register'),
    # 类视图:注册  as_view()可以将类视图转换成视图,并决定如何分发请求
    url(r'^register/$', views.RegisterView.as_view(), name='register'),
    ]
  1. 如果用户访问了View中没有定义的方法。比如你的类视图只支持get方法,而出现了post方法,那么就会把这个请求转发给http_method_not_allowed(request,*args,**kwargs)。

示例:

class BookDetaialView(View):
    def post(self,request,book_id):
        return HttpResponse('图书id是:{}'.format(book_id))
    def http_method_not_allowed(self, request, *args, **kwargs):
        return HttpResponse('你使用的是%s请求,但是不支持POST以外的其他请求!'%request.method)

然后在urls中添加映射:
path('detaial/',views.BookDetaialView.as_view()),

当我们输入网址进行访问的时候,就会返回一个字符串:你使用的是GET请求,但是不支持POST以外的其他请求!

其实不管是get请求还是post请求,都会走django.views.generic.base.View中dispatch(request,*args,**kwargs)方法,所以如果实现这个方法,将能够对所有请求都处理到。

TemplateView

  1. django.view.generic.base.TemplateView,这个类视图是专门用来返回模板的。在这个类中,有两个属性是经常需要用到的,一个是template_name,这个属性是用来存储模板的路径,templateView会自动的渲染这个变量指向的模板。另外一个是get_context_data,这个方法是用来返回上下文数据的,也就是在给模板传的参数的。示例代码如下:
from django.views.generic.base import TemplateView

class HomePageView(TemplateView):
    template_name = "home.html"
    
    def get_context_data(self, **kwargs)
        context = super().get_context_data(**kwargs)
        context["username"] = "看看看"
        return context

urls.py中的映射代码如下:

from django.urls import path
from myapp.views import HomePageView

urlpatterns = [
    path('', HomePageView.as_view())
]

如果在模板中不需要传递任何参数,那么可以直接只在urls.py中使用TemplateView来渲染模板。示例代码如下:

from django.urls import path
from django.views.generic import TemplateView

urlpatterns = [
    path('', TemplateView.as_view(template_name="需要渲染的模板"))
]

ListView

  • 快速开发列表在Django中可以使用ListView

class articleListview(ListView):    # 必须继承ListView
    model = Atricle                 # 重写model类属性,指定这个列表是给哪个模型的
   
    template_name = 'atrophy.html'  # 指定这个列表的模板
    
    context_object_name = 'articles' # 指定这个列表模型在模板中的参数名称
    
    paginate_by = 10                # 指定这个列表一页中展示多少条数据
    
    ordering = 'creat_time'         # 指定这个列表的排序方式
    
    page_kwarg = 'p'                # 获取第几页的数据的参数名称。默认是page

    def get_context_data(self, **kwargs):
        """获取上下文的数据 """
        context = super(articleListview, self).get_context_data(*kwargs)  # 直接调用articListview
        context['username'] = "zhiliao"
        print(context)
        return context

    def get_queryset(self):
        """如果你提取数据的时候,并不是要把所有数据都返回,那么你可以重写这个方法。将一些不需要展示的数据给过滤掉。"""
        return Atricle.objects.filter(id__lt=9)

Paginator和Page类

Paginator和Page类Page类都是用来做分页的,在Django中的路径为from django.core.paginator import Paginatorfrom django.core.paginator import Page

Paginator
  1. count:总共有多少数据
  2. num_pages:总共有多少页
  3. page_range:页面的区间。比如有三页,那么就range(1,4)
Page
  1. has_next:是否还有下一页
  2. has_previous:是否还有上一页
  3. next_page_number:下一页的页码
  4. previous_page_number:上一页的页码
  5. number: 当前页
  6. start_index:当前这一页的第一条数据的索引值
  7. end_index:当前这一页的最后一条数据的索引值

给类视图加装饰器

有时候需要给一些视图添加装饰器。如果用函数视图那么非常简单,只要在函数的上面写上装饰器就可以了。但是如果想要给类添加装饰器,那么可以通过以下两种方案来实现

装饰dispatch方法:

from django.utils.decorators import method_decorator

def login_required(func):
    def wrapper(request,*args,**kwargs):
        if request.GET.get("username"):
            return func(request,*args,**kwargs)
        else:
            return redirect(reverse('index'))
    return wrapper

class IndexView(View)
    def get(self, request, *args, **kwargs):
        return HttpResponse("index")
        
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        super(IndexView,self).dispatch(request, *args, **kwargs)

直接装饰在整个类上

from django.utils.decorators import method_decorator
def login_required(func):
    def wrapper(request,*args,**kwargs):
        if request.GET.get("username"):
            return func(request,*args,**kwargs)
        else:
            return redirect(reverse('login'))
    return wrapper


@method_decorator(login_required,name='dispatch')
class IndexView(View):
    def get(self,request,*args,**kwargs):
        return HttpResponse("index")

    def dispatch(self, request, *args, **kwargs):
        super(IndexView, self).dispatch(request,*args,**kwargs)

错误处理

常见的错误码

  • 404:服务器没有指定的url。
  • 403:没有权限访问相关的数据。
  • 405:请求的method错误。
  • 400:bad request,请求的参数错误。
  • 500:服务器内部错误,一般是代码出bug了。
  • 502:一般部署的时候见得比较多,一般是nginx启动了,然后uwsgi有问题。

错误处理的解决方案

对于404和500这种自动抛出的错误。我们可以直接在templates文件夹下新建相应错误代码的模板文件。而对于其他的错误,我们可以专门定义一个app,用来处理这些错误。

def view_403(request):
    return render(request, 'errors/403.html',status=403)

def view_403(request):
    return render(request, 'errors/500.html',status=500)

你可能感兴趣的:(Django)