簡體   English   中英

將幾個 Django 模型一起拉到一個列表中

[英]Pulling several Django models together into a single list

我有一個 MySQL 數據庫,其中包含四個相關表:項目、單元、unit_equipment 和設備。 一個項目可以有多個單元; 一個單元可以有許多相關的設備條目。 單個單元只能屬於一個項目,但設備和單元之間存在多對多(因此DB中的unit_equipment橋接表)。 我正在使用 Django 並嘗試創建一個視圖(或列表?),將所有 3 個模型一起顯示在同一頁面上。 所以它會列出所有項目、所有單位和所有設備。 理想情況下,顯示應該是這樣的:

    Project --------- Unit ------------- Equipment
    Project 1         first_unit         some_equipment1, some_equipment2
    Project 1         second_unit        more_equipment1, more_equipment2
    Project 2         another_unit       some_equipment1, more_equipment1
    Project 2         and_another_unit   some_equipment2, more_equipment2

但在這一點上,如果用逗號分隔它們很痛苦,我也會很高興為每件設備單獨設置一條線。

雖然創建一個表單似乎很簡單,我可以在其中添加一個新項目並添加相關的單元和設備數據(使用 TabularInline 類),但我終其一生都無法弄清楚如何將這些數據組合在一起並僅顯示它。 基本上,我只想要數據庫中所有內容的“主列表”。

這是我到目前為止的代碼:

模型.py

class Project(models.Model):
    name = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'project'

    def __str__(self):
        return self.name

class Unit(models.Model):
    project = models.ForeignKey(Project, models.DO_NOTHING, blank=True, null=True)
    name = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'unit'

    def __str__(self):
        return self.name

class UnitEquipment(models.Model):
    unit = models.ForeignKey(Unit, models.DO_NOTHING, blank=True, null=True)
    equipment = models.ForeignKey(Equipment, models.DO_NOTHING, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'unit_equipment'

class Equipment(models.Model):
    name = models.CharField(max_length=100, blank=True, null=True)
    description = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'equipment'

    def __str__(self):
        return self.name

視圖.py

def project_detail_view(request):
    obj = Project.objects.all()
    context = {'object': obj}
    return render(request, "project/project_detail.html", context)

網址.py

urlpatterns = [
    path('project/', project_detail_view),
    path('', admin.site.urls),
]

管理員.py

class UnitTabularInLine(admin.TabularInline):
    model = Unit
    extra = 0

class ProjectAdmin(admin.ModelAdmin):
    inlines = [UnitTabularInLine]

    class Meta:
        model = Project

    # a list of displayed columns name.
    list_display = ['name']
    # define search columns list, then a search box will be added at the top of list page.
    search_fields = ['name']
    # define filter columns list, then a filter widget will be shown at right side of list page.
    list_filter = ['name']
    # define model data list ordering.
    ordering = ('name')

我想我需要以某種方式向admin文件中的 list_display 添加更多條目,但是每次我嘗試添加單元或設備時都會引發錯誤。 我也嘗試向 Project 添加更多屬性,但我似乎無法正確使用語法,而且我不確定應該使用哪個 model class 。

我也看過 FormSets,但我無法理解如何更改當前代碼以使其正常工作。

如何將這些模型整合到一個統一的視圖中?

您無需編輯管理視圖即可添加您自己的視圖:您可能會發現在這種情況下您可以這樣做,以使您的數據完全按照您的需要顯示。

如果您確實想在管理列表中顯示相關的 object 值,那么您可以使用查找和自定義列:但是在這種情況下,您的列表將基於單元。

# You don't need an explicit UnitEquipment model here: you can
# use a simple ManyToManyField

class Unit(models.Model):
    project = ...
    name = ...
    equipment = models.ManyToManyField(Equipment, related_name='units')


def equipment_list(admin, instance):
    return ', '.join([x.name for x in instance.equimpent.all()])


class UnitAdmin(admin.ModelAdmin):
    class Meta:
        model = Unit

    list_display = ['project__name', 'name', equipment_list]


    def get_queryset(self, request):
       return super().get_queryset(request)\
                     .select_related('project')\
                     .prefetch_related('equipment')

請注意,您需要覆蓋查詢集,否則會有一堆額外的查詢,因為每個單元還需要獲取該單元的項目和設備列表。

您還可以對查詢進行進一步改進:您可以使用子查詢注釋聚合相關設備名稱,並防止第二次查詢(獲取查詢集中單元的所有相關設備項)。 這將取代prefetch_related()

感謝@Matthew Schinckel,我能夠找到答案。 這是我的文件現在的樣子(僅在models.py中編輯了Unit class ):

模型.py

class Unit(models.Model):
    project = models.ForeignKey(Project, models.DO_NOTHING, blank=True, null=True)
    name = models.CharField(max_length=255, blank=True, null=True)
    equipment = models.ManyToManyField(Equipment, related_name='units')

    class Meta:
        managed = False
        db_table = 'unit'

    def __str__(self):
        return self.name

    def equipment_list(self):
        return ', '.join([x.name for x in self.equipment.all()])

管理員.py

class UnitAdmin(admin.ModelAdmin):
    class Meta:
        model = Unit

    # a list of displayed columns name.
    list_display = ('project', 'name', 'equipment_list')
    # define search columns list, then a search box will be added at the top of list page.
    search_fields = ['project']
    # define filter columns list, then a filter widget will be shown at right side of list page.
    list_filter = ['project', 'name']
    # define model data list ordering.
    ordering = ('project', 'name')

    def get_queryset(self, request):
        return super().get_queryset(request)\
            .select_related('project')\
            .prefetch_related('equipment')

所以我所做的改變是:
1. 使 list_display 成為一個元組而不是一個列表。
2. 將def equipment_list(self)放入 Unit class (因此它可以作為 Unit 的屬性調用)並傳遞(self)而不是(admin, instance) (我一直在尋找實例參數的錯誤)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM