mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #17461 -- Doc'd the presumed order of foreign keys on the intermediary model of a self-referential m2m.
Thanks Giannis Terzopoulos and Sarah Boyce for the reviews.
This commit is contained in:
		
				
					committed by
					
						 Sarah Boyce
						Sarah Boyce
					
				
			
			
				
	
			
			
			
						parent
						
							0f5dd0dff3
						
					
				
				
					commit
					9d93e35c20
				
			| @@ -2041,6 +2041,42 @@ that control how the relationship functions. | ||||
|         prefer Django not to create a backwards relation, set ``related_name`` | ||||
|         to ``'+'``. | ||||
|  | ||||
|     .. admonition:: Foreign key order in intermediary models | ||||
|  | ||||
|         When defining an asymmetric many-to-many relationship from a model to | ||||
|         itself using an intermediary model without defining | ||||
|         :attr:`through_fields`, the first foreign key in the intermediary model | ||||
|         will be treated as representing the source side of the | ||||
|         ``ManyToManyField``, and the second as the target side. For example:: | ||||
|  | ||||
|             from django.db import models | ||||
|  | ||||
|  | ||||
|             class Manufacturer(models.Model): | ||||
|                 name = models.CharField(max_length=255) | ||||
|                 clients = models.ManyToManyField( | ||||
|                     "self", symmetrical=False, related_name="suppliers", through="Supply" | ||||
|                 ) | ||||
|  | ||||
|  | ||||
|             class Supply(models.Model): | ||||
|                 supplier = models.ForeignKey( | ||||
|                     Manufacturer, models.CASCADE, related_name="supplies_given" | ||||
|                 ) | ||||
|                 client = models.ForeignKey( | ||||
|                     Manufacturer, models.CASCADE, related_name="supplies_received" | ||||
|                 ) | ||||
|                 product = models.CharField(max_length=255) | ||||
|  | ||||
|         Here, the ``Manufacturer`` model defines the many-to-many relationship | ||||
|         with ``clients`` in its role as a supplier. Therefore, the ``supplier`` | ||||
|         foreign key (the source) must come before the ``client`` foreign key | ||||
|         (the target) in the intermediary ``Supply`` model. | ||||
|  | ||||
|         Specifying :attr:`through_fields=("supplier", "client") | ||||
|         <.ManyToManyField.through_fields>` on the ``ManyToManyField`` makes the | ||||
|         order of foreign keys on the ``through`` model irrelevant. | ||||
|  | ||||
|     If you don't specify an explicit ``through`` model, there is still an | ||||
|     implicit ``through`` model class you can use to directly access the table | ||||
|     created to hold the association. It has three fields to link the models, a | ||||
|   | ||||
| @@ -533,9 +533,12 @@ There are a few restrictions on the intermediate model: | ||||
| * For a model which has a many-to-many relationship to itself through an | ||||
|   intermediary model, two foreign keys to the same model are permitted, but | ||||
|   they will be treated as the two (different) sides of the many-to-many | ||||
|   relationship. If there are *more* than two foreign keys though, you | ||||
|   must also specify ``through_fields`` as above, or a validation error | ||||
|   will be raised. | ||||
|   relationship. If :attr:`~.ManyToManyField.through_fields` is not specified, | ||||
|   the first foreign key will be taken to represent the source side of the | ||||
|   ``ManyToManyField``, while the second will be taken to represent the target | ||||
|   side. If there are *more* than two foreign keys though, you must specify | ||||
|   :attr:`~.ManyToManyField.through_fields` to explicitly indicate which foreign | ||||
|   keys to use, otherwise a validation error will be raised. | ||||
|  | ||||
| Now that you have set up your :class:`~django.db.models.ManyToManyField` to use | ||||
| your intermediary model (``Membership``, in this case), you're ready to start | ||||
|   | ||||
		Reference in New Issue
	
	Block a user