Как обрабатывать форму (через 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 (и сообщения, если это необходимо)?
У меня есть еще один пример:
@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 или что.
Спасибо.
EDIT: Решение, с которым я закончил:
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
Я оставляю это здесь кому-то с тем же вопросом:)
Ответы
Ответ 1
Поведение класса FormView
по умолчанию - отображать несвязанную форму для запросов GET
и привязать форму для POST
(или PUT
). Если связанная форма действительна, то вызывается метод form_valid
, который просто перенаправляет URL-адрес успеха (определяется атрибутом success_url
или get_success_url
).
Это хорошо подходит для примера. Вам необходимо переопределить метод form_valid
для создания нового User
, прежде чем вызывать метод суперкласса для перенаправления на URL-адрес успеха.
class CreateUser(FormView):
template_name = 'registration/register.html'
success_url = '/accounts/register/success/'
form_class = RegistrationForm
def form_valid(self, form):
user = User.objects.create_user(
username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
email=form.cleaned_data['email']
)
return super(CreateUser, self).form_valid(form)
Ваш первый пример не соответствует потоку FormView
так хорошо, потому что вы не обрабатываете форму с данными POST
, и вы ничего не делаете, когда форма действительна.
Я могу попробовать расширить TemplateView
и поместить всю логику в get_context_data
.
Как только вы получите эту работу, вы можете указать код, который анализирует данные GET и возвращает закладки в свой собственный метод. Вы можете посмотреть расширение ListView
, но я не думаю, что есть какое-либо реальное преимущество, если вы не хотите разбивать на страницы результаты.
Ответ 2
Обратите внимание, что ответ здесь (Обновление данных контекста в FormView form_valid method?) решил эту проблему следующим образом:
class ContextFormView(FormView):
template_name = 'some_template.html'
success_url = '...'
form_class = ClassOfTheForm
def get(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
context = self.get_context_data(**kwargs)
context['form'] = form
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
return self.form_valid(form, **kwargs)
else:
return self.form_invalid(form, **kwargs)
def form_invalid(self, form, **kwargs):
context = self.get_context_data(**kwargs)
context['form'] = form
# here you can add things like:
context[show_results] = False
return self.render_to_response(context)
def form_valid(self, form, **kwargs):
context = self.get_context_data(**kwargs)
context['form'] = form
# here you can add things like:
context[show_results] = True
return self.render_to_response(context)
Это работало идеально для меня. (тот же вопрос, что и в этом вопросе)
Как указано выше, это не мое решение, если вы хотите дать кому-то кредиты, зайдите в ответ по ссылке и дайте этому человеку кредиты! (Обновление данных контекста в FormView form_valid method?)