Расширенная модель Django
У меня есть 2 модели. В одной из них я хочу выводить общую информацию, а в другой - расширенную. Я хочу, чтобы модели объединяло поле service_id.
В модели AdvancedService у меня есть 2 объекта с одним service_id. В модели Service, когда я нажимаю на service_id, я хочу просмотреть 2 объекта с таким service_id. Однако я не понимаю, как это можно сделать. Мой код:
#models.py
class ServiceModel(models.Model):
service_id = models.CharField(max_length=150)
total_cars = models.PositiveIntegerField() # bmw + audi
repaired = models.PositiveIntegerField() # broken_motor + broken_body
advanced = models.ForeignKey(
'AdvancedServiceModel', on_delete=models.CASCADE)
class AdvancedServiceModel(models.Model):
service_id = models.CharField(max_length=150)
bmw = models.PositiveIntegerField()
audi = models.PositiveIntegerField()
broken_motor = models.PositiveIntegerField()
broken_body = models.PositiveIntegerField()
def __str__(self) -> str:
return f'{self.service_id}'
#admin.py
from django.contrib import admin
from .models import ServiceModel, AdvancedServiceModel
from django.urls import reverse
from django.utils.html import escape, mark_safe
@admin.register(ServiceModel)
class ServiceModelAdmin(admin.ModelAdmin):
list_display = ['advanced_link', 'total_cars', 'repaired']
def advanced_link(self, obj: AdvancedServiceModel):
link = reverse("admin:tasks_advancedservicemodel_changelist")
return mark_safe(f'<a href="{link}">{escape(obj.advanced.__str__())}</a>')
advanced_link.short_description = 'Service id'
advanced_link.admin_order_field = 'service_id' # Make row sortable
@admin.register(AdvancedServiceModel)
class AdvancedServiceModelAdmin(admin.ModelAdmin):
list_display = ['service_id', 'bmw', 'audi', 'broken_motor', 'broken_body']
Мой ответ требует, чтобы ServiceModel.service_id
был уникальным. Вы должны переместить внешний ключ из ServiceModel
в AdvancedServiceModel
. Это потому, что вы хотите иметь один экземпляр модели сервиса для всех продвинутых моделей сервиса. В Django нет OneToManyField
. Он может быть реализован только через ForeignKey
.
В рамках этого изменения вы удалите поле service_id
из AdvancedServiceModel
. Если вам нужно получить фактический идентификатор услуги, вам нужно будет извлечь связанное с ним поле ServiceModel
.
class ServiceModel(models.Model):
service_id = models.CharField(max_length=150, unique=True)
total_cars = models.PositiveIntegerField() # bmw + audi
repaired = models.PositiveIntegerField() # broken_motor + broken_body
class AdvancedServiceModel(models.Model):
service_model = models.ForeignKey(
ServiceModel, related_name='advanced_service_models', on_delete=models.CASCADE)
bmw = models.PositiveIntegerField()
audi = models.PositiveIntegerField()
broken_motor = models.PositiveIntegerField()
broken_body = models.PositiveIntegerField()
# admin.py
from django.db.models import Count
@admin.register(ServiceModel)
class ServiceModelAdmin(admin.ModelAdmin):
list_display = ['advanced_link', 'total_cars', 'repaired']
def get_queryset(self, *args, **kwargs): # I forget the arguments, look them up please.
return super().get_queryset(*args, **kwargs).annotate(
advanced_count=Count('advanced_service_models__id'),
)
def advanced_link(self, obj: AdvancedServiceModel):
link = reverse("admin:tasks_advancedservicemodel_changelist") + f"?service_model__id__exact={obj.id}"
count = obj.advanced_count
return mark_safe(f'<a href="{link}">View Advanced Services ({count})</a>')
advanced_link.short_description = 'Service id'
advanced_link.admin_order_field = 'service_id' # Make row sortable
@admin.register(AdvancedServiceModel)
class AdvancedServiceModelAdmin(admin.ModelAdmin):
list_display = ['service_id', 'bmw', 'audi', 'broken_motor', 'broken_body']
list_select_related = ['service_model']
def service_id(self, obj):
return obj.service_model.service_id