接受Django ListView中的输入

时间:2016-10-22 10:27:43

标签: django

在Django网站上,我有一个分页ListView,其中显示了某些对象的列表,每页100个。

我想在此页面上包含一个文本框并接受+处理用户输入。但是在Django中,这需要我:

i)使用FormView(在这种情况下我会失去分页)或

ii)编写基于函数的视图,我手动处理分页和表单处理。

是否有第三种方法可以实现我想要做的事情,理想情况下不会破坏ListView

2 个答案:

答案 0 :(得分:2)

在我看来,每个观点应该有一个目的。并不意味着您不能在单个页面中拥有多个表单元素。你可以通过

来做到这一点

制作一个只处理数据的普通视图。您可以设置视图的URL,然后对该视图进行ajax调用。如果您也愿意使用JavaScript,这很容易实现。(简单的xhr方法,模糊,更改事件)

例如: -

class FormElementProcess(View):
    def post(self,request,*args,**kwargs):
        #Do your processing and return httpresponse

如果还使用了表单类,您可以进一步自定义上面的类,并使用表单视图来处理和返回表单数据。

这就是我猜的方法。假设我的主页上有几十种表格。形式如 - >搜索,登录,注册等。我不会通过我的IndexView处理所有事情。当应用程序规模扩大时,这会使一切变得复杂。

2)如果页面刷新,那么我建议你使用FormMixin。 我发现了一个很好的实现 FormListView

from django.http import Http404
from django.utils.translation import ugettext as _
from django.views.generic.edit import FormMixin
from django.views.generic.list import ListView

class FormListView(FormMixin, ListView):
    def get(self, request, *args, **kwargs):
        # From ProcessFormMixin
        form_class = self.get_form_class()
        self.form = self.get_form(form_class)

        # From BaseListView
        self.object_list = self.get_queryset()
        allow_empty = self.get_allow_empty()
        if not allow_empty and len(self.object_list) == 0:
            raise Http404(_(u"Empty list and '%(class_name)s.allow_empty' is False.")
                          % {'class_name': self.__class__.__name__})

        context = self.get_context_data(object_list=self.object_list, form=self.form)
        return self.render_to_response(context)

    def post(self, request, *args, **kwargs):
        return self.get(request, *args, **kwargs)


class MyListView(FormListView):
    form_class = MySearchForm
    model = MyModel
    # ...

Detailed Code Explanation

您可以进一步修改post方法来进行处理。您可以直接使用表单类,包括请求处理的参数。

答案 1 :(得分:1)

使用基于函数的视图来实现所需的示例如下:

联系人/ models.py:

from django.db import models
from django.utils.encoding import python_2_unicode_compatible


@python_2_unicode_compatible
class Contact(models.Model):
    email = models.EmailField(unique=True)
    first_name = models.CharField(max_length=40, blank=True)
    last_name = models.CharField(max_length=40, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.email

联系人/ forms.py:

from django import forms


class UserForm(forms.Form):
    search = forms.CharField(label='Search', max_length=100)

联系人/ views.py:

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render, redirect
from .models import Contact
from .forms import UserForm


def my_contacts(request):
    form = UserForm()
    if request.method == 'POST':
        form = UserForm(request.POST)
        if form.is_valid():
            # Do something with form data here
            print(form.cleaned_data['search'])
        redirect('my_contacts')

    contacts_list = Contact.objects.all()
    page = request.GET.get('page', 1)

    paginator = Paginator(contacts_list, 10)
    try:
        contacts = paginator.page(page)
    except PageNotAnInteger:
        contacts = paginator.page(1)
    except EmptyPage:
        contacts = paginator.page(paginator.num_pages)

    return render(request, 'contacts/contacts.html', {'contacts': contacts, 'form': form})

联系人/ urls.py:

from django.conf.urls import patterns, url

urlpatterns = patterns(
   'contacts.views',
    url(r'^$', 'my_contacts', name='my_contacts'),
)

<强>模板/联系人/ contacts.html:

{% extends 'base.html' %}

{% block 'container' %}
<div class="row">
  <div class="col-sm-12">
    <form action="" method="post">
      {% csrf_token %}
      {{ form }}
      <input type="submit" value="Submit" />
    </form>
  </div>
</div>
<div class="row">
<div class="col-sm-12">
<table class="table table-bordered">
  <thead>
    <tr>
      <th>Email</th>
      <th>First name</th>
      <th>Last name</th>
    </tr>
  </thead>
  <tbody>
    {% for contact in contacts %}
      <tr>
        <td>{{ contact.email }}</td>
        <td>{{ contact.first_name }}</td>
        <td>{{ contact.last_name }}</td>
      </tr>
    {% endfor %}
  </tbody>
</table>

{% if contacts.has_other_pages %}
  <ul class="pagination">
    {% if contacts.has_previous %}
      <li><a href="?page={{ contacts.previous_page_number }}">&laquo;</a></li>
    {% else %}
      <li class="disabled"><span>&laquo;</span></li>
    {% endif %}
    {% for i in contacts.paginator.page_range %}
      {% if contacts.number == i %}
        <li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
      {% else %}
        <li><a href="?page={{ i }}">{{ i }}</a></li>
      {% endif %}
    {% endfor %}
    {% if contacts.has_next %}
      <li><a href="?page={{ contacts.next_page_number }}">&raquo;</a></li>
    {% else %}
      <li class="disabled"><span>&raquo;</span></li>
    {% endif %}
  </ul>
{% endif %}
</div>
</div>
{% endblock %}

<强>模板/ base.html文件:

{% load static %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>{% block 'title'%}{% endblock %}</title>
    <!-- Bootstrap Core CSS -->
    <link href={% static 'css/bootstrap.min.css' %} rel="stylesheet">
</head>
<body>
    <!-- Page Content -->
    <div class="container" style="padding-top: 50px;">
        {% block 'container' %}{% endblock %}
    </div>
    <!-- /.container -->

    <script src="{% static 'js/jquery.js' %}"></script>
    <!-- Bootstrap Core JavaScript -->
    <script src="{% static 'js/bootstrap.min.js' %}"></script>
</body>
</html>