Django 高级模型

Django Advanced Model

我有 2 个模型。在其中一个中,我想撤回一般信息,在另一个中,我想撤回高级信息。 我希望模型结合 service_id 字段。

在 AdvancedService 模型中,我有 2 个对象和一个 service_id。在服务模型中,当我单击 service_id 时,我想查看 service_id 这样的 2 个对象。但是,我不明白该怎么做。我的代码:

#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.

实现

作为此更改的一部分,您将从 AdvancedServiceModel 中删除 service_id 字段。如果您需要获取实际的服务 ID,则需要提取关联的 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