Skip to content

Instantly share code, notes, and snippets.

@simo97
Last active August 17, 2019 10:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simo97/164e73dc4a4bc66d1ca64332c7192300 to your computer and use it in GitHub Desktop.
Save simo97/164e73dc4a4bc66d1ca64332c7192300 to your computer and use it in GitHub Desktop.
from django.db.models import Q
from django.contrib import messages
class SearchViewMixin:
"""
this mixins allow a class based view to handle dynamically and automatically
a search. It add a GET param name as 's' which hold the searched term, and use
lookup_fields = [] to perform search
WARNING : At the moment this method fail silenty
Should be used only with a ListView class
How it work :
- Let your view inherit from this mixins
- Add lookup_fields as a method of your class and assign a list of fields you want to perform the search into
- In your template just add a form as follow (May be in future i will add this directly into this mixin's code):
<form action="{% url 'YOUR_URL_HERE' %}" method='GET'>
<input type='text' name='s' />
<input type='submit' value='search' />
</form>
- The search result is available directly in your self.context_object_name context var within the template
Example :
class ArticleListView(SearchViewMixin, ListView):
lookup_fields = ['ATTRIBUTE_1', 'ATTRIBUTE_2',]
pass
"""
_search_term = ''
_lookup_expression = 'icontains'
def _is_search(self):
if 's' in self.request.GET:
self._search_term = self.request.GET['s']
return True
else:
return False
def is_searchable(self):
"""
verify if the current model can accept automatic search, following this mixin rules
"""
return hasattr(self, 'lookup_fields') and type(self.lookup_fields) == list and len(self.lookup_fields) > 0
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self._is_search():
if self.is_searchable():
lookup = '{}__{}'.format(self.lookup_fields, self._lookup_expression)
__lookup_dir = {}
Qr = None
# build the search query with Q object based on the list of lookup field
for item in self.lookup_fields:
__lookup_dir = {}
__lookup_dir[
'{}__{}'.format(item, self._lookup_expression)
] = self._search_term
q = Q(**__lookup_dir)
if Qr:
Qr = Qr | q
else:
Qr = q
context[self.context_object_name] = self.model.objects.filter(Qr)
return context
class MessageWinErrorMixin:
"""
Working on a project (even a legacy code) and you want to quickly add default feedback messages
to all your class based view which handle forms, just add this mixins and you're done !!!
example :
class MyFormClass(FormView, MessageWinErrorMixin):
pass
"""
def form_valid(self, data):
messages.success(self.request, 'Operation successful !')
return super().form_valid(data)
def form_invalid(self, error):
messages.error(self.request, 'Sorry !!! An error occur when processing the form. {}'.format(error.errors))
return super().form_invalid(error)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment