Как обработать форму (через get или post), используя представления на основе классов? - PullRequest
33 голосов
/ 18 января 2012

Я пытаюсь изучить представления на основе классов, для детализации или представления списка это не так сложно.

У меня есть форма поиска, и я просто хочу посмотреть, отправляю ли я запрос, чтобы показать результаты.

Вот код функции (не мой, взят из книги 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 или что.

Спасибо.

РЕДАКТИРОВАТЬ: Решение, которое я закончил:

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

Я оставляю это здесь кому-то с таким же вопросом:)

Ответы [ 2 ]

26 голосов
/ 18 января 2012

Поведение по умолчанию класса 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, но я не думаю, что есть какое-то реальное преимущество, если толькоВы хотите разбить результаты на страницы.

9 голосов
/ 04 января 2015

Обратите внимание, ответ здесь ( Обновление контекстных данных в методе FormView form_valid? ) решило эту проблему следующим образом:

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? )

...