Django - Проблема с менеджером моделей - Запрос
Я все еще новичок и застрял в сложном для меня месте. Я не могу добиться того, чтобы данные из таблицы с внешним ключом "правильно" вставлялись в столбец ListView.
В основном я хочу создать представление списка в таблице (FeatureFilm). Это тоже работает. Но в одном столбце я получаю информацию из другой таблицы, а здесь я получаю данные, но не те, которые принадлежат конкретной строке таблицы.
Вот мои модели. Таблица, которую я хочу показать, это модель "FeatureFilm". Эта модель наследуется от моего базового класса Project "ProjectBaseModel". Затем есть еще одна таблица "CompanyInvolved Model". Она присоединена к таблице FeatureFilm с внешним ключом (feature_id).
Хранятся фильмы (FeatureFilm), и в процесс создания фильмов вовлечены различные компании. (CompanyInvolved)
class ProjectBaseModel(models.Model):
title = models.CharField("Titel", max_length=100, blank=False, unique=True)
leading_postproduction_id = models.ForeignKey(
Company,
verbose_name="Federführende Postproduktion",
on_delete=models.SET_NULL,
blank=True,
null=True,
)
phase = models.CharField(choices=post_phase, max_length=30, blank=True, null=True)
former_title = models.CharField("Titel, ehemalig", max_length=100, blank=True)
title_international = models.CharField(
"Titel, international", max_length=100, blank=True, null=True, unique=True
)
class FeatureFilm(ProjectBaseModel):
class Meta:
verbose_name = "Kinofilm"
verbose_name_plural = "Kinofilme"
ordering = ["title"]
class ProductionManager(models.Manager):
def get_production(self):
return (
super()
.get_queryset()
.filter(company_role="Produktion", is_production_list=True)
.values_list("company_involved__name")
)
class CompanyInvolved(models.Model):
feature_id = models.ForeignKey(
FeatureFilm,
on_delete=models.CASCADE,
null=True,
blank=True,
)
tv_movie_id = models.ForeignKey(
TvMovie, on_delete=models.CASCADE, null=True, blank=True
)
company_role = models.CharField(
choices=company_role,
max_length=15,
blank=True,
help_text="Produktion, Co-Produktion, Kinoverleiher, Sender, Weltvertrieb",
)
company_involved = models.ForeignKey(
Company,
on_delete=models.SET_NULL,
null=True,
blank=True,
)
is_production_list = models.BooleanField(
default=False,
verbose_name="Produktion in Liste",
)
productionmanager = ProductionManager()
def __str__(self):
return "#" + str(self.pk)
class Meta:
verbose_name = "Produktion, Co-Produktion, Verleih, Sender, Weltvertrieb"
verbose_name_plural = "Produktion, Co-Produktion, Verleih, Sender, Weltvertrieb"
ordering = ["pk"]
В основном я хотел генерировать вывод сейчас через шаблон. Я могу итерировать строки с помощью шаблона for loop. Но я также узнал, что более сложные запросы не работают в языке DjangoTemplate, или просто им там не место. Мне не нужны все строки данных из CompanyInvolved, а только company_role = "Production" и is_production_list = True. Комбинированный пункт "Where" в шаблоне сейчас хорош, но его не существует, поэтому я создал себе МЕНЕДЖЕР МОДЕЛИ (ProductionManager), который делает эту фильтрацию в модели.
вот вид:
class FeatureListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
permission_required = "project.can_access_featurefilm_list"
model = FeatureFilm
template_name = "project/feature-list.html"
def handle_no_permission(self):
return redirect("access-denied")
здесь находится зависимый фрагмент в шаблоне:
<tbody>
{% for project in object_list %}
<tr>
<td><a href="{% url 'feature-detail-date' project.pk %}">{{ project.title }}</a></td>
<td>{{ project.companyinvolved_set.get_production }}
<br>
</td>
<td>{% if project.program_length_planned %}
{{ project.program_length_planned }}
{% endif %}
</td>
<td>{{ project.global_shooting_resolution }}</td>
<td>{{ project.global_resolution_theatrical }}</td>
<td>{% if project.hdr == 1%}
ja
{% else %}
nein
{% endif %}
</td>
<td>{{ project.stafflist.postproduction_supervisor_id.username }}</td>
<td>{% if project.phase %}
{{ project.phase }}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
Итак, я перебираю каждый кинопроект с помощью {% for project in object_list %} и затем я хочу показать в колонке "проблема" компанию, которая имеет роль production, а так как их может быть несколько, то ту, которая была ранее отмечена пользователем для просмотра списков - > is_production_list = TRue и тогда вывод должен получиться: {{ project.companyinvolved_set.get_production }}.
Результат движется в правильном направлении, но он все еще не окончательно корректен. Я получаю данные CompanyINvolved и они также отфильтрованы по company_role = "Production" и is_production_list = True , но эти значения теперь отображаются мне каждый раз в каждой отдельной строке одинаково, я получаю не по ROW связанных с ними производств, а просто каждый раз ВСЕ. Мне не хватает ссылки на объект FeatureFilm, но я не знаю, как теперь ее получить, или куда теперь эту ссылку поместить?
Я думаю, что ваш код не работает, потому что get_production
вызывает super().get_queryset()
, который возвращает новый QuerySet
, без примененных фильтров, не основанный на Queryset в обратном поиске в companyinvolved_set
Я думаю, что лучше всего поместить эту логику либо в класс FeatureListView
, либо в класс FeatureFilm
, в зависимости от того, нужно ли вам повторно использовать этот вид поиска или нет.
Для FeatureListView вы можете переопределить get_queryset
чем-то вроде этого (Здесь могут быть ошибки, я не могу проверить прямо сейчас):
class FeatureListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
permission_required = "project.can_access_featurefilm_list"
model = FeatureFilm
template_name = "project/feature-list.html"
def handle_no_permission(self):
return redirect("access-denied")
def get_queryset(self):
return FeatureFilm.objects.annotate(
production_companies=FilteredRelation(
'company_involved', condition=(Q(company_involved__company_role='Production') & Q(company_involved__is_production_list=True))
)
).all()
Тогда вы должны быть в состоянии перебирать производственные_компании в вашем шаблоне:
<td>{% for production in project.production_companies %}production.company_involved.name{% endfor %}</td>