Home > database >  How to handle ManyToMany fields while testing django-models?
How to handle ManyToMany fields while testing django-models?

Time:10-02

I am trying to write tests for my django models. However, I've got a problem with testing ManyToManyFields and haven't resolved it yet.

class TestVolunteeringModels(TestCase):
    def setUp(self) -> None:
        self.test_need = sample_need(title="Need", description="Description")
        self.test_opportunity = sample_opportunity(title="Opportunity", description="Description")
        for i in range(10):
            self.test_category = sample_category(name="Category")
            self.test_need.category = self.test_category
            self.test_opportunity.category = self.test_category

    def tearDown(self) -> None:
        self.test_need.delete()
        self.test_opportunity.delete()

Which brings me this error:

TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use category.set() instead.

The problem is when I use .set() as written in traceback instructions, like this:

self.test_need.category.set(self.test_category)
self.test_opportunity.category.set(self.test_category)

It gives me another error, which says "TypeError: 'Category' object is not iterable"

So my question is how can I access ManyToMany field in this case, so I can test it freely?

CodePudding user response:

.set() expects an iterable as argument, but the argument that you pass, self.test_category, is not iterable. You have two options:

  • Use .set([self.test_category,]) instead of .set(self.test_category). Thereby you are passing a list, which is iterable, instead of a single object, which is not iterable (therefor the error message that you get).
  • Alternatively, you could use .add(self.test_category). The function .add() takes individual objects as positional arguments, and adds them to any pre-existing catetories.

You should probably opt for .set() though, because this ensures that after its execution, the set of associated categories will be precisely the one that you pass.

  • Related