1👍
Since you want "one url" and "single view", you can’t pass the relevant parameters in __init__
.
To handle that:
dal
(django-autocomplete-light) supportsforwarded
values, so you can use that to specify which model you want.- Use a static
config
withlambda
functions to define themodel
,model_query
andmodel_field_name
. - Override
model
andmodel_field_name
fields as properties.
This would be how you can implement it:
class AutocompleteHandler(autocomplete.Select2QuerySetView):
config = {
'Location': {
'model': Location,
},
'Society': {
'model': Society,
'model_query': lambda self: {'location_id__in': self.forwarded.get('preferred_area', None)},
},
'Property': {
'model': Property,
'model_query': lambda self: {'type__enq_code': self.request.session.get('enquiry_flag', 3)},
},
'Floor': {
'model': Floor,
'model_field_name': 'floor',
},
'Project': {
'model': Project,
},
}
def get_queryset(self):
if not self.request.user.is_authenticated:
return self.model.objects.none()
qs = self.model.objects.filter(**self.model_query)
qs = self.get_search_results(qs, self.q)
return qs
@property
def model(self):
return self.model_config['model']
@property
def model_config(self):
model_name = self.forwarded.get('m')
model_config = self.config.get(model_name)
if not model_config:
raise ValueError
return model_config
@property
def model_field_name(self):
return self.model_config.get('model_field_name', 'name')
@property
def model_query(self):
model_query = self.model_config.get('model_query')
if not model_query:
return {}
return model_query(self)
Usage:
from dal import autocomplete, forward
widgets = {
'location': autocomplete.ModelSelect2(
url='autocomplete-handler',
forward=(forward.Const('Location', 'm'),),
),
}
1👍
class GenericModelAutoComplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not seslf.request.user.is_authenticated:
return self.model.objects.none()
qs = self.qs or self.get_qs()
return self._get_queryset().filter(name__istartswith=self.q)
class FloorAutocomplete(GenericModelAutoComplete):
qs = Floor.objects.all()
class PropertyAutocomplete(GenericModelAutoComplete):
def get_qs(self):
enquiry_flag = self.request.session.get('enquiry_flag', 3)
return PropertyCategory.objects.filter(type__enq_code = enquiry_flag)
And so on, and with the same urls. Optionally, there is this: https://github.com/isik-kaplan/django-urls
Which you can use to simplify how your urls work with your views.
from django_urls import UrlManager
autocomplete = UrlManager()
class GenericModelAutoComplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not seslf.request.user.is_authenticated:
return self.model.objects.none()
qs = self.qs or self.get_qs()
return self._get_queryset().filter(name__istartswith=self.q)
def __init_subclass__(self, **kwargs):
# Automatically adds the view to autocomplete urlpatterns
cls = self.__class__
autocomplete.path(name=f"{cls.endpoint}-autocomplete")(cls)
return super().__init_subclass__(**kwargs)
class FloorAutocomplete(GenericModelAutoComplete):
qs = Floor.objects.all()
class PropertyAutocomplete(GenericModelAutoComplete):
def get_qs(self):
enquiry_flag = self.request.session.get('enquiry_flag', 3)
return PropertyCategory.objects.filter(type__enq_code = enquiry_flag)
# urls.py
from .views import autocomplete
urlpatterns = autocomplete.url_patterns
The second version is just 4-5 lines longer in the base view, but it saves you from writing a new url pattern for every view you have.
- [Django]-How to fix " '__proxy__' object has no attribute 'get' " when trying to update wrongly a form
- [Django]-How to use connection pooling for redis.StrictRedis?
- [Django]-Object is not iterable, but becomes iterable
- [Django]-Run Django commands on Elastic Beanstalk SSH -> Missing environment variables
1👍
You were almost there. In Django, you can override class attributes by providing arguments for the as_view
function, as explained in Django docs. To use that feature, you need to declare your parameters as class attributes instead of writing them in init:
class AutoCompleteHandler(autocomplete.Select2QuerySetView):
model = None
model_query = None
def get_queryset(self):
if not self.request.user.is_authenticated:
return self.model.objects.none()
enquiry_flag = self.request.session.get('enquiry_flag', 1)
qs = self.model.objects.filter(**self.model_query)
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
Then you can use your view in your urlpatterns
as such:
path('locations/', views.AutoCompleteHandler.as_view(model=Location, model_query={}), name='location-autocomplete'),
To add some more flexibility, you can define some getter functions for your parameters:
class AutoCompleteHandler(autocomplete.Select2QuerySetView):
model = None
model_query = None
def get_model(self):
if self.model is None:
raise ImproperlyConfigured("Some useful exception")
return self.model
def get_model_query(self):
model_query = {} if self.model_query is None else self.model_query
return model_query
def get_queryset(self):
model = self.get_model()
if not self.request.user.is_authenticated:
return model.objects.none()
enquiry_flag = self.request.session.get('enquiry_flag', 1)
qs = model.objects.filter(**self.get_model_query())
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
- [Django]-Sorl thumbnail + django issues in production
- [Django]-How to install mod_wsgi on Windows+XAMPP in 2017