Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django how to save a custom formset

I've written the following custom formset, but for the life of me I don't know how to save the form. I've searched the Django docs and done extensive searches, but no one solution works. Lots of rabbit holes, but no meat ;-) Can someone point me in the right direction?

// views.py partial //

@login_required

def add_stats(request, group_slug, team_id, game_id, template_name = 'games/stats_add_form.html'):

    if request.POST:

        formset = AddStatsFormSet(group_slug=group_slug, team_id=team_id, game_id=game_id, data=request.POST)

        if formset.is_valid():

            formset.save()

            return HttpResponseRedirect(reverse('games_game_list'))

        else:

            formset = TeamStatFormSet(group_slug=group_slug, team_id=team_id, game_id=game_id)

        return render_to_response(template_name, {'formset': formset,})


// modles.py partial //

class PlayerStat(models.Model):

    game = models.ForeignKey(Game, verbose_name=_(u'sport event'),)
    player = models.ForeignKey(Player, verbose_name=_(u'player'),)
    stat = models.ForeignKey(Stat, verbose_name=_(u'statistic'),)
    total = models.CharField(_(u'total'), max_length=25, blank=True, null=True)

    class Meta:
        verbose_name = _('player stat')
        verbose_name_plural = _('player stats')
        db_table     = 'dfusion_playerstats'

        def __unicode__(self):
            return u'%s' % self.player


// forms.py

class TeamStatForm(forms.Form):

    total = forms.IntegerField()


class BaseTeamStatsFormSet(BaseFormSet):

    def __init__(self, *args, **kwargs):
        self.group_slug = kwargs['group_slug']
        self.team_id = kwargs['team_id']
        self.game_id = kwargs['game_id']
        self.extra = len(Stat.objects.filter(group__slug=self.group_slug))
        del kwargs['group_slug']
        del kwargs['game_id']
        del kwargs['team_id']
        super(BaseTeamStatsFormSet, self).__init__(*args, **kwargs)

    def add_fields(self, form, index):
        super(BaseTeamStatsFormSet, self).add_fields(form, index)
        form.fields["stat"] = forms.ModelChoiceField(queryset = Stat.objects.filter(group__slug=self.group_slug))
        form.fields["game"] = forms.ModelChoiceField(queryset = Game.objects.all())
        form.fields["team"] = forms.ModelChoiceField(queryset = Team.objects.all())
        form.fields["game"].initial = self.game_id
        form.fields["team"].initial = self.team_id

TeamStatFormSet = formset_factory(TeamStatForm, BaseTeamStatsFormSet)
like image 225
Terry Owen Avatar asked Sep 09 '09 03:09

Terry Owen


People also ask

What does save () do in django?

The save method is an inherited method from models. Model which is executed to save an instance into a particular Model. Whenever one tries to create an instance of a model either from admin interface or django shell, save() function is run.

How do I customize Modelan in django?

To create ModelForm in django, you need to specify fields. Just associate the fields to first_name and lastName. Under the Meta class you can add : fields = ['first_name','lastName']. @Shishir solution works after I add that line. or you can try solution in Jihoon answers by adding vacant fields.

How can I have multiple models in a single django ModelForm?

In a nutshell: Make a form for each model, submit them both to template in a single <form> , using prefix keyarg and have the view handle validation. If there is dependency, just make sure you save the "parent" model before dependant, and use parent's ID for foreign key before commiting save of "child" model.


2 Answers

In your custom forms, you'll need to add a save() method that stuffs the form data into your models as needed. All of the data entered in the form will be available in a hash called cleaned_data[].

For example:

def save(self):
    teamStat = TeamStat(game_id=self.cleaned_data['game_id'],team_id=self.cleaned_data['team_id'])
    teamStat.save()
    return teamStat
like image 139
gbc Avatar answered Sep 30 '22 06:09

gbc


Only model forms and formsets come with a save() method. Regular forms aren't attached to models, so you have to store the data yourself. How to save a formset? from the Django mailing list has an example of saving data from a regular formset.

Edit: You can always add a save() method to a regular form or formset as gbc suggests. They just don't have one built-in.

I don't see a TeamStat model in your code snippets, but if you had one, your forms.py should look something like this:

class TeamStatForm(forms.ModelForm):
    total = forms.IntegerField()

    class Meta:
        model = TeamStat


class BaseTeamStatsFormSet(BaseModelFormSet):

    def __init__(self, *args, **kwargs):
        self.group_slug = kwargs['group_slug']
        self.team_id = kwargs['team_id']
        self.game_id = kwargs['game_id']
        self.extra = len(Stat.objects.filter(group__slug=self.group_slug))
        del kwargs['group_slug']
        del kwargs['game_id']
        del kwargs['team_id']
        super(BaseTeamStatsFormSet, self).__init__(*args, **kwargs)

    def add_fields(self, form, index):
        super(BaseTeamStatsFormSet, self).add_fields(form, index)
        form.fields["stat"] = forms.ModelChoiceField(queryset = Stat.objects.filter(group__slug=self.group_slug))
        form.fields["game"] = forms.ModelChoiceField(queryset = Game.objects.all())
        form.fields["team"] = forms.ModelChoiceField(queryset = Team.objects.all())
        form.fields["game"].initial = self.game_id
        form.fields["team"].initial = self.team_id

TeamStatFormSet = modelformset_factory(TeamStatForm, BaseTeamStatsFormSet)

See Creating forms from models from the Django docs

like image 42
Selene Avatar answered Sep 30 '22 06:09

Selene