Django将自定义表单参数传递给ModelFormset

16 浏览
0 Comments

Django将自定义表单参数传递给ModelFormset

我的问题与Django中传递自定义表单参数到Formset类似。

我有以下这些类:

class Game(models.Model):
    home_team = models.ForeignKey(Team, related_name='home_team')
    away_team = models.ForeignKey(Team, related_name='away_team')
    round = models.ForeignKey(Round)
TEAM_CHOICES = ((1, '1'), (2, 'X'), (3, '2'),)
class Odds(models.Model):
    game = models.ForeignKey(Game, unique=False)
    team = models.IntegerField(choices = TEAM_CHOICES)
    odds = models.FloatField()
    class Meta:
        verbose_name_plural = "Odds"
        unique_together = (
            ("game", "team"),
        )
class Vote(models.Model):
    user = models.ForeignKey(User, unique=False)
    game = models.ForeignKey(Game)
    score = models.ForeignKey(Odds)
    class Meta:
        unique_together = (
            ("game", "user"),)

我已定义了自己的modelformset_factory:

def mymodelformset_factory(ins):
    class VoteForm(forms.ModelForm):
        score = forms.ModelChoiceField(queryset=Odds.objects.filter(game=ins), widget=forms.RadioSelect(), empty_label=None)
        def __init__(self, *args, **kwargs):
            super(VoteForm, self).__init__(*args, **kwargs)
        class Meta:
            model = Vote
            exclude = ['user']
    return VoteForm 

我使用它的方式如下:

        VoteFormSet = modelformset_factory(Vote, form=mymodelformset_factory(v), extra=0)
        formset = VoteFormSet(request.POST, queryset=Vote.objects.filter(game__round=round, user=user))

这将显示表单:

在指定的轮次中显示Game的下拉框,并且应该显示3个关于Odds的单选按钮,但我不知道应该将什么作为参数传递给mymodelformset_factory。如果v = Game.objects.get(pk=1),显然它只会显示所有Game中pk为1的数据,我需要的是v = Game.objects.get(pk="与Odds相关的Game"),如果你明白我的意思的话。

0
0 Comments

问题出现的原因是在Django中,ModelFormSet的_construct_forms方法默认只接受一个参数i,而实际上可以传入任意数量的关键字参数。解决方法是创建一个子类继承BaseModelFormSet,并重写_construct_forms方法,将额外的参数传递给_formset构造函数。

在上述代码中,通过在视图方法中创建一个名为ActionsFormSet的子类,重写_construct_forms方法,并在其中将额外的参数传递给_construct_form函数。然后使用modelformset_factory创建一个model formset,指定formset为ActionsFormSet,将该formset传递给模板进行渲染。

在ActionForm中,重写了__init__方法,并接受一个名为dep的参数。在该方法中,调用父类的__init__方法,并在初始化self.fields['user'].choices时使用传入的dep参数进行筛选。

通过以上的解决方法,我们可以在ModelFormSet中传递自定义的参数给ModelForm,并在初始化过程中使用这些参数进行相应的操作。

0
0 Comments

问题原因:问题的原因是在自定义的工厂函数中返回了form而不是formset类。

解决方法:修改自定义的工厂函数,让其返回formset类而不是form。

def make_vote_formset(game_obj, extra=0):
    class _VoteForm(forms.ModelForm):
        score = forms.ModelChoiceField(
            queryset=Odds.objects.filter(game=game_obj), 
            widget=forms.RadioSelect(), 
            empty_label=None)
        class Meta:
            model = Vote
            exclude = ['user',]
    return modelformset_factory(Vote, form=_VoteForm, extra=extra)

然后在视图代码中使用该工厂函数来创建formset对象:

current_game = Game.objects.filter(id=current_game_id)
VoteFormSet = make_vote_formset(current_game)
formset = VoteFormSet(
             request.POST, 
             queryset=Vote.objects.filter(game__round=round, user=user))

以上是解决该问题的方法。

0