Python 将多个视图优化为一个视图-Django
我使用动态加载数据以在HTML表单中显示 我想将下面的url优化为一个url,并将其视图类优化为单个视图,因为大多数代码(90%的代码)在所有视图中都是通用的,只有少数参数不同 这是我的Python 将多个视图优化为一个视图-Django,python,django,Python,Django,我使用动态加载数据以在HTML表单中显示 我想将下面的url优化为一个url,并将其视图类优化为单个视图,因为大多数代码(90%的代码)在所有视图中都是通用的,只有少数参数不同 这是我的url.py: path('locations/', views.LocationAutocomplete.as_view(), name='location-autocomplete'), path('societies/', views.SocietyAutocomplete.as_view(), name=
url.py
:
path('locations/', views.LocationAutocomplete.as_view(), name='location-autocomplete'),
path('societies/', views.SocietyAutocomplete.as_view(), name='society-autocomplete'),
path('propcats/', views.PropertyCategoryAutocomplete.as_view(), name='propcat-autocomplete'),
...
path('projects/', views.ProjectAutocomplete.as_view(), name='project-autocomplete'),
class LocationAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return Location.objects.none()
qs = Location.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
class SocietyAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return Society.objects.none()
preferred_area = self.forwarded.get('preferred_area', None)
qs = Society.objects.filter(location_id__in=preferred_area)
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
class PropertyCategoryAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return PropertyCategory.objects.none()
enquiry_flag = self.request.session.get('enquiry_flag', 3)
qs = PropertyCategory.objects.filter(type__enq_code = enquiry_flag)
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
class FloorAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return Floor.objects.none()
qs = Floor.objects.all()
if self.q:
qs = qs.filter(floor__istartswith=self.q)
return qs
class ProjectAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return Project.objects.none()
qs = Project.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
以下是来自Views.py的视图:
path('locations/', views.LocationAutocomplete.as_view(), name='location-autocomplete'),
path('societies/', views.SocietyAutocomplete.as_view(), name='society-autocomplete'),
path('propcats/', views.PropertyCategoryAutocomplete.as_view(), name='propcat-autocomplete'),
...
path('projects/', views.ProjectAutocomplete.as_view(), name='project-autocomplete'),
class LocationAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return Location.objects.none()
qs = Location.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
class SocietyAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return Society.objects.none()
preferred_area = self.forwarded.get('preferred_area', None)
qs = Society.objects.filter(location_id__in=preferred_area)
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
class PropertyCategoryAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return PropertyCategory.objects.none()
enquiry_flag = self.request.session.get('enquiry_flag', 3)
qs = PropertyCategory.objects.filter(type__enq_code = enquiry_flag)
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
class FloorAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return Floor.objects.none()
qs = Floor.objects.all()
if self.q:
qs = qs.filter(floor__istartswith=self.q)
return qs
class ProjectAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated:
return Project.objects.none()
qs = Project.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
我尝试过类似的方法,但不确定如何传递其他相关参数,如数据库查询参数、模型名称等
class AutoCompleteHandler(autocomplete.Select2QuerySetView):
def __init__(self, model, model_query, *args, **kwargs):
super().__init__(*args, **kwargs)
self.model = model
self.model_query = model_query
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
有人能帮我优化上面的代码吗
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)
以此类推,并使用相同的URL。或者,有以下几种:
您可以使用它来简化URL如何与视图一起工作
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
第二个版本在基本视图中仅长4-5行,但它可以避免为每个视图编写新的url模式。由于您需要“一个url”和“单个视图”,因此无法在\uuuu init\uuu
中传递相关参数
要处理这个问题:
dal
(django自动完成指示灯)支持转发的值,因此您可以使用该值指定所需的型号
使用带有lambda
函数的静态config
来定义模型
、模型查询
和模型字段名
将model
和model\u field\u name
字段重写为属性
这将是您实现它的方式:
类自动完成处理程序(自动完成。选择2QuerySetView):
配置={
“地点”:{
“模型”:位置,
},
“社会”:{
"模范":社会,,
'model_query':lambda self:{'location_id_uuin':self.forwarded.get('preferred_area',None)},
},
“财产”:{
“模型”:属性,
'model_query':lambda self:{'type_enq_code':self.request.session.get('inquiry_flag',3)},
},
“地板”:{
“模型”:地板,
“型号字段名称”:“楼层”,
},
“项目”:{
“模型”:项目,
},
}
def get_queryset(自我):
如果未对self.request.user.u进行身份验证:
返回self.model.objects.none()
qs=self.model.objects.filter(**self.model\u查询)
qs=self.get\u搜索结果(qs,self.q)
返回qs
@财产
def型号(自):
返回self.model_config['model']
@财产
def型号配置(自):
model_name=self.forwarded.get('m')
model\u config=self.config.get(model\u名称)
如果不是型号配置:
升值误差
返回模型配置
@财产
def型号字段名称(自身):
返回self.model\u config.get('model\u field\u name','name')
@财产
def模型_查询(自):
model\u query=self.model\u config.get('model\u query')
如果不是model_查询:
返回{}
返回模型查询(self)
用法:
从dal导入自动完成,向前
小部件={
“位置”:autocomplete.ModelSelect2(
url='autocomplete-handler',
forward=(forward.Const('Location','m'),),
),
}
你就快到了。在Django中,可以通过为as\u view
函数提供参数来覆盖类属性,如中所述。要使用该功能,您需要将参数声明为类属性,而不是在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
然后,您可以在urlpatterns
中使用视图,如下所示:
path('locations/', views.AutoCompleteHandler.as_view(model=Location, model_query={}), name='location-autocomplete'),
要增加更多灵活性,可以为参数定义一些getter函数:
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
@格温比尔德——事实上,我喜欢你的答案,因为它更灵活。但公认的答案更准确,因为它只需要很少的修改。我希望我能把赏金分给你们两个。