Python 将多个视图优化为一个视图-Django

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=

我使用动态加载数据以在HTML表单中显示

我想将下面的url优化为一个url,并将其视图类优化为单个视图,因为大多数代码(90%的代码)在所有视图中都是通用的,只有少数参数不同

这是我的
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
    

    @格温比尔德——事实上,我喜欢你的答案,因为它更灵活。但公认的答案更准确,因为它只需要很少的修改。我希望我能把赏金分给你们两个。