文章目录

  • 1. 工作原理
  • 2. 函数视图
  • 1. render()
  • 2. get_object_or_404()
  • 3. 类视图
  • 4. 通用类视图继承与重写
  • 5. 函数视图与类视图区别


1. 工作原理

  • Django的视图(view)是处理业务逻辑的核心,它负责处理用户的请求并返回响应数据。Django提供了两种编写视图的方式:基于函数的视图和基于类的视图
  • Django的视图(views.py)通常和URL路由(URLconf)一起工作的。服务器在收到用户通过浏览器发来的请求后,会根据用户请求的url地址和urls.py里配置的url-视图映射关系,去执行相应视图函数或视图类,从而返回给客户端响应数据
  • 每个视图函数的第一个默认参数都必需是request, 它是一个全局变量。Django把每个用户请求封装成了request对象,它包含里当前请求的所有信息,比如请求路径request.path, 当前用户request.user以及用户通过POST提交的数据request.POST

2. 函数视图

from django.shortcuts import render, redirect, get_object_or_404
 from django.urls import reverse
 from .models import Article
 from .forms import ArticleForm
 
 # 创建文章
 def article_create(request):
     # 如果用户通过POST提交,通过request.POST获取提交数据
     if request.method == "POST":
         # 将用户提交数据与ArticleForm表单绑定
         form = ArticleForm(request.POST)
         # 表单验证,如果表单有效,将数据存入数据库
         if form.is_valid():
             form.save()
             # 创建成功,跳转到文章列表
             return redirect(reverse("blog:article_list"))
     else:
         # 否则空表单
         form = ArticleForm()
     return render(request, "blog/article_form.html", { "form": form, })

 # 更新文章
 def article_update(request, pk):
     # 从url里获取单篇文章的id值,然后查询数据库获得单个对象实例
     article = get_object_or_404(Article, pk=id)
     
     # 如果用户通过POST提交,通过request.POST获取提交数据
     if request.method == 'POST':
         # 将用户提交数据与ArticleForm表单绑定,进行验证
         form = ArticleForm(instance=article, data=request.POST)
         if form.is_valid():
             form.save()
             # 更新成功,跳转到文章详情
             return redirect(reverse("blog:article_detail", args=[pk,]))
     else:
         # 否则用实例生成表单
         form = ArticleForm(instance=article)

     return render(request, "blog/article_form.html", { "form": form, "object": article})


#blog/forms.py 中自定义的 ArticleForm类
from .models import Article
from django import forms

class ArticleForm(forms.ModelForm):
     class Meta:
         model = Article
         fields = ['title', 'body']

1. render()

render() 有4个参数。第一个是request, 第二个是模板的名称和位置,第三个是需要传递给模板的数据内容, 也被称为context object。第四个参数是可选参数content_type(内容类型)

2. get_object_or_404()

get_object_or_404() 第一个参数是模型Models或数据集queryset的名字,第二个参数是筛选条件(比如pk = id, title = ‘python’)。当需要获取的对象不存在时,给方法会自动返回Http 404错误

3. 类视图

  • 注意:在URL配置文件中使用类视图时,需要使用 as_view() 将其伪装成方法
# blog/urls.py
from django.urls import path, re_path
from . import views
 
urlpatterns = [
    path('', views.MyClassView.as_view()),
]

Django提供了很多通用的基于类的视图,来简化视图的编写


作用

举例

ListView

展示对象列表

比如所有用户,所有文章

DetailView

展示某个对象的详细信息

比如用户资料,文章详情

CreateView

通过表单创建某个对象

比如创建用户,新建文章

UpdateView

通过表单更新某个对象信息

比如修改密码,修改文字内容

FormView

用户填写表单后转到某个完成页面

DeleteView

删除某个对象

  • 上述常用通用视图一共有6个,前2个属于展示类视图(Display view), 后面4个属于编辑类视图(Edit view)
  • 使用Edit view,请务必在模型里里定义 get_absolute_url() 方法,否则会出现错误。因为通用视图在对一个对象完成编辑后,需要一个返回链接。get_absolute_url()可以为某个对象生成独一无二的url

4. 通用类视图继承与重写

# Create your views here.
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView, DetailView, CreateView, UpdateView, FormView, DeleteView
from .models import Article
from django.utils import timezone
from .forms import ArticleCreateForm
from myapp.forms import ContactForm


# ListView
class IndexView(ListView):

    template_name = 'blog/article_list.html'
    context_object_name = 'latest_articles'

    def get_queryset(self):
        return Article.objects.filter(author=self.request.user).order_by('-pub_date')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['now'] = timezone.now()
        return context


# DetailView
class ArticleDetailView(DetailView):

    queryset = Article.objects.all().order_by("-pub_date") # 一般不写
    template_name = 'blog/article_detail.html'
    context_object_name = 'article'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['now'] = timezone.now()
        return context


# CreateView
class ArticleCreateView(LoginRequiredMixin, CreateView):
    model = Article
    template_name = 'blog/article_create_form.html'
    form_class = ArticleCreateForm

    def form_valid(self, form):
       # form.do_something()
       form.instance.author = self.request.user
       return super(ArticleCreateView, self).form_valid(form)

# 对于CreateView, 重写它的 form_valid 方法不是必需,但很有用
# 当用户提交的数据是有效的时候,执行该方法
# 通过定义此方法做些别的事情,比如发送邮件,存取额外的数据
# form_valid方法一个常见用途就是(需要用户先登录再提交)


# UpdateView
class ArticleUpdateView(UpdateView):
    model = Article
    template_name = 'blog/article_update_form.html'
    form_class = ArticleUpdateForm

    def form_valid(self, form):
       form.do_sth()
       return super(ArticleUpdateView, self).form_valid(form)

    def get_object(self, queryset=None):
        obj = super().get_object(queryset=queryset)
        if obj.author != self.request.user:
            raise Http404()
        return obj
# UpdateView的常用自定义方法是 get_object 方法。比如一个用户只能编辑自己发表的文章对象,当用户查看别人的对象时,返回http 404错误


# FormView
class ContactView(FormView):
    template_name = 'contact.html'
    form_class = ContactForm
    success_url = '/thanks/'

    def form_valid(self, form):
        # This method is called when valid form data has been POSTed.
        # It should return an HttpResponse.
        form.send_email()
        return super().form_valid(form)
# 使用FormView, 当用户输入信息未通过表单验证,显示错误信息
# 当用户输入信息通过表单验证提交后,跳到其它页面
# 一般需要定义template_name, form_class和success_url


# DeleteView
class ArticleDelete(DeleteView):
    model = Article
    success_url = reverse_lazy('index')
# 删除后通过 reverse_lazy 方法返回到index页面

5. 函数视图与类视图区别

# Create your views here.
from django.views.generic import ListView
from .models import Article

class IndexView(ListView):
    model = Article

# 上述类视图等同于下面函数视图:
def index(request):
    queryset = Article.objects.all()
    return render(request, 'blog/article_list.html', {"article_list": queryset})

虽然只一行model = Article, 但ListView实际上在背后做了很多事情:

  • 提取了需要显示的对象列表或数据集queryset: Article.objects.all()
  • 指定了用来显示对象列表的模板名称: 默认app_name/model_name_list.html
  • 指定了内容对象名称(context object name):默认值object_list