web-dev-qa-db-fra.com

Django View basé sur la classe View avec formulaire

La vue principale est une simple liste de pages paginées et je souhaite ajouter un formulaire de recherche à celui-ci.

Je pensais que quelque chose comme ça ferait l'affaire:

class MyListView(ListView, FormView):
    form_class = MySearchForm
    success_url = 'my-sucess-url'
    model = MyModel
    # ...

Mais apparemment, je me suis trompé .. et je ne trouve pas comment le faire dans la documentation officielle.

Suggestions ?

28
h3.

Ces réponses ont beaucoup aidé à me diriger dans la bonne direction. Merci gars.

Pour ma mise en œuvre, j'avais besoin d'une vue de formulaire qui a renvoyé une liste de réception sur Get and Post. Je n'aime pas avoir à répéter le contenu de la fonction d'obtention, mais cela avait besoin de quelques changements. Le formulaire est maintenant disponible à partir de get_queryset maintenant avec Self.Form.

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
    # ...
30
AgentK

J'ai aussi jeté pour une solution appropriée. Mais je ne pouvais pas y trouver aucun aussi devait venir avec moi-même.

vues.py

class VocationsListView(ListView):

    context_object_name = "vocations"
    template_name = "vocations/vocations.html"
    paginate_by = 10

    def get_queryset(self):
        get = self.request.GET.copy()
        if(len(get)):
            get.pop('page')
        self.baseurl = urlencode(get)
        model = Vocation
        self.form = SearchForm(self.request.GET)
        filters = model.get_queryset(self.request.GET)
        if len(filters):
            model = model.objects.filter(filters)
        else:
            model = model.objects.all()
        return model



def get_context_data(self):
    context = super(VocationsListView, self).get_context_data()
    context['form'] = self.form
    context['baseurl']= self.baseurl
    return context

modèles.py

class Vocation(models.Model):
    title = models.CharField(max_length = 255)
    intro = models.TextField()
    description = models.TextField(blank = True)
    date_created = models.DateTimeField(auto_now_add = True)
    date_modified = models.DateTimeField(auto_now = True)
    created_by = models.ForeignKey(User, related_name = "vocation_created")
    modified_by = models.ForeignKey(User, related_name = "vocation_modified")

    class Meta:
        db_table = "vocation"

    @property
    def slug(self):
        return defaultfilters.slugify(self.title)

    def __unicode__(self):
        return self.title

    @staticmethod
    def get_queryset(params):

        date_created = params.get('date_created')
        keyword = params.get('keyword')
        qset = Q(pk__gt = 0)
        if keyword:
            qset &= Q(title__icontains = keyword)
        if date_created:
            qset &= Q(date_created__gte = date_created)
        return qset

donc, fondamentalement, j'ajoute ce morceau de code à chaque classe modèle, où je veux implémenter la fonctionnalité de recherche. En effet, les filtres pour chaque modèle doivent être préparés explicitement

@staticmethod
def get_queryset(params):

    date_created = params.get('date_created')
    keyword = params.get('keyword')
    qset = Q(pk__gt = 0)
    if keyword:
        qset &= Q(title__icontains = keyword)
    if date_created
        qset &= Q(date_created__gte = date_created)
    return qset

il prépare le filtre QSe que j'utilise pour récupérer les données du modèle

7
Azamat Tokhtaev

L'ajout de formulaires à l'index et les vues de la liste à l'aide de mixines est couverte de la documentation officielle .

La documentation recommande généralement de cette approche. Cela suggère de simplement écrire un peu plus de python et coder la vue manuellement.

1
Owen Brown

Des réponses précédentes, voici mon prise sur les points de vue que j'ai utilisés pour afficher le formulaire sur la même page que la liste de liste:

class IndexView(FormMixin, ListView):
    ''' Homepage: displays list of links, and a form used to create them '''
    template_name = "links/index.html"
    context_object_name = "links"
    form_class = LinkForm

    def get_queryset(self):
        return Links.objects.all()

def add_link(request):
    # Sole job of this function is to process the form when POSTed. 
    if request.method == "POST":
        form = LinkForm(request.POST)

        if form.is_valid():
            Links.objects.create(address=form.cleaned_data['address'])

        return HttpResponseRedirect('/')

Ensuite, la dernière chose est de lier la fonction Add_Link View à l'URL d'action du formulaire et que vous êtes prêt à partir, je pense.

1
lkostka

In Django 2.2 Vous pouvez le faire (cela fonctionne bien au moins avec un get- Demande):

from Django.views.generic import ListView
from Django.views.generic.edit import FormMixin

from .models import Property
from .forms import SearchForm

class ListPageView(FormMixin, ListView):
    template_name = 'property_list.html'
    model = Property
    form_class = SearchForm
    queryset = Property.objects.all()

Utilisez le FormMixin avant le ListView. Si vous souhaitez utiliser le SearchForm dans un TemplateView vous pouvez le faire:

from Django.views.generic.base import TemplateView
from Django.views.generic.edit import FormMixin

from .models import Property
from .forms import SearchForm

class HomePageView(FormMixin, TemplateView):
    template_name = 'home.html'
    form_class = SearchForm
0
didierCH