[英]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 類),但我終其一生都無法弄清楚如何將這些數據組合在一起並僅顯示它。 基本上,我只想要數據庫中所有內容的“主列表”。
這是我到目前為止的代碼:
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
def project_detail_view(request):
obj = Project.objects.all()
context = {'object': obj}
return render(request, "project/project_detail.html", context)
urlpatterns = [
path('project/', project_detail_view),
path('', admin.site.urls),
]
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 ):
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()])
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.