django -- 视图高级

* django 限制请求  
* 页面重定向  
* HttpRequest对象  
* 生成CSV文件  
* 类视图   

## django 限制请求    

* get  一般用来像服务器索取数据 不会对服务器的状态进行修改  不会像服务器提交数据  
* post 一般用来像服务器提交数据  会对服务器的状态进行修改 比如提交一片文章给服务器  


~~~
 **装饰器:require_http_method()
    使用Django预置的require_http_methods(methods)装饰器进行限制, 让框架帮你拦截那些不想要的请求。
    
405代码表示:请求的方法 不被允许。

require_GET() - 声明被装饰的视图仅支持GET方法
require_POST() - 声明被装饰的视图仅支持POST方法
require_SAFE() - 声明被装饰的视图仅支持GET和HEAD方法


~~~


```
from django.views.decorators.http import require_http_methods
@require_http_methods(['GET'])   这样的话只能 GET请求过来 
def index(request):
    #首页用来展示数据
    #一般用get请求 展示数据
    articles = Article.objects.all()
    return render(request,'index.html',context={"articles":articles})
    
完整实例
models.py
    from django.db import models
    class Article(models.Model):
        title = models.CharField(max_length=100)
        content = models.TextField()
        price = models.FloatField(default=0)
        create_time = models.DateTimeField(auto_now_add=True)
        class Meta:
            db_table = 'article'
views.py
      from django.shortcuts import render
      from .models import Article
      from django.views.decorators.http import                     require_http_methods,require_GET,require_POST,require_safe
      from django.http import HttpResponse

      def add(request):
          books = Article(title='三国',content='haha')
          books.save()
          return HttpResponse("添加成功")
        
      #两种方法判断method请求方法
      # @require_GET
      @require_http_methods(['GET'])
      def index(request):
          article = Article.objects.all()
          for i in article:
              print(i.title)
          return render(request,'index.html',context={"article":article})

      @require_http_methods(['GET','POST'])
      def add_article(request):
          if request.method == "GET":
              return render(request,'add_article.html')
          else:
              title = request.POST.get('title')
              content = request.POST.get('content')
              price = request.POST.get('price')
              #第一种方法添加数据            
              Article.objects.create(title=title,content=content,price=price)
              #第二种方法添加数据
              a = Article(title=title,content=content,price=price)
                a.save()
              return HttpResponse("添加成功")
              
add_article.html
      <form action="{% url 'add_article' %}" method="get">
          <table>
              <tbody>
                  <tr>
                      <td>标题</td>
                      <td><input type="text" name="title"></td>
                  </tr>
                  <tr>
                      <td>内容</td>
                      <td><input type="text" name="content"></td>
                  </tr>
                  <tr>
                      <td>价格</td>
                      <td><input type="text" name="price"></td>
                  </tr>
                  <tr>
                      <td></td>
                      <td><input type="submit" name="提交"></td>
                  </tr>
              </tbody>
          </table>
      </form>        
```

## 页面重定向  

* 301 永久性重定向  比如  t.tt 跳转到  https://www.smartisan.com/   www.jingdong.com 跳转到 www.jd.com
* 302暂时性的重定向   https://www.zhihu.com 如果没有登陆 跳转到  https://www.zhihu.com/signup?next=%2F

## HttpRequest对象  

```
django在接收到http请求以后  会根据请求携带的参数 及 报文 创建 一个 WSGIRequest对象  这个对象会作为视图函数的第一个参数传递给 视图函数  也就是经常看到的request  
```

### WSGIRequest 属性  

* path  request.path  请求服务器的完整的路径 注意这里不包括域名和端口号  

* method request.method 请求的方法  GET 或者 POST 

* request.get_raw_uri()   包含域名和端口   

* ​    http://127.0.0.1:9000/signup/?username=1111&password=12345 

* request.get_host()  返回的是127.0.0.1

  ~~~
  代码实例
  views.py
        from django.shortcuts import render,redirect,reverse
        from django.http import HttpResponse
        from django.core.handlers.wsgi import WSGIRequest
        # Create your views here.

        # def index(request):
        #     username = request.GET.get('username')
        #     if username:
        #         return HttpResponse("首页")
        #     else:
        #         return redirect(reverse('signup'))
        #
        # def signup(request):
        #     return HttpResponse("登录界面")

        def index(request):
            print(type(request))#打印出<class 'django.core.handlers.wsgi.WSGIRequest'>
            print(request.path)#打印出 /
            return HttpResponse("首页")

        def signup(request):
            print(request.path)#打印出/signup/
            print(request.method)#打印出GET
            print(request.get_raw_uri())#打印出http://127.0.0.1:9000/signup/
            print(request.get_host())#打印出127.0.0.1:9000
            return HttpResponse("登录首页")
            
  主目录下的urls.py
        from front import views
        urlpatterns = [
            path('', views.index,name='index'),
            path('signup/', views.signup,name='signup'),
        ]
        
  ~~~

  ​

## 将数据到处到 CSV  文件  

```
from django.http import HttpResponse
import csv

def index(request):
    response = HttpResponse(content_type='text/csv') #告诉浏览器这是一个  csv 格式的文件 不是html 如果不指定 就是html 
    response['Content-Disposition']="attechment;filename='abc.csv'"# 在 response 添加一个 'Content-Disposition'头  这样的话 是为了告诉他 该怎么样处理这个csv文件 attechment 说明这是一个附件 这样浏览器就不会显示它 而是下载  filename='abc.csv' 是指定附件的名字  
    writer = csv.writer(response) writer 将 内容写进respone
    writer.writerow(['username','age','height'])
    writer.writerow(['qulinx', '18', '181cm'])
    return response

```

### 根据模板 导出 csv 文件  

```
def template_csv_view(request):
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = "attechment;filename='linzhen.csv'"
    context = {
        'rows':[
            ['username','age','height','weight'],
            ['zelinx',18,'181cm','90kg']
        ]
    }
    #获得模板python1806.txt
    template= loader.get_template('python1806.txt')
    csv_template = template.render(context)
    response.content = csv_template
    return response
```

### StreamingHttpResponse 在处理大文件的时候 不会因为 服务器响应时间长而超时  这个类不继承于  HttpResponse  类似于 大视频 边看边下载 

```
def large_csv_view(request):
    # response = HttpResponse(content_type='text/csv')
    # response['Content-Disposition'] = "attechment;filename='linzhen.csv'"
    # writer = csv.writer(response)
    # for row in range(0,1000000):
    #     writer.writerow(['Row {}'.format(row),'{}'.format(row)])
    # return response
    response = StreamingHttpResponse(content_type='text/csv')
    response['Content-Disposition'] = "attechment;filename='kangbazi.csv'"
    rows = ("第{},{}\n".format(row,row) for row in range(0,10000000))
    response.streaming_content=rows
    return response

```

## 类视图  

```
views.py  
from django.views.generic import View
class AddFront(View):
    def get(self,request,*args,**kwargs):
        #*args 所有的位置参数  **kwargs 所有的关键字参数
        # 这两个说明 你可以接收任意的参数
        #self 这个参数是对象的参数
        return render(request,'add_book.html')
    def post(self,request,*args,**kwargs):
        title = request.POST.get('title')
        content = request.POST.get('content')
        print("title:{},content:{}".format(title,content))
        return HttpResponse("添加成功")
        
        
 urls  
    path('add/',views.AddFront.as_view(),name="add_front")
```

## TemplateView 返回模板用    比如果壳网 的  关于我们  这个网页完全可以是  静态的 可以直接返回    不用每次请求 请求数据库 之类的   

```python
class AboutView(TemplateView):
    template_name = 'about.html'

urls.py
    path('about',views.AboutView.as_view(),name="about_view"),

如果想要加载动态内容  
    只需要  
class AboutView(TemplateView):
    template_name = 'about.html'
    def get_context_data(self, **kwargs):
        context = {
            "phone":"13888888888"
        }
        return context
        
 页面上: 
     {{phone}}
```

~~~
完整代码实例
views.py
    from django.shortcuts import render
    from .models import Front
    from django.http import HttpResponse
    from django.views.generic import View,TemplateView
    # Create your views here.

    def add_front(request):
        fronts = []
        for a in range(0,100):
            front = Front(title='标题:%s'%a,content='内容:%s'%a)
            fronts.append(front)
        Front.objects.bulk_create(fronts)#保存数据
        return HttpResponse("添加成功")

    class AddFront(View):
        def get(self,request,*args,**kwargs):
            return render(request,'add_book.html')

        def post(self,request,*args,**kwargs):
            title = request.POST.get('title')
            content = request.POST.get('content')
            create_time = request.POST.get('create_time')
            print("title:{},content:{},创建时间:{}".format(title,content,create_time))
            front = Front(title=title,content=content,create_tme=create_time)
            front.save()
            return HttpResponse("添加成功")

    class AboutView(TemplateView):
        template_name = 'about.html'
        def get_context_data(self, **kwargs):
            context = {
                "phone":"13888888888888888"
            }
            return context
            
models.py
    from django.db import models
    # Create your models here.
    class Front(models.Model):
        title = models.CharField(max_length=100)
        content = models.TextField()
        create_tme = models.DateTimeField(auto_now_add=True)
        class Meta:
            db_table = 'front'
app下的urls.py
    from django.urls import path
    from . import  views
    urlpatterns = [
        path('',views.add_front),
        path('add/',views.AddFront.as_view(),name='add_front'),
        path('about/',views.AboutView.as_view(),name='about_view'),
    ]

项目下的urls.py
    from django.urls import path,include
    urlpatterns = [
        path('front/', include('front.urls')),
    ]

~~~

猜你喜欢

转载自blog.csdn.net/qq_42336700/article/details/82765412