python_new
  • Introduction
  • First Chapter
  • 一、python基础
    • 1.1 常识
      • sys
    • 1.2 基础语法(1)
    • 1.2 基础语法(2)
    • 1.3 常见问题求解
    • 1.4 算法
  • 二、爬虫
    • urllib库(1)
      • urllib库(2)
    • requests模块(1)
      • requests模块(2)
    • 2.1 爬虫基础(3)HTTP原理
    • 2.1 爬虫基础(4)会话和Cookies
    • 2.1 爬虫基础(5)数据存储
      • Mysql存储
      • MongoDB存储
      • Redis存储
    • 2.3 正则表达式
    • 2.4 解析库lxml
      • BeautifulSoup
      • pyquery(1)
      • pyquery(2)
    • 2.5 selenium(1)
    • 2.5 seleium(2)
    • 2.6 Json
    • 2.7 scrapy
      • scrapy(2)
    • 2.9 异步加载
    • 2.6 Splash
  • ORM框架
    • SQLAlchemy
  • Django
    • 1、初阶(一)
    • 初学:投票教程(一)
    • 初学:投票教程(二)
    • 初学:投票教程(三)
    • 初学:投票教程(总结)
    • 模型(一)
    • 模型(二)
    • 视图(一)
    • 视图(二)
    • 模板(一)
    • django实际使用笔记
  • 面试题收集总结
    • 数据结构原理
    • 算法篇
      • 排序
    • 题目篇
  • python数据分析
    • 基础了解(一)
    • 基础了解(二)
    • 基础了解(三)
  • 多线程
  • 深度学习
    • 疑问
  • keras(一)
  • 神经网络
  • 图像识别
  • Docker
    • 一、基础了解
Powered by GitBook
On this page
  • 1、内置视图
  • 1、在开发环境中提供文件
  • 2、错误视图
  • 2、文件上传
  • 1、基础的文件上传
  • 2、用模型处理上传文件
  • 3、上传多个文件
  • 4、上传文件的处理器
  • 3、输出CSV文件
  • 1、使用python库CSV
  • 2、传输较大的CSV文件
  • 3、使用模板系统
  • 4、输出PDF文件
  • 1、安装ReportLab
  • 2、写视图函数
  • 3、复杂的PDFs

Was this helpful?

  1. Django

视图(二)

Previous视图(一)Next模板(一)

Last updated 6 years ago

Was this helpful?

参考资料:

1、内置视图:

2、文件上传:

3、生成csv文件:

4、生成pdf文件:

1、内置视图

1、在开发环境中提供文件

from django.conf import settings
from django.urls import re_path
from django.views.static import serve

if settings.DEBUG:
    urlpatterns += [re_path(r'^media/(?P<path>.*)$', serve, 
    {'document_rot': settings.MEDIA_ROOT})]

这个视图的使用方式我确实不知道

2、错误视图

  • 404(page not found) view

default.page_not_found(request, exception, template_name='404.html')

当出现Http404异常时,django会调用

django.views.defaults.page_not_found()

视图,以及404.html模板。默认的视图会传两个参数变量到模板,分别是:request_path,exception。这个视图有几个需要注意的点,

1:如果django在URLconf中找不到一个匹配时会被调用

2:视图中可以传递一个RequestContext变量

3、如果DEBUG设置为True,那这个视图永远不会被调用,而URLconf会被播放演示出来,并附带一些debug信息

  • 500(server error) view

defaults.server_error(request, template_name='500.html')

在运行过程中,django可能也会报错,这时django默认会调用django.views.defaults.server_error视图,然后简单地生成一个“Server Error”的信息,或者如果你在模板目录下创建了505.html时,他也会使用这个这个模板。

默认的500视图不会传任何参数到500.html模板中,用空Context渲染以减少错误的可能。如果DEBUG被设置为True,500视图永远不会被调用,而是会赝势traceback的信息,并有一些debug的信息。

  • 403(HTTP forbidden) view

defaults.permission_denied(request, exception, template_name='403.html')

基本上与前面的类似,这个视图是被PermissionDenied异常触发的,当然也可以人为触发

from django.core.exception import PermissionDenied

def edit(request, pk):
    if not request.user.is_staff:
        raise PermissionDenied
    ...
  • 400(bad request) view

defaults.bad_request(request, exception, template_name='400.html')

当SuspiciousOperation在django中被触发时,django中的一个组件可能会处理,但是如果这个组件没有处理的话,就会把这个请求作为“错误请求”而不是服务器错误。

django.views.defaults.bad_request跟500的服务器错误很相似,但返回的代码是400,表示错误的条件是异常客户端操作的结果。

bad_request当DEBUG为True也不会被调用。

2、文件上传

1、基础的文件上传

django处理文件上传的时候,文件最终会在request.FILES中

# forms.py 
from django impot forms

class UploadFileForm(forms.Form):
    title = forms.CharField(max_length=50)
    file = forms.FileField()

处理这个表单的视图将通过request.FILE获取到文件数据,而request.FILES是一个字典,每一个键对应一个FileField或者ImageField或者FileField子类,所以上面的表格的数据可以这样获得request.FILES['file']

请注意,只有请求的方法是POST的时候,并且<form>有enctype="multipart/form-data"的属性时才可以被获取到,否则,是空的。

# views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm

from somewhere import handle_uploaded_file

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            handle_uploaded_file(request.FILES['file'])
            return HttpResponseRedirect('/success/url')
    else:
        form = UploadFileForm()
    return render(request, 'upload.html', {'form': form})

一个处理file的示例

def handle_upload_file(f):
    with open('some/file/name.txt', 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)

不要直接读(read()),而是使用chunks()来确保过大的文件不会溢出内存。

2、用模型处理上传文件

如果你想要用一个模型和FileField来保存文件,使用ModelForm会让过程更加轻松。

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import ModelFormWithFileField

def upload_file(request):
    if request.method == 'POST':
        form = ModelFormWithFileField(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/success/url/')
    else:
        form = ModelFormWithFileField()
    return render(request, 'upload.html', {'form': form})

如果你想要手动编写一个模型,那你可以这样

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import UploadFileForm
from .models import ModelWithFileField

def upload_file(request):
    if request.method == 'POST':
        form = UploadFielForm(request.POST, request,.FILES)
        if form.is_valid():
            instance = ModelWithFileField(file_field=requst.FILES['file'])
            instance.save()
            return HttpResponseRedirect('/success/url')
    else:
        form = UploadFileForm()
    return render(request, 'upload.html', {'form': form})

对了,保存的时候可以调用‘upload_to’字段,指定保存的路径。

3、上传多个文件

使用表格字段(form field)的方式来上传多个文件,需要设置

# forms.py
from django import forms

class FileFieldForm(forms.Form):
    file_field = forms.FileField(widget=forms.ClaerbleFileInput(atts={'multiple': True}))

然后覆盖FormView子类的post方法来处理多个文件上传

from django.views.generic.edit import FormView
from .forms import FileFieldForm

class FileFieldView(FormView):
    form_class = FileFieldForm
    template_name = 'upload.html'
    success_url = '....'

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        files = request.FILES.getlist(file_field'')
        if form.is_valid():
            for i in files:
                ...
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

4、上传文件的处理器

当一个文件被上传的时候,django会把文件数据传递给文件处理器,一个小的类来处理上传的文件数据。这个处理器的定义设置在

# FILE_UPLOAD_HANDLERS
["django.core.files.uploadhandler.MemoryFileUploadHandler", 
"django.core.files.uploadhandler.TemporaryFileUploadHandler"]

这里可以自定义很多行为。

在文件被保存的之前,这些数据需要被存储在某个地方

默认的情况,如果文件小于2.5M,django会把它放在缓存中。这样保存文件的过程中,就只会涉及到一个内存读取和硬盘写入,会很快。但是如果很大的文件的话,django会把他保存在某个路径下。当然这个2.5也是可以修改的。

3、输出CSV文件

实现CSV文件的输出可以使用python的CSV库,或者django模板系统

1、使用python库CSV

使用csv的关键是它可以处理类文件对象的能力,而HttPResponse恰好是。

import csv
from django.http HttpResponse

def some_view(request):
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment;filename="somefilename.csv"'
    writer = csv.writer(response)
    writer = writerow(['First row', 'Foo', 'Bar', 'Baz'])
    writer = writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"])
    return response

提示:

1、不要忘记类型是‘text/csv’,否则会视为html文件

2、'Content-Disposition'是为了设置文件名,比如浏览器保存的时候,会显示保存文件名到某某地方。

2、传输较大的CSV文件

这时候使用StreamingHttpResponse更好

import csv
from django.http import StreamingHttpResponse

class Echo:
    def write(self, value):
        return value

def some_streaming_csv_view(request):
    rows = (["Row {}".format(idx), str(idx)] for iidx in range(65536))
    pseudo_buffer = Echo()
    writer = csv.writer(pseudo_buffer)
    response = StreamingHttpResponse(writer.writerow(row) for row in rows),
                                    content_type='text/csv'
    response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
    return response

说实话,不懂

3、使用模板系统

from django.http import HttpResponse
from django.template import Context, loader

def some_view(request):
    response = HttpResponese(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
    csv_data = (('First row', 'Foo', 'Bar', 'Baz'),
                ('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"))
    t = loader.get_template('my_template_name.txt')
    c = Context({'data': csv_data})
    response.write(t.render(c))
    return response

这个就有点意思了,它把数据传到一个模板中,然后返回这个模板,只不过,这个模板是txt格式的。这让我很惊讶,我一直以为模板只能使用在html文件中,没想到其他的也可以,这说明,文件名和模板操作没有关系,不论是不是html,都可以使用模板传递数据,然后渲染效果。

{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}",
"{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
{% endfor %}

这里不止csv,只是一种示例,txt也可以的。

4、输出PDF文件

1、安装ReportLab

pip install reportlab

2、写视图函数

reportlab也可以处理类文件对象

from django.http import HttpResponse
from reportlab.pdfgen import canvas

def some_view(request):
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
    p = canvas.Canvas(response)
    p.drawString(100, 100, 'Hello World.')

    p.showPage()
    p.save()
    return response

提示:如同csv文件

1、attachment的作用是强制浏览器弹出对话框提示如何处理pdf文件,如果没有的话,浏览器自动寻找插件或者其他处理pdf的工具。

3、复杂的PDFs

如果你想要生成一个较复杂的pdf文件,可以考虑io库来作为pdf文件的临时保存器。

from io import BytesIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse

def some_view(request):
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
    buffer = BytesIO()
    # 暂时放在buffer中
    p = canvas.Canvas(buffer)
    p.drawString(100, 100, 'Hello World.')
    p.showPage()
    p.save()
    # 从buffer中取出数据
    pdf = buffer.getvalue()
    buffer.close()
    response.writer(pdf)
    return response
https://docs.djangoproject.com/zh-hans/2.0/ref/views/
https://docs.djangoproject.com/zh-hans/2.0/topics/http/file-uploads/
https://docs.djangoproject.com/zh-hans/2.0/howto/outputting-csv/
https://docs.djangoproject.com/zh-hans/2.0/howto/outputting-pdf/