views:

28

answers:

1

Consider I have defined the following models:

class Tag(models.Model):
  name = models.CharField(max_length=20)

class Entry(models.Model):
  title = models.CharField(max_length=100)
  date = models.DateField()
  tags = models.ManyToManyField(Tag)

and the following model form:

class EntryForm(forms.ModelForm):
  tags =  CharField(max_length=100, label='Tags', required=False)
  class Meta:
    model = Entry

Basically I have an entry with tags. The tags are not necessarily already created. I need to receive a filled entry form and save it with tags.

I can do that easily if I don't have the ManyToMany relation in the Entry. But with it I first need to save the tags, then add the saved tags to the entry and then save the entry. Which means I have to override the EntryForm's save() method.

I saw this question already, but it looks different. In my case I need to save only the tags, and the rest should be able use ModelForm's default save().

I presented a simplified example. In real one I have much more fields in the Entry. What is your recommendation for writing EntryForm's save() method in a django way?

+2  A: 

I think you can call super after you save the tags. Perhaps you need to append to the entry after the entry is created.

def save(self, commit=True):
    # do custom stuff
    tags =[]
    for t in self.cleaned_data['tags'].split(','):
         tags.append(Tag.objects.get_or_create(name=t))
    # save entry
    e = super(EntryForm, self).save(commit=commit)

    for t in tags:
        e.tags.add(t)
OmerGertel
Thanks. But one problem. How can I prevent initial saving of tags field at super(EntryForm, self).save()?
grigy
Good question. You can also save the Entry manually. If you get the instance, `Entry.objects.get(id=instance.id)` and then update the fields, otherwise `Entry.objects.create(title=...,date=...)`. Then add the tags. It's so little work that using the form's save may not be worth it.
OmerGertel
One correction: get_or_create returns a tuple - (tag, created), so we need to take only the first part
grigy