Вопрос или проблема
проблема
У меня есть две модели (ModelB
, ModelC
), связанные с другой (ModelA
). Я хочу показать все объекты ModelC
, связанные с тем же объектом ModelA
, что и ModelB
, на странице администратора ModelB
.
модели
class ModelA(models.Model):
# ...
class ModelB(models.Model):
# ...
model_a = models.OneToOneField(ModelA)
class ModelC(models.Model):
# ...
models_a = models.ManyToManyField(ModelA)
админ
class ModelCInline(admin.StackedInline):
model = ModelC
class ModelBAdmin(admin.ModelAdmin):
inlines = (ModelCInline,)
# ...
Я экспериментировал с инлайнами, но так и не нашел решения.
Ответ или решение
Для решения вашей задачи по отображению всех объектов ModelC
, связанных с тем же объектом ModelA
, что и объект ModelB
, на странице администратора ModelB
, необходимо внести некоторые изменения в ваш код.
Во-первых, связки между моделями в ваших классах установлены следующим образом: ModelB
имеет однонаправленное отношение OneToOne
к ModelA
, а ModelC
имеет двунаправленное отношение ManyToMany
к ModelA
. Это значит, что для объекта ModelB
вы можете получить связанный объект ModelA
, а затем на его основе извлечь все соответствующие объекты ModelC
.
Вот как вы можете это сделать:
Модели
Убедитесь, что ваши модели выглядят как в вашем примере:
from django.db import models
class ModelA(models.Model):
# Поля вашей модели ModelA
pass
class ModelB(models.Model):
model_a = models.OneToOneField(ModelA, on_delete=models.CASCADE)
class ModelC(models.Model):
models_a = models.ManyToManyField(ModelA)
Админская часть
Вам нужно создать ModelCInline
, который будет фильтровать объекты ModelC
по связанному ModelA
для текущего объекта ModelB
.
from django.contrib import admin
from .models import ModelB, ModelC, ModelA
class ModelCInline(admin.TabularInline): # Вы можете использовать StackedInline, если нужно
model = ModelC
extra = 0
def get_queryset(self, request):
qs = super().get_queryset(request)
# Получаем объект ModelA, связанный с текущим объектом ModelB
model_b_id = request.resolver_match.kwargs.get('object_id')
try:
model_b = ModelB.objects.get(id=model_b_id)
return qs.filter(models_a=model_b.model_a)
except ModelB.DoesNotExist:
return qs.none() # Если объект ModelB не найден, возвратите пустой QuerySet
class ModelBAdmin(admin.ModelAdmin):
inlines = (ModelCInline,)
# Другие настройки вашего ModelBAdmin
admin.site.register(ModelB, ModelBAdmin)
admin.site.register(ModelC) # Регистрируем ModelC, если еще не зарегистрирована
admin.site.register(ModelA) # Регистрируем ModelA, если еще не зарегистрирована
Объяснение кода
-
ModelCInline:
- Мы переопределяем метод
get_queryset
, чтобы вернуть только те объектыModelC
, которые связаны с объектомModelA
, на который ссылается текущий объектModelB
. - Если объект
ModelB
не найден, метод возвращает пустойQuerySet
, чтобы избежать ошибок.
- Мы переопределяем метод
-
ModelBAdmin:
- Включает
ModelCInline
для отображения связанных объектовModelC
.
- Включает
Теперь, когда вы зайдете в интерфейс администратора для ModelB
, вы увидите все связанные объекты ModelC
, которые имеют ту же связь с ModelA
, что и текущий ModelB
.
Это решение должно полностью удовлетворить ваши требования. Если у вас есть дополнительные вопросы или требуется дальнейшая помощь, пожалуйста, дайте знать!