2009-07-31 13 views
4

Mein Problem ModelFormset ist ähnlich Django Passing Custom Form Parameters to FormsetDjango Passing Custom Form Parameter

Ive haben diese Klassen

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"),) 

Und ich habe meine eigene modelformset_factory definiert:

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 

Und ich benutze es ist wie folgt:

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

Dies zeigt die Form:

Drop-Down-Box von Game (s) in der Runde angegeben und sollte für die Quoten 3 Radio-Buttons angezeigt werden, aber ich weiß nicht, was als Parameter an die mymodelformset_factory zu übergeben. Wenn v = Game.objects.get (pk = 1) ist, zeigt es offensichtlich nur Spiel mit pk = 1 für ALLE Spiele an, was ich brauche, ist v = Game.objects.get (pk = "Spiel, das mit den Quoten betreffend verbunden ist ") Wenn Sie meine Drift fangen ..

Antwort

4

Ich denke, dass Sie einige Änderungen an Ihrer benutzerdefinierten Factory-Funktion vornehmen möchten. Es sollte die Formset-Klasse und nicht das Formular zurückgeben. Wie wäre es damit:

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) 

dann in der Ansicht Code:

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

Diese für ein ähnliches Problem für mich zu funktionieren scheint! – balleyne

0

Eine andere Lösung ist BaseModelFormSet Unterklasse und _construct_forms Methode außer Kraft setzen. Standardmäßig BaseFormSet _construct_form Methode nur in _construct_forms mit einem Argument aufruft, 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)) 

aber es kann eine beliebige Anzahl von Keyword-args sein:

# django/forms/formsets.py 
def _construct_form(self, i, **kwargs): 

So, hier ist meine Ansicht Methode und Form, die erhält zusätzliche Parameter in init von _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',)