_姜4

2.0里的内容
path转换器
str,int,uuid,/
slug:可理解为注释、后缀、附属等解释性字符
匹配任何ASCII字符以及连接符和下划线
自定义path转换器类

class FourDigitYearConverter:
    regex = '[0-9]{4}'#类属性regex:一个字符串形式的正则表达式属性

    def to_python(self, value):
        return int(value)#数据转换失败,它必须弹出ValueError

    def to_url(self, value):
        return '%04d' % value#数据类型转换为一段url的方法
使用正则表达式re_path


#错误页面
#可以在url里重新定义这个,view.py里加新模板逻辑即可
请求不成功,系统自动返回一个错误页面
handler400 —— django.conf.urls.handler400
handler403 —— django.conf.urls.handler403
handler404 —— django.conf.urls.handler404
handler500 —— django.conf.urls.handler500
手动处理转到错误页面
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})

url路由转发include
1. include('apps.help.urls')遇到include会去掉URL中匹配的部分并将剩下的字符串发送给include的URLconf,转发到二级路由
2. include(extra_url列表)相当于把二级路由模块内的代码写到根路由模块里,不推荐
3. 被转发的URLconf会收到来自父URLconf捕获的所有参数url(r'^(?P\w+)/blog/', include('foo.urls.blog#username可以传去blog对应的url
4. 嵌套参数url(r'comments/(?:page-(?P\d+)/)?$', comments)
5. 向视图传递额外参数url(r'^blog/(?P[0-9]{4})/$', views.year_archive, {'foo': 'bar'})
6. 传递额外的参数给include()参数会传递给include指向的urlconf中的每一行url(r'^blog/', include('inner'), {'blogid': 3})#bug在于有些不要此参数的也会赋值


url反向解析
安全、可靠、自适应的机制,当修改URLconf中的代码后,无需在项目源码中大范围搜索、替换失效的硬编码URL
通过这个name参数,可以反向解析URL、反向URL匹配、反向URL查询或者简单的URL反查
url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive')
  • {{ yearvar }} Archive
  • def redirect_to_year(request): # ... year = 2006 # ...注意参数的传递方法 return HttpResponseRedirect(reverse('news-year-archive', args=(year,))) 命名空间 app_name='xxx' url(r'^(?P\d+)/$', views.DetailView.as_view(), name='detail') ##'polls:index'将解析到'author-polls'实例的index视图 view:reverse('polls:index', current_app=self.request.resolver_match.namespace) template: {% url 'polls:index' %} include一个包含嵌套命名空间数据的对象。 如果你include()一个url()实例的列表,那么该对象中包含的URL将添加到全局命名空间。 但是,你也可以include()一个2元组 polls_patterns = ([ url(r'^$', views.IndexView.as_view(), name='index'), url(r'^(?P\d+)/$', views.DetailView.as_view(), name='detail'), ], 'polls')#元祖 urlpatterns = [ url(r'^polls/', include(polls_patterns)), ]

    @@@view
    $基础响应
    HttpResponse('html')#status=200
    HttpResponseNotFound('html')
    
    from django.http import HttpResponse, HttpResponseNotFound
    from django.http import Http404
    from django.shortcuts import render
    from polls.models import Poll
    from django.shortcuts import get_object_or_404
    def detail(request, poll_id):
        try:
            p = Poll.objects.get(pk=poll_id)#获取表poll内容
        except Poll.DoesNotExist:#表poll不存在
            raise Http404("Poll does not exist")#404
        return render(request, 'polls/detail.html', {'poll': p})#默认空字典
        #my_object = get_object_or_404(MyModel, pk=1)#model
        return redirect(reverse('some-view-name'), foo='bar')#reverse_model
        #queryset = Book.objects.filter(title__startswith='M')#queryset
        #get_object_or_404(queryset, pk=1)
        #get_object_or_404(Book, title__startswith='M', pk=1)#简化
    
    $get_object_or_404(klass, args, *kwargs)[source]#get
    这个方法,非常有用,请一定熟记。常用于查询某个对象,找到了则进行下一步处理,如果未找到则返回404页面
    $my_objects = get_list_or_404(MyModel, published=True)#filter
    返回一个给定模型管理器上filter()的结果,并将结果映射为一个列表,结果为空则弹出Http404异常
    $redirect重定向
    调用对象的get_absolute_url()方法来重定向URL
    object = MyModel.objects.get(...)
    return redirect(object)
    return redirect(object, permanent=True)#永久重定向
    传递视图名,使用reverse()方法反向解析url
    return redirect('some-view-name', foo='bar')#视图名
    return redirect('/some/url/')#硬编码
    return redirect('https://example.com/')#完整url
    

    = = =

    - HttpRequest
    属性
    HttpRequest.scheme求的协议种类
    HttpRequest.body表示原始HTTP请求的正文
    HttpRequest.path表示当前请求页面的完整路径,但是不包括协议名和域名
    HttpRequest.path_info包含路径信息部分,WSGIScriptAlias
    HttpRequest.method方法'GET'POST
    HttpRequest.encoding数据的编码方式DEFAULT_CHARSET
    HttpRequest.content_type请求MIME类型
    HttpRequest.content_params在CONTENT_TYPE标题中的键/值参数字典
    HttpRequest.GET包含GET请求中的所有参数-字典
    HttpRequest.POST包含POST请求的参数与表单数据-字典
    HttpRequest.COOKIES所有Cookie信息的字典。 键和值都为字符串-字典-cookie不安全敏感不要写入
    HttpRequest.FILES包含所有上传的文件数据-字典-键中的name属性值-值UploadedFile
    HttpRequest.METAHTTP头部信息-字典-可用的头部信息取决于客户端和服务器
      CONTENT_LENGTH —— 请求正文的长度(以字符串计)。
      CONTENT_TYPE —— 请求正文的MIME类型。
      HTTP_ACCEPT —— 可接收的响应Content-Type。
      HTTP_ACCEPT_ENCODING —— 可接收的响应编码类型。
      HTTP_ACCEPT_LANGUAGE —— 可接收的响应语言种类。
      HTTP_HOST —— 客服端发送的Host头部。
      HTTP_REFERER —— Referring页面。
      HTTP_USER_AGENT —— 客户端的user-agent字符串。
      QUERY_STRING —— 查询字符串。
      REMOTE_ADDR —— 客户端的IP地址。想要获取客户端的ip信息,就在这里!
      REMOTE_HOST —— 客户端的主机名。
      REMOTE_USER —— 服务器认证后的用户,如果可用。
      REQUEST_METHOD —— 表示请求方法的字符串,例如"GET" 或"POST"。
      SERVER_NAME —— 服务器的主机名。
      SERVER_PORT —— 服务器的端口(字符串)。
    HttpRequest.current_app表示当前app的名字。url模板标签将使用其值作为reverse()方法的current_app参数
    HttpRequest.urlconf设置当前请求的根URLconf,用于指定不同的url路由进入口,这将覆盖settings中的ROOT_URLCONF设置
    
    
    中间件设置的属性
    from django.utils.deprecation import MiddlewareMixin
    HttpRequest.session#SessionMiddleware中间件:一个可读写的,类似字典的对象,表示当前会话
    HttpRequest.site#CurrentSiteMiddleware中间件:get_current_site()方法返回的Site或RequestSite的实例,代表当前站点是哪个
    HttpRequest.user#AuthenticationMiddleware中间件:表示当前登录的用户的AUTH_USER_MODEL的实例未登录AnonymousUser
    #if request.user.is_authenticated:判断当前用户是否合法用户
    
    
    #方法
    HttpRequest.get_host()[source]根据HTTP_X_FORWARDED_HOST和HTTP_HOST头部信息获取请求的原始主机
    HttpRequest.get_port()[source]
    使用META中HTTP_X_FORWARDED_PORT和SERVER_PORT的信息返回请求的始发端口
    HttpRequest.get_full_path()[source]返回包含完整参数列表的path。例如:/music/bands/the_beatles/?print=true
    HttpRequest.build_absolute_uri(location)[source]返回location的绝对URI形式。若location没有提供,则使用request.get_full_path()的值
    HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)[source]
    从已签名的Cookie中获取值,如果签名不合法则返回django.core.signing.BadSignature。
    可选参数salt用来为密码加盐,提高安全系数。 max_age参数用于检查Cookie对应的时间戳是否超时
    HttpRequest.is_secure()[source]
    如果使用的是Https,则返回True,表示连接是安全的
    HttpRequest.is_ajax()[source]
    如果请求是通过XMLHttpRequest生成的,则返回True
    
    从HttpRequest实例读取文件数据,可以将HttpRequest实例直接传递到XML解析器,例如ElementTree
    HttpRequest.read(size=None)[source]
    HttpRequest.readline()[source]
    HttpRequest.readlines()[source]
    HttpRequest.xreadlines()[source]
    HttpRequest.iter()
    import xml.etree.ElementTree as ET
    for element in ET.iterparse(request):
        process(element)
    

    = = =

    ###QueryDict
    request.POST或request.GET的QueryDict都是不可变,只读的
    QueryDict.copy()可以获取一个拷贝然后进行修改
    
    QueryDict.init(query_string=None, mutable=False, encoding=None)[source]
    QueryDict('a=1&a=2&c=3',mutable=True)#实例化可以修改的对象
    
    QueryDict.update(other_dict)用新的QueryDict或字典更新当前QueryDict。类似dict.update(),但是追加内容,而不是更新并替换它们,且查询只返回最新那个
    >>> q = QueryDict('a=1', mutable=True)
    >>> q.update({'a': '2'})
    >>> q.getlist('a')
    ['1', '2']
    >>> q['a'] #'2' returns the last
    
    QueryDict.items()类似dict.items(),如果有重复项目,返回最近的一个,而不是都返回
    >>> q = QueryDict('a=1&a=2&a=3')
    >>> q.items()
    [('a', '3')]
    QueryDict.values()类似dict.values(),但是只返回最近的值
    >>> q = QueryDict('a=1&a=2&a=3')
    >>> q.values()#['3']
    QueryDict.getlist(key, default=None)返回键对应的值列表。 如果该键不存在并且未提供默认值,则返回一个空列表
    QueryDict.setlist(key, list_)[source]为list_设置给定的键
    QueryDict.appendlist(key, item)[source]将键追加到内部与键相关联的列表中
    QueryDict.setdefault(key, default=None)[source]类似dict.setdefault(),为某个键设置默认值
    QueryDict.setlistdefault(key, default_list=None)[source]类似setdefault(),除了它需要的是一个值的列表而不是单个值
    QueryDict.lists()类似items(),只是它将其中的每个键的值作为列表放在一起
    >>> q = QueryDict('a=1&a=2&a=3')
    >>> q.lists()#[('a', ['1', '2', '3'])]
    QueryDict.pop(key)[source]返回给定键的值的列表,并从QueryDict中移除该键。 如果键不存在,将引发KeyError
    >>> q = QueryDict('a=1&a=2&a=3', mutable=True)
    >>> q.pop('a')#['1', '2', '3']
    QueryDict.popitem()[source]删除QueryDict任意一个键,并返回二值元组,包含键和键的所有值的列表。在一个空的字典上调用时将引发KeyError
    >>> q = QueryDict('a=1&a=2&a=3', mutable=True)
    >>> q.popitem()#('a', ['1', '2', '3'])
    QueryDict.dict()将QueryDict转换为Python的字典数据类型,并返回该字典。
    如果出现重复的键,则将所有的值打包成一个列表,最为新字典中键的值
    >>> q = QueryDict('a=1&a=3&a=5')
    >>> q.dict()#{'a': '5'}
    QueryDict.urlencode(safe=None)[source]已url的编码格式返回数据字符串
    >>> q = QueryDict('a=2&b=3&b=5')
    >>> q.urlencode()#'a=2&b=3&b=5'
    

    = = =

    #HttpResponse
    我们编写的每个视图都要实例化、填充和返回一个HttpResponse对象。也就是函数的return值。
    >>> from django.http import HttpResponse
    >>> response = HttpResponse("Here's the text of the Web page.")
    >>> response = HttpResponse("Text only, please.", content_type="text/plain")
    >>> response = HttpResponse()
    >>> response.write("

    Here's the text of the Web page.

    ")#可以write()不短写入内容 可以把HttpResponse对象当作一个字典一样,在其中增加和删除头部字段,与字典不同的是,如果要删除的头部字段如果不存在,del不会抛出KeyError异常 >>> response = HttpResponse() >>> response['Age'] = 120 >>> del response['Age'] 让浏览器以文件附件的形式处理响应, 需要声明content_type类型和设置Content-Disposition头信息 >>> response = HttpResponse(my_data, content_type='application/vnd.ms-excel') >>> response['Content-Disposition'] = 'attachment; filename="foo.xls"' HttpResponse.content HttpResponse.charset HttpResponse.status_code HttpResponse.reason_phrase响应的HTTP原因短语 HttpResponse.streaming这个值总为False,能使得中间件能够区别对待流式响应和常规响应 HttpResponse.closed响应已关闭True/False #方法 HttpResponse.init(content='', content_type=None, status=200, reason=None, charset=None)[source] HttpResponse.has_header(header)检查头部中是否有给定的名称(不区分大小写),返回True或 False HttpResponse.setdefault(header, value)设置一个头部,除非该头部已经设置过了 HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False) 设置一个Cookie。 参数与Python标准库中的Morsel.Cookie对象相同 domain: 用于设置跨域的Cookie。例如domain=".lawrence.com"将设置一个www.lawrence.com、blogs.lawrence.com和calendars.lawrence.com都可读的Cookie。 否则,Cookie将只能被设置它的域读取。 阻止客服端的JavaScript访问Cookie,可以设置httponly=True HttpResponse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=True) 与set_cookie()类似,但是在设置之前将对cookie进行加密签名。通常与HttpRequest.get_signed_cookie()一起使用 HttpResponse.delete_cookie(key, path='/', domain=None) 删除Cookie中指定的key。 由于Cookie的工作方式,path和domain应该与set_cookie()中使用的值相同,否则Cookie不会删掉 HttpResponse.write(content)[source]将HttpResponse实例看作类似文件的对象,往里面添加内容 HttpResponse.flush()清空HttpResponse实例的内容 HttpResponse.tell()[source]将HttpResponse实例看作类似文件的对象,移动位置指针 HttpResponse.getvalue()[source]返回HttpResponse.content的值。 此方法将HttpResponse实例看作是一个类似流的对象 HttpResponse.readable()Django1.10中的新功能,值始终为False HttpResponse.seekable()Django1.10中的新功能,值始终为False HttpResponse.writable()[source]Django1.10中的新功能,值始终为True HttpResponse.writelines(lines)[source]将一个包含行的列表写入响应对象中。 不添加分行符 #衍生子类 Django包含了一系列的HttpResponse衍生类(子类),用来处理不同类型的HTTP响应。与HttpResponse相同, 这些衍生类存在于django.http之中。 class HttpResponseRedirect[source]:重定向,返回302状态码。已经被redirect()替代。 class HttpResponsePermanentRedirect[source]:永久重定向,返回301状态码。 class HttpResponseNotModified[source]:未修改页面,返回304状态码。 class HttpResponseBadRequest[source]:错误的请求,返回400状态码。 class HttpResponseNotFound[source]:页面不存在,返回404状态码。 class HttpResponseForbidden[source]:禁止访问,返回403状态码。 class HttpResponseNotAllowed[source]:禁止访问,返回405状态码。 class HttpResponseGone[source]:过期,返回405状态码。 class HttpResponseServerError[source]:服务器错误,返回500状态码。 #JsonResponse JsonResponse是HttpResponse的一个子类,是Django提供的用于创建JSON编码类型响应的快捷类,默认Content-Type头部设置为application/json JsonResponse(data,encoder = DjangoJSONEncoder,safe = True,json_dumps_params = None ,** kwargs)[source] >>> from django.http import JsonResponse >>> response = JsonResponse({'foo': 'bar'}) >>> response.content#b'{"foo": "bar"}' 若要序列化非dict对象,必须设置safe参数为False,不传递safe=False,将抛出一个TypeError >>> response = JsonResponse([1, 2, 3], safe=False) 如果你需要使用不同的JSON 编码器类,可以传递encoder参数给构造函数 >>> response = JsonResponse(data, encoder=MyJSONEncoder) #StreamingHttpResponse StreamingHttpResponse类被用来从Django响应一个流式对象到浏览器,对于生成大型的CSV文件非常有用 #FileResponse FileResponse是StreamingHttpResponse的衍生类 >>> from django.http import FileResponse >>> response = FileResponse(open('myfile.png', 'rb'))

    = = =

    文件上传打包在request.FILES
    request.FILES只有在请求方法为POST,并且提交请求的
    具有enctype="multipart/form-data"属性时才有效。 否则,request.FILES将为空。 # forms.py from django import forms class UploadFileForm(forms.Form): title = forms.CharField(max_length=50) file = forms.FileField() 用request.FILES['file']来获取上传文件的具体数据 # 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) # 注意获取数据的方式必须将request.FILES传递到form的构造函数中。 if form.is_valid(): handle_uploaded_file(request.FILES['file']) return HttpResponseRedirect('/success/url/') else: form = UploadFileForm() return render(request, 'upload.html', {'form': form}) 处理上传文件的方法 def handle_uploaded_file(f): with open('some/file/name.txt', 'wb+') as destination: for chunk in f.chunks(): destination.write(chunk) 遍历UploadedFile.chunks(),而不是直接使用read()方法,能确保大文件不会占用系统过多的内存 = = = @使用模型层的model来指定上传文件的保存方式使用ModelForm更方便。 调用form.save()的时候,文件对象会保存在相应的FileField的upload_to参数指定的地方 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(): # 这么做就可以了,文件会被保存到Model中upload_to参数指定的位置 form.save()#保存在相应的FileField的upload_to参数 return HttpResponseRedirect('/success/url/') else: form = ModelFormWithFileField() return render(request, 'upload.html', {'form': form}) @如果手动构造一个对象,还可以简单地把文件对象直接从request.FILES赋值给模型 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 = UploadFileForm(request.POST, request.FILES)#构造对象 if form.is_valid(): instance = ModelWithFileField(file_field=request.FILES['file'])#直接赋值给模型 instance.save()#保存在相应的FileField的upload_to参数 return HttpResponseRedirect('/success/url/') else: form = UploadFileForm() return render(request, 'upload.html', {'form': form}) @如果要使用一个表单字段同时上传多个文件,需要设置字段HTML标签的multiple属性为True,如下所示: # forms.py from django import forms class FileFieldForm(forms.Form): file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True})) # views.py from django.views.generic.edit import FormView from .forms import FileFieldForm class FileFieldView(FormView): form_class = FileFieldForm template_name = 'upload.html' # 用你的模版名替换. success_url = '...' # 用你的URL或者reverse()替换. 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 f in files: ... # Do something with each file. return self.form_valid(form) else: return self.form_invalid(form) @上传文件处理器 上传处理器的配置定义在FILE_UPLOAD_HANDLERS ["django.core.files.uploadhandler.MemoryFileUploadHandler", "django.core.files.uploadhandler.TemporaryFileUploadHandler"] MemoryFileUploadHandler和TemporaryFileUploadHandler定义了Django的默认文件上传行为:将小文件读取到内存中,大文件放置在磁盘中 普通写入csv import csv from django.http import HttpResponse def some_view(request): # Create the HttpResponse object with the appropriate CSV header. 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 #利用Python的生成器来有效处理大尺寸CSV文件的拼接和传输,Django的StreamingHttpResponse避免断连 import csv from django.http import StreamingHttpResponse class Echo(object): """An object that implements just the write method of the file-like interface. """ def write(self, value): """Write the value by returning it, instead of storing in a buffer.""" return value def some_streaming_csv_view(request): """A view that streams a large CSV file.""" # Generate a sequence of rows. The range is based on the maximum number of # rows that can be handled by a single sheet in most spreadsheet # applications. rows = (["Row {}".format(idx), str(idx)] for idx 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 #使用Django的模板系统来生成CSV不建议使用=for {% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}" {% endfor %} from django.http import HttpResponse from django.template import loader, Context def some_view(request): # Create the HttpResponse object with the appropriate CSV header. response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="somefilename.csv"' # The data is hard-coded here, but you could load it from a database or # some other source. 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 @动态生成PDF文件 不是线程安全的 pip install reportlab from reportlab.pdfgen import canvas from django.http import HttpResponse def some_view(request): # 创建带有PDF头部定义的HttpResponse对象 response = HttpResponse(content_type='application/pdf') response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"' # 创建一个PDF对象,并使用响应对象作为它要处理的‘文件’ p = canvas.Canvas(response) # 通过PDF对象的drawString方法,写入一条信息。具体参考模块的官方文档说明。 p.drawString(100, 100, "Hello world.") # 关闭PDF对象 p.showPage() p.save() return response #复杂的PDF涉及IO from io import BytesIO from reportlab.pdfgen import canvas from django.http import HttpResponse def some_view(request): # Create the HttpResponse object with the appropriate PDF headers. response = HttpResponse(content_type='application/pdf') response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"' buffer = BytesIO() # Create the PDF object, using the BytesIO object as its "file." p = canvas.Canvas(buffer) # Draw things on the PDF. Here's where the PDF generation happens. # See the ReportLab documentation for the full list of functionality. p.drawString(100, 100, "Hello world.") # Close the PDF object cleanly. p.showPage() p.save() # Get the value of the BytesIO buffer and write it to the response. pdf = buffer.getvalue() buffer.close() response.write(pdf) return response

    你可能感兴趣的:(_姜4)