首页 > 解决方案 > 将多个视图优化为一个视图 - Django

问题描述

我正在使用django-autocomplete-light 小部件动态加载数据以显示在 HTML 表单中。

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

这是我的urls.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'),

以下是其观点views.py

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

谁能帮我优化上面的代码?

标签: pythondjango

解决方案


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)

依此类推,并且使用相同的网址。可选地,有这个:https ://github.com/isik-kaplan/django-urls

您可以使用它来简化您的 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 模式。


推荐阅读