具有M2M中介模型的Django:list_display和Views

时间:2019-02-19 18:25:15

标签: python django

我正在编写一个Django应用程序来跟踪我的魔术卡收藏。我现在对模型非常满意,并且管理界面可以正常工作。我可以添加新的卡片,卡片的收藏夹和副本,并且一切正常。但是,我现在想将我的整个模型关系中的属性添加到“管理”部分中的list_display。

基本上,我想列出每个集合的副本,copys_foil和copyss_premium,以及每个卡的条目。 (每个集合可以具有同一张卡的多个普通副本,铝箔副本和高级副本。)我想在管理UI的list_display中以及以后在视图中同时列出它们。我该怎么办?

这是我的模型。py:

from django.db import models

class Expansion(models.Model):
name = models.CharField(max_length=100, unique=True, verbose_name='Expansion')
symbol = models.CharField(max_length=3, unique=True, primary_key=True, verbose_name='Expansion Symbol')
released = models.DateField()
added = models.DateField(auto_now_add=True)
modified = models.DateField(auto_now=True)

def __str__(self):
    return '%s' % (self.symbol)

class Card(models.Model):
LAND = 'L'
COMMON = 'C'
UNCOMMON = 'U'
RARE = 'R'
MYTHIC = 'M'
TOKEN = 'T'
RARITY_CHOICES = (
    (LAND, 'Land'),
    (COMMON, 'Common'),
    (UNCOMMON, 'Uncommon'),
    (RARE, 'Rare'),
    (MYTHIC, 'Mythic Rare'),
    (TOKEN, 'Token'),
)
WHITE = 'W'
BLUE = 'U'
BLACK = 'B'
RED = 'R'
GREEN = 'G'
COLOURLESS  = 'C'
GOLD = 'M'
COLOUR_CHOICES = (
    (WHITE, 'White'),
    (BLUE, 'Blue'),
    (BLACK, 'Black'),
    (RED, 'Red'),
    (GREEN, 'Green'),
    (COLOURLESS, 'Colourless'),
    (GOLD, 'Gold'),
)
WHITE = 'W'
BLUE = 'U'
BLACK = 'B'
RED = 'R'
GREEN = 'G'
REDGREEN  = 'RG'
BLACKGREEN = 'BG'
WHITEREDGREEN = 'WRG'
BLUEBLACKRED = 'UBR'
COLOUR_CHOICES_IND = (
    (WHITE, 'White'),
    (BLUE, 'Blue'),
    (BLACK, 'Black'),
    (RED, 'Red'),
    (GREEN, 'Green'),
    (REDGREEN, 'Red/Green'),
    (BLACKGREEN, 'Black/Green'),
    (WHITEREDGREEN, 'White/Red/Green'),
    (BLUEBLACKRED, 'Blue/Black/Red'),
)
name = models.CharField(max_length=200)
name_transformed = models.CharField(max_length=200, blank=True, verbose_name='Name (Transformed)',
    help_text='For double-sided cards')
slug = models.SlugField(max_length=220, unique=True, primary_key=True,
    help_text='Example: totallylost-gtc-054')
colour = models.CharField(
    max_length=1,
    choices=COLOUR_CHOICES,
    default='COLOURLESS',
    verbose_name='Colour'
)
cost_w = models.IntegerField(blank=True, null=True, verbose_name='Cost White')
cost_u = models.IntegerField(blank=True, null=True, verbose_name='Cost Blue')
cost_b = models.IntegerField(blank=True, null=True, verbose_name='Cost Black')
cost_r = models.IntegerField(blank=True, null=True, verbose_name='Cost Red')
cost_g = models.IntegerField(blank=True, null=True, verbose_name='Cost Green')
cost_c = models.IntegerField(blank=True, null=True, verbose_name='Cost Generic')
cost_wu = models.IntegerField(blank=True, null=True, verbose_name='Cost White/Blue')
cost_wb = models.IntegerField(blank=True, null=True, verbose_name='Cost White/Black')
cost_cw = models.IntegerField(blank=True, null=True, verbose_name='Cost Generic/White')
cost_ub = models.IntegerField(blank=True, null=True, verbose_name='Cost Blue/Black')
cost_ur = models.IntegerField(blank=True, null=True, verbose_name='Cost Blue/Red')
cost_cu = models.IntegerField(blank=True, null=True, verbose_name='Cost Generic/Blue')
cost_br = models.IntegerField(blank=True, null=True, verbose_name='Cost Black/Red')
cost_bg = models.IntegerField(blank=True, null=True, verbose_name='Cost Black/Green')
cost_cb = models.IntegerField(blank=True, null=True, verbose_name='Cost Generic/Black')
cost_rg = models.IntegerField(blank=True, null=True, verbose_name='Cost Red/Green')
cost_rw = models.IntegerField(blank=True, null=True, verbose_name='Cost Red/White')
cost_cr = models.IntegerField(blank=True, null=True, verbose_name='Cost Generic/Red')
cost_gw = models.IntegerField(blank=True, null=True, verbose_name='Cost Green/White')
cost_gu = models.IntegerField(blank=True, null=True, verbose_name='Cost Green/Blue')
cost_cg = models.IntegerField(blank=True, null=True, verbose_name='Cost Generic/Green')
art = models.FileField(upload_to='img/card/', blank=True)
art_transformed = models.FileField(upload_to='img/card/', blank=True, verbose_name='Art (Flip Side)',
    help_text='For double-sided cards')
colour_indicator = models.CharField(
    max_length=5,
    choices=COLOUR_CHOICES_IND,
    default='',
    blank=True,
    verbose_name='Colour Indicator'
)
supertype = models.CharField(max_length=50, blank=True)
type = models.CharField(max_length=50, blank=True)
subtype = models.CharField(max_length=50, blank=True)
colour_indicator_transformed = models.CharField(
    max_length=5,
    choices=COLOUR_CHOICES_IND,
    default='',
    blank=True,
    verbose_name='Colour Indicator',
    help_text='For double-sided cards'
    )
supertype_transfomed = models.CharField(max_length=50, blank=True, verbose_name='Supertype (Transformed)',
    help_text='For double-sided cards')
type_transformed = models.CharField(max_length=50, blank=True, verbose_name='Type (Transformed)',
    help_text='For double-sided cards')
subtype_transformed = models.CharField(max_length=50, blank=True, verbose_name='Subtype (Transformed)',
    help_text='For double-sided cards')
expansion = models.ForeignKey(Expansion,
on_delete=models.CASCADE)
power = models.IntegerField(blank=True, null=True, help_text='(Creatures)')
toughness = models.IntegerField(blank=True, null=True)
loyalty = models.IntegerField(blank=True, null=True, help_text='(Planeswalkers)')
power_transformed = models.IntegerField(blank=True, null=True, verbose_name='Power (Transformed)',
    help_text='For double-sided cards')
toughness_transformed = models.IntegerField(blank=True, null=True, verbose_name='Toughness (Transformed)',
    help_text='For double-sided cards')
loyalty_transformed = models.IntegerField(blank=True, null=True, verbose_name='Loyalty (Transformed)',
    help_text='For double-sided cards')
rules = models.TextField(blank=True, verbose_name='Rules Text')
flavour = models.TextField(blank=True, verbose_name='Flavour Text')
rules_transformed = models.TextField(blank=True, verbose_name='Rules Text (Transformed)',
    help_text='For double-sided cards')
flavour_transformed = models.TextField(blank=True, verbose_name='Flavour Text (Transformed)',
    help_text='For double-sided cards')
number = models.IntegerField(blank=True, null=True, verbose_name='Collector Number')
max_number = models.IntegerField(blank=True, null=True, verbose_name='...of')
rarity = models.CharField(
    max_length=1,
    choices=RARITY_CHOICES,
    default=COMMON,
    verbose_name='Rarity'
)
artist = models.CharField(max_length=50, blank=True)
artist_transformed = models.CharField(max_length=50, blank=True, verbose_name='Artist (Flip Side)',
    help_text='For double-sided cards')
errata = models.TextField(blank=True, help_text='Notes and Rulings on this card')
url = models.URLField(max_length=220, unique=True, verbose_name='Scryfall URL')
added = models.DateField(auto_now_add=True)
modified = models.DateField(auto_now=True)

def __str__(self):
    return '%s (%s)' % (self.name, self.expansion)

class Collection(models.Model):
name = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True, primary_key=True)
added = models.DateField(auto_now_add=True)
modified = models.DateField(auto_now=True)
cards = models.ManyToManyField(Card, through='Copy')

def __str__(self):
    return '%s' % (self.name)

class Copy(models.Model):
class Meta:
    verbose_name_plural = 'copies'
card = models.ForeignKey(Card, on_delete=models.CASCADE)
collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
added = models.DateField(auto_now_add=True)
copies = models.IntegerField(blank=True, null=True)
copies_foil = models.IntegerField(blank=True, null=True, verbose_name='Foil Copies')
copies_premium = models.IntegerField(blank=True, null=True, verbose_name='Premium Copies')

def __str__(self):
    return ''

这是我的admin.py:

from django.contrib import admin
from django.utils.html import format_html

from .models import Expansion, Card, Collection, Copy

class CopyInline(admin.TabularInline):
model = Copy
extra = 1 # extra rows below in the admin view

class CardAdmin(admin.ModelAdmin):
inlines = (CopyInline,)
fieldsets = [
    (None,                      {'fields': ['name', 'name_transformed', 'slug', 'colour']}),
    ('Card Cost',               {'fields': [('cost_w', 'cost_u', 'cost_b'), ('cost_r',
                                            'cost_g', 'cost_c'), ('cost_wu', 'cost_wb',
                                            'cost_cw'), ('cost_ub', 'cost_ur', 'cost_cu'),
                                            ('cost_br', 'cost_bg', 'cost_cb'), ('cost_rg',
                                            'cost_rw', 'cost_cr'), ('cost_gw', 'cost_gu',
                                            'cost_cg')]}),
    ('Type Line',               {'fields': [('colour_indicator', 'supertype', 'type', 'subtype')]}),
    ('Type Line (Transformed)', {'fields': [('colour_indicator_transformed', 'supertype_transfomed',
                                            'type_transformed', 'subtype_transformed')]}),
    (None,                      {'fields': ['art', 'art_transformed', 'expansion']}),
    (None,                      {'fields': [('power', 'power_transformed',
                                            'toughness', 'toughness_transformed')]}),
    (None,                      {'fields': [('loyalty', 'loyalty_transformed')]}),
    (None,                      {'fields': [('rules', 'rules_transformed')]}),
    (None,                      {'fields': [('flavour', 'flavour_transformed')]}),
    (None,                      {'fields': [('number', 'max_number')]}),
    (None,                      {'fields': ['rarity']}),
    (None,                      {'fields': [('artist', 'artist_transformed')]}),
    (None,                      {'fields': ['errata', 'url']})
]
list_display = ('name', 'colour', 'expansion', 'number', 'rarity', 'show_url')
list_filter = ['colour', 'expansion__name', 'rarity']

def show_url(self, obj):
    return format_html("<a href='{url}'>{url}</a>", url=obj.url)

show_url.short_description = "Scryfall URL"

admin.site.register(Expansion)
admin.site.register(Card, CardAdmin)
admin.site.register(Collection)

1 个答案:

答案 0 :(得分:2)

您可以定义一个名为count_copies的函数,并在列表管理员中显示该函数的输出,如下所示。请注意,以下假设每个Copy对象都绑定到唯一的Card。从您的数据库结构中,我不确定为什么这是两个单独的模型。

from .models import Copy

class CardAdmin(admin.ModelAdmin):
    list_display = (..., 'count_copies')

    def count_copies(self, obj):
        try:
            c = Copy.objects.get(card=obj)
        except Copy.DoesNotExist:
            c = None

        if c:
            return c.copies
        else:
            return 0
相关问题