对Django中通用视图generic的一些理解

在django中,多种相似的view视图会造成代码的冗余。这时候,可以用django中的通用视图来解决这个问题。

例如:

# polls/urls
from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

# polls/views
def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)

def detail(request, question_id):
	question = get_object_or_404(Question, pk=question_id)
	return render(request, 'polls/detail.html', {'question': question})

def results(request, question_id):
	question = get_object_or_404(Question, pk = question_id)
	return render(request, 'polls/results.html',{'question': question})

这种视图有很多相似的地方。
其实,这类视图都有一个共通的地方,从根据url提供的参数从数据库中获取数据,加载模板文件并且返回渲染后的模板。django中的通用视图可以解决这个问题。

先来看看用generic修改后的样子:

# polls/urls
from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

# polls/views
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic
# 导入的通用视图

from .models import Choice, Question

# 使用Listview
class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        """Return the last five published questions."""
        return Question.objects.order_by('-pub_date')[:5]

# 使用DetailView
class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'


class ResultsView(generic.DetailView):
    model = Question
    template_name = 'polls/results.html'

两个通用视图的区别:
ListView显示一个对象列表。
DetailView显示一个特定类型对象的详细信息页面。

下面解释以下更改的内容:

1、由于DetailView需要从url中获取主键值,所以在urls中将question_id更改为pk(主键值);
2、在默认情况下,通用视图 DetailView 使用一个叫做 < app name>/< model name>_detail.html 的模板。在例子中,它将使用 “polls/Question_detail.html” 模板。template_name 属性是用来告诉 Django 使用一个指定的模板名字,而不是自动生成的默认名字。类似地,ListView 使用一个叫做 < app name>/< model name>_list.html 的默认模板;使用 template_name 来告诉 ListView 使用已经存在的 “polls/index.html” 模板。

修改中遇到的问题

1、

TypeError: __init__() takes 1 positional argument but 2 were given

解决方法:没有添加as_view()方法(自动查找指定方法)

修改前:

path('', views.IndexView, name='index'),

修改后:

path('', views.IndexView.as_view(), name='index'),

2、

Generic detail view ResultsView must be called with either an object pk or a slug.

没有修改question_id 为pk 因为通用视图DetailView已经制订了model 所以需要提供pk(主键值)。

修改前:

path('<int:question_id>/results/', views.ResultsView.as_view(), name='results'),

修改后:

path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
发布了16 篇原创文章 · 获赞 21 · 访问量 690

猜你喜欢

转载自blog.csdn.net/kongge123456/article/details/103323732