In short.
Trying 2 ways to create an object with m2m field in test setup. Both fail.
1-
a = Model1.objects.create()
b = Model2.objects.create(a=a)
Fails with “TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use a.set() instead.”
2-
b = Model2.objects.create()
b.save()
b.a.add(a) Or b.a.set([a])
Fails with “django.db.utils.IntegrityError: NOT NULL constraint failed: myapp_b.a_id”
What am I missing?
Full code
Models
class Color(models.Model):
name = models.CharField()
class Size(models.Model):
name = models.CharField()
class Tshirt(models.Model):
name = models.CharField()
color = models.ManyToManyField(Color, through="TshirtColorSize", related_name="+")
size = models.ManyToManyField(Size, through="TshirtColorSize", related_name="+")
weight = models.IntegerField()
material = models.TextField(blank=True)
class TshirtColorSize(models.Model):
tshirt = models.ForeignKey(Tshirt, on_delete=models.CASCADE)
color = models.ForeignKey(Color, on_delete=models.CASCADE)
size = models.ForeignKey(Size, on_delete=models.CASCADE)
photo = models.ImageField(blank=True, null=True)
Test
Fails with error N1
class TestHomeTshirtDetails(TestCase):
def setUp(self):
self.color = Color.objects.create(name="white")
self.size = Size.objects.create(name="XS")
self.tshirt = Tshirt.objects.create(
name="CL",
weight=1,
material="100%",
color=self.color,
size=self.size,
)
self.tcs = TshirtColorSize.objects.create(
tshirt=self.tshirt, color=self.color, size=self.size
)
Fails with error N2
class TestHomeTshirtDetails(TestCase):
def setUp(self):
self.color = Color.objects.create(name="white", name_html="white")
self.size = Size.objects.create(name="XS")
self.tshirt = Tshirt.objects.create(
name="CL",
weight=1,
material="100%",
)
self.tshirt.save()
self.tshirt.color.add(self.color)
self.tshirt.size.add(self.size)
self.tcs = TshirtColorSize.objects.create()
self.tcs.save()
self.tcs.tshirt.add(self.tshirt)
self.tcs.color.add(self.color)
self.tcs.size.add(self.size)
def test_tshirt_details_view(self):
url = f"/calc/tshirt-details/CL/white/"
response = self.client.get(url)
self.assertEqual(200, response.status_code)
Error detail on the N2:
- “django.db.utils.IntegrityError: NOT NULL constraint failed: home_tshirtcolorsize.size_id”
- ‘INSERT INTO “home_tshirtcolorsize” (“tshirt_id”, “color_id”, “size_id”, “photo”) VALUES (?, ?, ?, ?) RETURNING “home_tshirtcolorsize”.“id”’
params = (1, 1, None, ‘’)
It looks like it only misses “size_id”, while “tshirt_id”, “color_id” are somehow ok: (1, 1, None, ‘’)
Test
def test_size(self):
self.assertEqual(self.size.id, 1)
passes.