mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			108 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from django.apps import apps
 | |
| from django.db import models
 | |
| from django.test import SimpleTestCase, TestCase
 | |
| from django.test.utils import isolate_apps
 | |
| 
 | |
| from .models import ManyToMany
 | |
| 
 | |
| 
 | |
| class ManyToManyFieldTests(SimpleTestCase):
 | |
|     def test_abstract_model_pending_operations(self):
 | |
|         """
 | |
|         Many-to-many fields declared on abstract models should not add lazy
 | |
|         relations to resolve relationship declared as string (#24215).
 | |
|         """
 | |
|         pending_ops_before = list(apps._pending_operations.items())
 | |
| 
 | |
|         class AbstractManyToManyModel(models.Model):
 | |
|             fk = models.ForeignKey("missing.FK", models.CASCADE)
 | |
| 
 | |
|             class Meta:
 | |
|                 abstract = True
 | |
| 
 | |
|         self.assertIs(AbstractManyToManyModel._meta.apps, apps)
 | |
|         self.assertEqual(
 | |
|             pending_ops_before,
 | |
|             list(apps._pending_operations.items()),
 | |
|             "Pending lookup added for a many-to-many field on an abstract model",
 | |
|         )
 | |
| 
 | |
|     @isolate_apps("model_fields", "model_fields.tests")
 | |
|     def test_abstract_model_app_relative_foreign_key(self):
 | |
|         class AbstractReferent(models.Model):
 | |
|             reference = models.ManyToManyField("Referred", through="Through")
 | |
| 
 | |
|             class Meta:
 | |
|                 app_label = "model_fields"
 | |
|                 abstract = True
 | |
| 
 | |
|         def assert_app_model_resolved(label):
 | |
|             class Referred(models.Model):
 | |
|                 class Meta:
 | |
|                     app_label = label
 | |
| 
 | |
|             class Through(models.Model):
 | |
|                 referred = models.ForeignKey("Referred", on_delete=models.CASCADE)
 | |
|                 referent = models.ForeignKey(
 | |
|                     "ConcreteReferent", on_delete=models.CASCADE
 | |
|                 )
 | |
| 
 | |
|                 class Meta:
 | |
|                     app_label = label
 | |
| 
 | |
|             class ConcreteReferent(AbstractReferent):
 | |
|                 class Meta:
 | |
|                     app_label = label
 | |
| 
 | |
|             self.assertEqual(
 | |
|                 ConcreteReferent._meta.get_field("reference").related_model, Referred
 | |
|             )
 | |
|             self.assertEqual(ConcreteReferent.reference.through, Through)
 | |
| 
 | |
|         assert_app_model_resolved("model_fields")
 | |
|         assert_app_model_resolved("tests")
 | |
| 
 | |
|     def test_invalid_to_parameter(self):
 | |
|         msg = (
 | |
|             "ManyToManyField(1) is invalid. First parameter to "
 | |
|             "ManyToManyField must be either a model, a model name, or the "
 | |
|             "string 'self'"
 | |
|         )
 | |
|         with self.assertRaisesMessage(TypeError, msg):
 | |
| 
 | |
|             class MyModel(models.Model):
 | |
|                 m2m = models.ManyToManyField(1)
 | |
| 
 | |
|     @isolate_apps("model_fields")
 | |
|     def test_through_db_table_mutually_exclusive(self):
 | |
|         class Child(models.Model):
 | |
|             pass
 | |
| 
 | |
|         class Through(models.Model):
 | |
|             referred = models.ForeignKey(Child, on_delete=models.CASCADE)
 | |
|             referent = models.ForeignKey(Child, on_delete=models.CASCADE)
 | |
| 
 | |
|         msg = "Cannot specify a db_table if an intermediary model is used."
 | |
|         with self.assertRaisesMessage(ValueError, msg):
 | |
| 
 | |
|             class MyModel(models.Model):
 | |
|                 m2m = models.ManyToManyField(
 | |
|                     Child,
 | |
|                     through="Through",
 | |
|                     db_table="custom_name",
 | |
|                 )
 | |
| 
 | |
| 
 | |
| class ManyToManyFieldDBTests(TestCase):
 | |
|     def test_value_from_object_instance_without_pk(self):
 | |
|         obj = ManyToMany()
 | |
|         self.assertEqual(obj._meta.get_field("m2m").value_from_object(obj), [])
 | |
| 
 | |
|     def test_value_from_object_instance_with_pk(self):
 | |
|         obj = ManyToMany.objects.create()
 | |
|         related_obj = ManyToMany.objects.create()
 | |
|         obj.m2m.add(related_obj)
 | |
|         self.assertEqual(
 | |
|             obj._meta.get_field("m2m").value_from_object(obj), [related_obj]
 | |
|         )
 |