Django 未绑定和绑定表单

Django unbound and bound forms

我正在创建一项服务,人们可以在其中创建指南,包括用于名为炉石的视频游戏的套牌。第一个必须 select 他们的英雄:

class SelectHero(ListView):
    template_name = 'hsguides/select_hero.html'
    model = Hero

    def get_context_data(self, **kwargs):
        context = super(SelectHero, self).get_context_data(**kwargs)
        context['heroes'] = Hero.objects.all()
        return context

当它被 selected 时,我渲染了一个带有甲板和指南表格的模板。现在,当我使用此设置时:

查看

@login_required(login_url="/accounts/login")
def guide_create_view(request, hero):
    print(DeckForm)
    return render(request, 'hsguides/guide_create.html', {
        'DeckForm': DeckForm(hero),
        'GuideForm': GuideForm,
    })

形式

class DeckForm(ModelForm):
    class Meta:
        model = Deck
        exclude = ('dust', 'hero',)


    def __init__(self, hero=None, **kwargs):
        super(DeckForm, self).__init__(**kwargs)
        if hero:
            self.fields['weapon_cards'].queryset = Weapon.objects.filter(Q(card_class='neutral') |
                                                                         Q(card_class=hero))
            self.fields['spell_cards'].queryset = Spell.objects.filter(Q(card_class='neutral') |
                                                                       Q(card_class=hero))
            self.fields['minion_cards'].queryset = Minion.objects.filter(Q(card_class='neutral') |
                                                                         Q(card_class=hero))

我看到这个表格是未绑定的,当我想在我的保存视图中使用它时它是无效的

@login_required(login_url="/accounts/login")
def guide_save(request):
    if request.method == "POST":
        deck_form  =  DeckForm(request.POST)
        guide_form = GuideForm(request.POST)
        print(guide_form.is_bound) # printed value, True
        print(deck_form.is_bound) # printed value, False
        if guide_form.is_valid() and deck_form.is_valid():
            new_deck  = deck_form.save(commit=False)
            new_deck.dust = 0 #TODO create a count method for the dust field!
            new_deck.save()

            new_guide = guide_form.save(commit=False)
            new_guide.author = Account.objects.get(id=request.user.id)
            new_guide.deck = Deck.objects.get(id=new_deck.id)
            new_guide.save()
        else:
            print(guide_form.errors)
            print(deck_form.errors)
    else:
        deck_form = DeckForm()
        guide_form = GuideForm()

    return HttpResponseRedirect('/guides/search-guide/')

现在我真的很依赖这部分:

def __init__(self, hero=None, **kwargs):
        super(DeckForm, self).__init__(**kwargs)
        if hero:
            self.fields['weapon_cards'].queryset = Weapon.objects.filter(Q(card_class='neutral') |
                                                                         Q(card_class=hero))
            self.fields['spell_cards'].queryset = Spell.objects.filter(Q(card_class='neutral') |
                                                                       Q(card_class=hero))
            self.fields['minion_cards'].queryset = Minion.objects.filter(Q(card_class='neutral') |
                                                                         Q(card_class=hero))

但我不知道如何以最好的方式验证套牌形式并保存它。关于最佳实践,我怎样才能最好地处理这种情况?

您重新定义了表单的签名,因此第一个参数是 hero,但随后您仅使用 request.POST 实例化它。

不要这样做,而是从 kwargs 获取 hero,并始终确保您接受 args 和 kwargs。

def __init__(self, *args, **kwargs):
    hero = kwargs.pop('hero', None)
    super(DeckForm, self).__init__(*args, **kwargs)
    if hero:
        ...

记得通过关键字传递英雄参数:

return render(request, 'hsguides/guide_create.html', {
    'DeckForm': DeckForm(hero=hero),
    'GuideForm': GuideForm,
})