Django 将自定义表单参数传递给 ModelFormset
Posted
技术标签:
【中文标题】Django 将自定义表单参数传递给 ModelFormset【英文标题】:Django Passing Custom Form Parameters to ModelFormset 【发布时间】:2010-11-15 22:45:12 【问题描述】:我的问题类似于Django Passing Custom Form Parameters to 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))
这会显示表单:
指定回合中游戏的下拉框,应该显示 3 个单选按钮,但我不知道将什么作为参数传递给 mymodelformset_factory.. 如果 v = Game.objects。 get(pk=1) 它显然只显示所有游戏的 pk=1 游戏,如果你发现我的漂移,我需要的是 v = Game.objects.get(pk="game who is connected to the odds about")。 .
【问题讨论】:
【参考方案1】:我认为您想对自定义工厂函数进行一些更改。它应该返回表单集类,而不是表单。这个怎么样:
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)
然后在你的视图代码中:
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))
【讨论】:
【参考方案2】:另一种解决方案是继承 BaseModelFormSet 并覆盖 _construct_forms 方法。默认情况下,BaseFormSet _construct_form 方法仅在 _construct_forms 中调用一个参数,i:
# django/forms/formsets.py
def _construct_forms(self):
# instantiate all the forms and put them in self.forms
self.forms = []
for i in xrange(self.total_form_count()):
self.forms.append(self._construct_form(i))
但可以有任意数量的关键字参数:
# django/forms/formsets.py
def _construct_form(self, i, **kwargs):
所以,这是我的视图方法和表单,它在 init 中从 _construct_form 接收附加参数:
# view
def edit(request, id):
class ActionsFormSet(BaseModelFormSet):
department = request.user.userdata.department.pk
def _construct_forms(self):
self.forms = []
for i in range(self.total_form_count()):
self.forms.append(self._construct_form(i, dep=self.department))
actions_formset = modelformset_factory(Action, form=ActionForm, extra=0, can_delete=True, formset=ActionsFormSet)
...
# form
class ActionForm(forms.ModelForm):
def __init__(self, dep=0, *args, **kwargs):
super(ActionForm, self).__init__(*args, **kwargs)
self.fields['user'].choices = [(u.pk, u.first_name) for u in User.objects.filter(userdata__department=dep)]
class Meta:
model = Action
exclude = ('req',)
【讨论】:
以上是关于Django 将自定义表单参数传递给 ModelFormset的主要内容,如果未能解决你的问题,请参考以下文章
将自定义参数传递给 Symfony2 中的自定义 ValidationConstraint