The main view is a simple paginated ListView and I want to add a search form to it.
I thought something like this would do the trick:
class MyListView(ListView, FormView): form_class = MySearchForm success_url = 'my-sucess-url' model = MyModel # ...
But apparently I got it wrong .. and I can't find how to do it in the official documentation.
Suggestions ?
For Django class-based views we access an appropriate view function by calling the class method as_view() . This does all the work of creating an instance of the class, and making sure that the right handler methods are called for incoming HTTP requests.
To decorate every instance of a class-based view, you need to decorate the class definition itself. To do this you apply the decorator to the dispatch() method of the class. The decorators will process a request in the order they are passed to the decorator.
object_list will contain the list of objects (usually, but not necessarily a queryset) that the view is operating upon. Ancestors (MRO) This view inherits methods and attributes from the following views: django.
Model form views provide a form_valid() implementation that saves the model automatically. You can override this if you have any special requirements; see below for examples. You don't even need to provide a success_url for CreateView or UpdateView - they will use get_absolute_url() on the model object if available.
These answers have helped so much to steer me in the right direction. Thank guys.
For my implementation I needed a form view that returned a ListView on both get and post. I don't like having to repeat the contents of the get function but it needed a couple of changes. The form is now available from get_queryset now too with 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 # ...
I've been seaching for a proper solution too. But I could not find any so had to come up with my own.
views.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
models.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
so basically I add this piece of code to every model class, where I want implement the search functionality. This is because filters for the every model have to be prepared explicitly
@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
it prepares the qset filter that I use to retrieve the data from the model
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With