Reputation:
In the official documentation, formView is A view that displays a form. On error, redisplays the form with validation errors; on success, redirects to a new URL. createView is A view that displays a form for creating an object, redisplaying the form with validation errors (if there are any) and saving the object. //(maybe my English isn't good enough)So if I want to make a generic view that users to create a new category I should use createview over formview right? I wasn't sure, so I tried both ways and both of them gives me same error:as_view() takes exactly 1 argument (2 given)
With form view:
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
with createView
#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)
Finally this is my urls.py
url(r'^add_category/', views.CategoryCreateView.as_view, name='add-category'),
Edit: sorry it works, just forgot to put parenthesis next to url, but can you please tell me the difference between createview and formview? when should use what?
Edit2:
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)
Edit 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'),
]
Upvotes: 9
Views: 5515
Reputation: 27861
Yes. You were missing function call in:
url(r'^add_category/', views.CategoryCreateView.as_view(), name='add-category'),
As for your other question, CreateView
and FormView
are pretty similar, except CreateView
is more specific implementation of FormView
.
FormView
is really meant to handle:
CreateView
on the other hand is identical to FormView
except it does this as well:
ModelForm
form which implements save()
methodsave()
is called which creates the modelself.object
so that you can use it in get_success_url
to generate a URL for the created object (e.g. redirect to object detail page)Classy views is an awesome resource to inspect Django class-based-views. Here are links for both classes:
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/
Check our the form_valid
methods where you will see the biggest diff.
As for picking which to use, I think it all depends on your scenario. If you are trying to create model instances via ModelForm
then CreateView
is probably better for you and if you are doing something generic then FormView
is probably a better fit.
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
Upvotes: 17