You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django表单下拉框中显示Deck模型的is_cedh字段信息

问题描述

我正在给Django表单的下拉框添加额外信息,程序逻辑如下:

  • 用户登录
  • 用户可创建将在game_tracking页面展示的「卡组(decks)」
  • 用户进入game_tracking页面后,第一个下拉框需要加载用户创建的所有卡组名称,同时显示Deck模型中的附加信息——该卡组是否为cEDH卡组。

目前我不确定如何在下拉框中除名称外,同时展示is_cedh的状态。当前下拉框仅显示卡组名称,理想效果是在cEDH卡组的名称旁标注「(cEDH)」。

以下是相关代码:

models.py文件

from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    profile_pic = models.ImageField(null=True,
                                blank=True,
                                default='Default.png',
                                upload_to='images/')

    user = models.ForeignKey(User,
                         max_length=10,
                         on_delete=models.CASCADE,
                         null=True)

    def __str__(self):
        return str(self.user)


class Deck(models.Model):
    deck = models.CharField(max_length=150)
    is_cedh = models.BooleanField(default=False)

    user = models.ForeignKey(User,
                         max_length=10,
                         on_delete=models.CASCADE,
                         null=True)

    def __str__(self):
        return str(self.deck)


class Game(models.Model):
    NUM_PLAYERS_CHOICE = [
        (2, 2),
        (3, 3),
        (4, 4),
        (5, 5),
        (6, 6)
        ]

    OUTCOME_CHOICE = [
        ('Win', 'Win'),
        ('Loss', 'Loss'),
        ('Draw', 'Draw'),
        ('Incomplete', 'Incomplete'),
        ]

    # ForeignKeys
    deck = models.ForeignKey(Deck, on_delete=models.CASCADE, null=True)
    wincon = models.ForeignKey(Wincon, on_delete=models.CASCADE, null=True, blank=True)

    num_players = models.IntegerField(choices=NUM_PLAYERS_CHOICE, default=4)
    outcome = models.CharField(max_length=10, choices=OUTCOME_CHOICE, default='Win')

forms.py文件

class GameForm(forms.ModelForm):
    def __init__(self, user, *args, **kwargs):
        super(GameForm, self).__init__(*args, **kwargs)
        self.fields['deck'].queryset = Deck.objects.filter(user=user)

class Meta:
    model = Game
    exclude = {'date', 'time', }
    labels = {
        'deck': 'What deck',
        'num_players': '# of Players',
        'outcome': 'Outcome',
    },

views.py文件

@login_required(login_url='my-login')
def game_tracker(request):
    user_decks = Deck.objects.filter(user=request.user)

    if request.method == "POST":
        form = GameForm(request.user, request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/')
    else:
        form = GameForm(request.user)

    context = {'form': form, }
    return render(request, 'gametracker_app/gametracker.html', context=context)

HTML文件

{% block content %}
    <form action=""
          method="POST">
      {% csrf_token %}
      <div class="container-sm p-4">
        <div class="card"
             style="">
          <div class="card-body">
            {{ form.deck|as_crispy_field }}
            <br>
            <a href="{% url 'my-decks' %}"
               class="">
              <p class="">Add new deck?</p>
            </a>
            <div class="flex-container">
              <div class="row">
                <div class="col-sm">
                  {{ form.num_players|as_crispy_field }}
                </div>
                <div class="col-sm">
                  {{ form.outcome|as_crispy_field }}
                </div>
              </div>
            </div>
            
            <button type='submit'
                    class="btn btn-secondary">Submit
            </button>
          </div>
        </div>
      </div>
    </form>
{% endblock %}
解决方案

方法1:修改Deck模型的__str__方法

这是最简单的全局生效方案,直接在模型的字符串表示中加入cEDH标记:

class Deck(models.Model):
    deck = models.CharField(max_length=150)
    is_cedh = models.BooleanField(default=False)
    user = models.ForeignKey(User, max_length=10, on_delete=models.CASCADE, null=True)

    def __str__(self):
        # 针对cEDH卡组添加标记
        if self.is_cedh:
            return f"{self.deck} (cEDH)"
        return self.deck

修改后,所有展示Deck实例的场景(包括表单下拉框)都会自动显示带标记的名称,无需修改其他代码。

方法2:在表单中自定义下拉选项

如果不想修改模型的全局字符串表示(比如其他场景需要纯卡组名称),可以在GameForm中手动构造下拉选项:

class GameForm(forms.ModelForm):
    def __init__(self, user, *args, **kwargs):
        super(GameForm, self).__init__(*args, **kwargs)
        # 获取用户卡组并构造自定义显示文本
        user_decks = Deck.objects.filter(user=user)
        self.fields['deck'].choices = [
            (deck.id, f"{deck.deck} (cEDH)" if deck.is_cedh else deck.deck)
            for deck in user_decks
        ]

    class Meta:
        model = Game
        exclude = {'date', 'time', }
        labels = {
            'deck': '使用的卡组',
            'num_players': '玩家数量',
            'outcome': '对局结果',
        }

这种方式仅在当前表单中生效,不影响其他地方的Deck显示逻辑,选项的值仍为卡组ID,不影响表单提交后的保存。

注意事项

  • 由于你使用了django-crispy-forms(模板中的|as_crispy_field),两种方案都能正常渲染出带标记的下拉选项。

内容的提问来源于stack exchange,提问作者bld-sync

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 12:22:23