Как использовать один и тот же класс ListView для разных моделей?
Есть 3 модели (компании, подразделения и штабные группы) для отображения в виде списка.
Я пытаюсь создать базовый класс представления, расширенный из ListView, чтобы перечислять различные модели, передавая имя модели в шаблонах URL.
Я создал отдельный класс представления для каждой модели, но там по сути копи-паст коды. Есть ли способ упростить код до одного класса и получить модель из urlpath.
models.py
from django.db import models
...
class Company(models.Model):
id = models.CharField(max_length=5, primary_key=True)
name = models.CharField(max_length=100)
is_active = models.BooleanField()
...
class Division(models.Model):
id = models.CharField(max_length=5, primary_key=True)
name = models.CharField(max_length=100)
is_active = models.BooleanField()
...
class StaffGroup(models.Model):
name = models.CharField(max_length=20)
is_active = models.BooleanField()
...
urls.py
from django.urls import path
from srrp.views import srrpIndexView, srrpListView
app_name = 'srrp'
urlpatterns = [
path('', srrpIndexView.as_view(), name='srrp_index'),
path('<str:modelname>', srrpListView.as_view(), name='srrp_list'),
]
views.py
class srrpListView(ListView):
template_name = 'srrp/srrplist.html'
model = self.kwargs['modelname'] # I know this is wrong, this is just placeholder for the right solution
paginate_by = 10
Подкласс get_queryset. (Закладка Виды, основанные на классах)
def get_queryset(self):
model = self.kwargs['modelname']
if model == 'foo':
return Foo.objects.all()
if model == 'bar':
return Bar.objects.all()
if model == 'green_bar':
return Bar.objects.filter( colour='green' )
...
raise ValueError(
f'This shouldn't be possible: model = "{model}"'
Если вам не нужны "специальные" модели, вы можете либо найти нужную модель в дикте классов:
klass = MODEL_CLASSES[model] # KeyError if bad model in URL
return klass.objects.all()
Или вы можете использовать функцию Django, название которой я забыл, чтобы получить класс модели по имени приложения и модели.
Решено.
views.py
class srrpListView(ListView):
template_name = 'srrp/srrplist.html'
paginate_by = 10
def get_queryset(self):
modelname = self.kwargs['modelname']
ctype = ContentType.objects.get(app_label='srrp', model=modelname)
model = ctype.model_class()
return model.objects.all()