Last active
August 17, 2019 10:39
-
-
Save simo97/164e73dc4a4bc66d1ca64332c7192300 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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