Question

All,

I am trying to initialize a modelformset with a manytomanyfield. A catch is that I do not know in advance the name of the manytomanyfield (nor the class it is bound to).

Here are my models and forms:

class Book_model(models.Model):
    title = models.CharField(max_length=BIG_STRING)
    authors = models.ManyToManyField("Author_model",)

class Author_model(models.Model):
    name = models.CharField(max_length=BIG_STRING)

class Book_form(ModelForm):
    class Meta:
        model = Book_model

class Author_form(ModelForm:
    class Meta:
        model = Author_model

Author_formset = modelformset_factory(Author_model,form=Author_form)

And elsewhere in my code I am trying to display a Model_form along with an Author_formset. When it comes time to initialize that formset, though, I'm not sure what to do. At that point I know the name of the m2m field ("authors"), the parent model instance (Book_model), the parent form instance (Book_form), and the formset class (Author_formset). I assume that I just need to do something like this:

m2m_field = getattr(book,"authors")
qset = field.filter(<only authors for which there is a m2m relationship from this book>)
formset = Author_formset(queryset=qset)

But, I don't know the right terms to put in the filter.

Any suggestions?

Was it helpful?

Solution 2

I think I have solved this.

In theory this is the correct way to do things, as Daniel suggests:

formset = Author_formset(queryset=book.authors.all())

But I can't do that directly, because I am trapped in some generic code that could be called for any model/form/formset. So I'm forced to do this instead:

 # these 4 lines are just for clarity's sake
 # I don't actually know what these map to in my code
 MyModelClass = Book_model
 MyFormClass = Book_form
 MyFormSetClass = Author_formset
 fieldName = "authors"

 def DoStuff(model_id=None):
   if (model_id):
     model = MyModelClass.objects.get(pk=model_id)
   else:
     model = MyModelClass()

   form = MyFormClass(instance=model)

   if model.pk:
     m2mModels = getattr(model,fieldName)
     formset = MyFormSetClass(queryset = m2mModels.all())
   else:
     m2mModelClass = MyFormSetClass.form.Meta.model
     formset = MyFormSetClass(queryset = m2mModelClass.objects.none())

This seems a bit ugly, but it works.

OTHER TIPS

You're on the right track.

book.authors is the queryset of "authors for which there is a m2m from this book". So that is perfectly valid to pass into the formset init.

formset = AuthorFormset(queryset=m2m_field.all())
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top