Spinnaay Spinnaay - 5 months ago 56
Python Question

Saving Django formset with Many to Many Field

I'm building a little app with a formset that lets me enter a number of game scores each linking to a player via a many to many field. I'm having problems getting this to save properly with various errors. Basic code.


class Player(models.Model):
name = models.CharField(max_length=30)

def __unicode__(self):
return self.name

class Score(models.Model):
score = models.DecimalField(max_digits=4, decimal_places=0)
turn = models.ForeignKey(Turn)
players = models.ManyToManyField(Player)

def __unicode__(self):
return self.score

Each score is then joined to a turn but I haven't shown that bit.


class NewScore(ModelForm):

class Meta:
model = Score
fields = ('score', 'players',)


def newscore(request):

NewScoreFormSet = formset_factory(NewScore, extra=2)

if request.method == 'POST':

formset = NewScoreFormSet(request.POST)

if formset.is_valid():

t = Turn.objects.latest('id')

for form in formset:

p = form.cleaned_data.get('players')

scoreSave = form.save(commit=False)
scoreSave.turn = t

print 'Formset not OK'

return render(request, 'scorer/game.html',


formset = NewScoreFormSet()

return render(request, 'scorer/game.html',
{'formset': formset,})

The issue seems to be around getting the player saved through the many to many field and in this current setup I get the error message

TypeError: int() argument must be a string or a number, not 'QuerySet'

I have also tried removing the line


but that just doesn't save the player at all. Just the score and turn.


The add() method used for associating instances in many-to-many relations takes one or more individual model instances. You cannot pass an entire list/queryset of players, but you can add them one by one:

for player in p:

Of course this is rather verbose, so you can use python's syntax sugar for calling add() with all instances at once:

scoreSave.players.add(*p) # same as scoreSave.players.add(p[0], p[1], ...)