【问题标题】:What's the difference between FormView and CreateViewFormView 和 CreateView 有什么区别
【发布时间】:2015-12-07 02:04:58
【问题描述】:

在官方文档中, formView 是显示表单的视图。出错时,重新显示带有验证错误的表单;成功后,重定向到一个新的 URL。 createView 是一个视图,它显示用于创建对象的表单,重新显示带有验证错误(如果有的话)的表单并保存对象。 //(也许我的英语不够好)所以如果我想为用户创建一个新类别创建一个通用视图,我应该使用 createview 而不是 formview 对吗?我不确定,所以我尝试了两种方法,但它们都给了我同样的错误:as_view() 只需要 1 个参数(给定 2 个)

带表单视图:

用于添加类别

class CategoryFormView(FormView):
    form_class = CategoryForm
    template_name = 'main/add_category.html'

    def get_success_url(self):
        return self.request.build_absolute_uri(reverse('category', args=[self.object.slug]))

    def get_context_data(self, **kwargs):
        context = super(CategoryFormView, self).get_context_data(**kwargs)
        # Add any extra context data needed for form here.
        return context

使用创建视图

#for adding category
class CategoryCreateView(CreateView):
    model = Category
    form_class = CategoryForm
    template_name = 'main/add_category.html'

    def form_valid(self, form):
      self.object = form.save(commit=False)
      #setting
      self.object.save()
      return HttpResponseRedirect(reverse('category', args=[self.object.slug]))

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
      return super(CategoryCreateView, self).dispatch(request, *args, **kwargs)
   

最后这是我的 urls.py

url(r'^add_category/', views.CategoryCreateView.as_view, name='add-category'),

编辑:对不起,它可以工作,只是忘记在 url 旁边放括号,但是你能告诉我 createview 和 formview 之间的区别吗?什么时候应该用什么?

编辑2:

def index(request):

    categories = Category.objects.order_by('likes')[:5]
    latest_posts = Post.objects.all().order_by('-created_at')
    popular_posts = Post.objects.all().order_by('-views')
    hot_posts = Post.objects.all().order_by('-score')[:25]
    context_dict = {
        'latest_posts': latest_posts,
        'popular_posts': popular_posts,
        'hot_posts': hot_posts,
        'categories': categories
    }
    return render(request, 'main/index.html', context_dict)
#for single-post page
#we use uuslug 
def post(request, slug):
    single_post = get_object_or_404(Post, slug=slug)
    single_post.views += 1  # increment the number of views
    single_post.save()      # and save it
    context_dict = {
      'single_post' :single_post,
    }
  
    return render(request, 'main/post.html', context_dict)
#for category page
#we use slugfield this time 
def category(request, category_name_slug):
  context_dict = {}
  try:
    category = Category.objects.get(slug=category_name_slug)
    context_dict['category_name'] = category.name

    posts = Post.objects.filter(category=category)
    context_dict['posts'] = posts
    context_dict['category'] = category
  except Category.DoesNotExist:
    pass

  return render(request, 'main/category.html', context_dict)
  

编辑 3

urls.py

from django.conf.urls import url
from main import views
from django.core.urlresolvers import reverse
from views import *

urlpatterns = [
    url(r'^$', IndexView.as_view(), name='index'),

    #url(r'^add_post/', views.add_post, name='add_post'),
    url(r'^add_post/$', PostCreateView.as_view(), name='post-add'),

    url(r'^(?P<slug>[\w|\-]+)/edit/$', PostUpdateView.as_view(), name='post-edit'),
    url(r'^(?P<slug>[\w|\-]+)/delete/$', PostDeleteView.as_view(), name='post-delete'),


    url(r'^add_category/$', CategoryCreateView.as_view(), name='add-category'),
    url(r'^(?P<slug>[\w|\-]+)/$', PostDetailView.as_view(), name='post'),

    url(r'^category/(?P<category_name_slug>[\w\-]+)/$', CategoryDetailView.as_view(), name='category'),
    
]

【问题讨论】:

    标签: django


    【解决方案1】:

    是的。您缺少函数调用:

    url(r'^add_category/', views.CategoryCreateView.as_view(), name='add-category'),
    

    至于你的另一个问题,CreateViewFormView 非常相似,除了CreateViewFormView 的更具体的实现。

    FormView 真的是用来处理的:

    • 在 GET 上显示表单
    • 在 POST 上显示错误的表单
    • 当表单没有错误时重定向到不同的页面

    另一方面,CreateViewFormView 相同,只是它也这样做:

    • 假设它正在处理实现save() 方法的ModelForm 表单
    • 在重定向到其他页面之前,会调用表单的 save() 来创建模型
    • 创建的模型存储在self.object中,以便您可以在get_success_url中使用它来为创建的对象生成URL(例如重定向到对象详细信息页面)

    Classy 视图是检查 Django 基于类的视图的绝佳资源。以下是这两个课程的链接:

    https://ccbv.co.uk/projects/Django/1.9/django.views.generic.edit/FormView/ https://ccbv.co.uk/projects/Django/1.9/django.views.generic.edit/CreateView/

    查看我们的 form_valid 方法,您将看到最大的差异。

    至于选择使用哪个,我认为这完全取决于您的情况。如果您尝试通过ModelForm 创建模型实例,那么CreateView 可能更适合您,如果您正在做一些通用的事情,那么FormView 可能更适合。


    class IndexView(TemplateView):
        template_name = 'main/index.html'
    
        def get_context_data(self, **kwargs):
            context = super(IndexView, self).get_context_data(**kwargs)
            context.update({
                'latest_posts': Post.objects.all().order_by('-created_at'),
                'popular_posts': Post.objects.all().order_by('-views'),
                'hot_posts': Post.objects.all().order_by('-score')[:25],
                'categories': Category.objects.order_by('likes')[:5],
            })
            return context
    
    class PostDetailView(DetailView):
        model = Post
        context_object_name = 'single_post'
        template_name = 'main/post.html'
        # note that these are already "slug" by default
        pk_url_kwarg = 'slug'
        slug_field = 'slug'
    
        def get_object(self, queryset=None):
            obj = seuper(PostView, self).get_object(queryset)
            obj.views += 1
            obj.save()
            return obj
    
    class CategoryDetailView(DetailView):
        model = Category
        template_name = 'main/category.html'
        context_object_name = 'category'
        # note that these are already "slug" by default
        pk_url_kwarg = 'slug'
        slug_field = 'slug'
    
        def get_context_date(self, **kwargs):
            context = super(CategoryDetailView, self).get_context_data(**kwargs)
            context.update({
                # really no need to put category_name in context
                # as you can simply do {{ category.name }} in your template
    
                # you can use relations to query related data
                'posts': self.object.post_set.all()
            })
            return context
    

    【讨论】:

    • 谢谢,那我应该使用createView。人们是否仅仅因为它更简单而使用通用视图?DRY 原则?因为对于我的索引、类别、帖子视图,它们比我在上面发布的更复杂,而且我认为使用通用视图会变得更复杂。我将发布我的索引、类别、发布功能,如果您能看一看,我将不胜感激。
    • 如果您不确定要使用什么,我会推荐CreateView,因为它可以简化您的生活。一旦你使用它一段时间,你就会开始遇到一些限制,当你真的需要做一些自定义的事情时,我建议你开始使用更多的基类之一,比如FormView,甚至只是简单的View
    • 是的,我同意你的看法,你介意看看我的索引、类别、发布功能吗?我正在尝试将它们转换为通用视图,但我遇到了麻烦,因为它们具有更多功能跨度>
    • 在您粘贴的 3 个视图中,没有一个实际创建任何内容或使用表单。我建议您查看DetailView,这是您正在尝试做的事情。您可以在ccbv.co.uk/projects/Django/1.9/django.views.generic.detail/…docs.djangoproject.com/en/1.9/ref/class-based-views/… 中查看更多信息
    • 嗯,我调查了它,但仍然不确定我应该如何管理它们,例如在索引函数中,context_dict 中有多个,在帖子中有增加视图的函数,在类别中它会过滤掉属于其他类别的帖子
    猜你喜欢
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    • 1970-01-01
    • 2010-10-02
    • 2011-12-12
    • 2010-09-16
    • 2012-03-14
    • 2012-02-06
    相关资源
    最近更新 更多