如何使用基于类的视图处理表单(通过 get 或 post)?
我正在尝试学习基于类的视图,因为详细信息或列表视图并不那么复杂。
我有一个搜索表单,我只想看看是否发送查询来显示结果。
这是函数代码(不是我的,来自 django 书籍):
def search_page(request):
form = SearchForm()
bookmarks = []
show_results = False
if 'query' in request.GET:
show_results = True
query = request.GET['query'].strip()
if query:
form = SearchForm({'query': query})
bookmarks = Bookmark.objects.filter(title__icontains=query)[:10]
show_tags = True
show_user = True
if request.is_ajax():
return render_to_response("bookmarks/bookmark_list.html", locals(), context_instance=RequestContext(request))
else:
return render_to_response("search/search.html", locals(), context_instance=RequestContext(request))
忽略 ajax 事实(只是为了让问题变得更容易),我如何将其转换为基于类的视图?
我很快尝试了这样的事情:
class SearchPageView(FormView):
template_name = 'search/search.html'
def get(self, request, *args, **kwargs):
form = SearchForm()
self.bookmarks = []
self.show_results = False
if 'query' in self.request.GET:
self.show_results = True
query = self.request.GET['query'].strip()
if query:
form = SearchForm({'query': query})
self.bookmarks = Bookmark.objects.filter(title__icontains=query)[:10]
return super(SearchPageView, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(SearchPageView, self).get_context_data(**kwargs)
context.update({
'show_tags': True,
'show_user': True,
'show_results': self.show_results,
'bookmarks': self.bookmarks
})
return context
不起作用,我得到一个:“'NoneType'对象不可调用”
公平地说,我今天开始使用这个东西。
那么,如何创建一个基于类的视图来管理 get(如果需要的话还可以管理 post)请求呢?
我还有另一个例子:
@render_to('registration/register.html')
def register_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
email=form.cleaned_data['email']
)
return HttpResponseRedirect('/accounts/register/success/')
else:
form = RegistrationForm()
return locals()
这会像第一个一样“转变”吗?或者他们提出了不同的观点?
我很困惑。我不知道第一个是 ProcessFormView,第二个是 FormView 还是什么。
谢谢。
编辑:我最终的解决方案:
class SearchPageView(FormView):
template_name = 'search/search.html'
def get(self, request, *args, **kwargs):
self.bookmarks = []
self.show_results = False
form = SearchForm(self.request.GET or None)
if form.is_valid():
self.show_results = True
self.bookmarks = Bookmark.objects.filter(title__icontains=form.cleaned_data['query'])[:10]
return self.render_to_response(self.get_context_data(form=form))
def get_context_data(self, **kwargs):
context = super(SearchPageView, self).get_context_data(**kwargs)
context.update({
'show_tags': True,
'show_user': True,
'show_results': self.show_results,
'bookmarks': self.bookmarks
})
return context
我把这个留给有同样问题的人:)
Im trying to learn class-based views, for a detail or list view is not that complicated.
I have a search form and I just want to see if I send a query to show up the results.
Here is the function code (is not mine, is from a django book):
def search_page(request):
form = SearchForm()
bookmarks = []
show_results = False
if 'query' in request.GET:
show_results = True
query = request.GET['query'].strip()
if query:
form = SearchForm({'query': query})
bookmarks = Bookmark.objects.filter(title__icontains=query)[:10]
show_tags = True
show_user = True
if request.is_ajax():
return render_to_response("bookmarks/bookmark_list.html", locals(), context_instance=RequestContext(request))
else:
return render_to_response("search/search.html", locals(), context_instance=RequestContext(request))
Ignoring the ajax fact (just to make the problem easier for now), how can I translate this to class-based views?
I quick tried something like this:
class SearchPageView(FormView):
template_name = 'search/search.html'
def get(self, request, *args, **kwargs):
form = SearchForm()
self.bookmarks = []
self.show_results = False
if 'query' in self.request.GET:
self.show_results = True
query = self.request.GET['query'].strip()
if query:
form = SearchForm({'query': query})
self.bookmarks = Bookmark.objects.filter(title__icontains=query)[:10]
return super(SearchPageView, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(SearchPageView, self).get_context_data(**kwargs)
context.update({
'show_tags': True,
'show_user': True,
'show_results': self.show_results,
'bookmarks': self.bookmarks
})
return context
Doesn't work, I get a: "'NoneType' object is not callable"
Fair enough, I started today with this stuff.
So, what's the way to make a Class-based views that can manage a get (and a post too if needed) request?
I have another example:
@render_to('registration/register.html')
def register_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
email=form.cleaned_data['email']
)
return HttpResponseRedirect('/accounts/register/success/')
else:
form = RegistrationForm()
return locals()
Would this be "transformed" the same way that the first one? Or they extend differents Views?
Im confused a lot. I don't know if the first is ProcessFormView and the second FormView or what.
Thanks.
EDIT: Solution I ended with:
class SearchPageView(FormView):
template_name = 'search/search.html'
def get(self, request, *args, **kwargs):
self.bookmarks = []
self.show_results = False
form = SearchForm(self.request.GET or None)
if form.is_valid():
self.show_results = True
self.bookmarks = Bookmark.objects.filter(title__icontains=form.cleaned_data['query'])[:10]
return self.render_to_response(self.get_context_data(form=form))
def get_context_data(self, **kwargs):
context = super(SearchPageView, self).get_context_data(**kwargs)
context.update({
'show_tags': True,
'show_user': True,
'show_results': self.show_results,
'bookmarks': self.bookmarks
})
return context
I leave this here to someone with same question :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
FormView< 的默认行为/code>
类是为
GET
请求显示未绑定的表单,并为POST
(或PUT
)请求绑定表单。如果绑定的表单有效,则调用form_valid
方法,该方法仅重定向到成功 url(由success_url
属性或get_success_url
定义) > 方法。您需要重写
form_valid
方法来创建新的User
,然后再调用超类方法来重定向到您的 成功 url。第一个例子与
FormView
的流程不太匹配,因为您没有处理带有POST
数据的表单,并且当表单有效时您不会执行任何操作。可以尝试扩展
TemplateView
,并将所有逻辑放入get_context_data
中。一旦您开始工作,您就可以将解析 GET 数据并将书签返回到其自己的方法中的代码分解。您可以考虑扩展
ListView
,但我认为除非您想对结果进行分页,否则没有任何真正的优势。The default behaviour of the
FormView
class is to display an unbound form forGET
requests, and bind the form forPOST
(orPUT
) requests. If the bound form is valid, then theform_valid
method is called, which simply redirects to the success url (defined by thesuccess_url
attribute or theget_success_url
method.This matches the example quite well. You need to override the
form_valid
method to create the newUser
, before calling the superclass method to redirect to the success url.Your first example does not match the flow of
FormView
so well, because you aren't processing a form withPOST
data, and you don't do anything when the form is valid.I might try extending
TemplateView
, and putting all the logic inget_context_data
.Once you get that working, you could factor the code that parses the GET data and returns the bookmarks into its own method. You could look at extending
ListView
, but I don't think there's any real advantage unless you want to paginate results.请注意,这里有一个答案(在 FormView form_valid 方法中更新上下文数据?)这样解决了这个问题:
这对我来说非常有效。 (与这个问题相同的问题)
如上所述,这不是我的解决方案,如果您想给某人学分,请转到链接中的答案并给这个人学分! (在 FormView form_valid 方法中更新上下文数据?)
Note, an answer here (Updating context data in FormView form_valid method?) solved this problem like this:
This worked perfect for me. (same issue as in this question)
As stated above, this is not my solution, if you want to give somebody credits, go to the answer in the link and give this person the credits! (Updating context data in FormView form_valid method?)