Ticket #14549: #14549-intermediary_m2m_disambiguation.diff
File #14549-intermediary_m2m_disambiguation.diff, 6.0 KB (added by , 14 years ago) |
---|
-
django/db/models/fields/related.py
998 998 if kwargs['rel'].through is not None: 999 999 assert self.db_table is None, "Cannot specify a db_table if an intermediary model is used." 1000 1000 1001 self.source_fk_name = kwargs.pop('source_fk_name', None) 1002 self.target_fk_name = kwargs.pop('target_fk_name', None) 1003 1001 1004 Field.__init__(self, **kwargs) 1002 1005 1003 1006 msg = _('Hold down "Control", or "Command" on a Mac, to select more than one.') … … 1023 1026 return getattr(self, cache_attr) 1024 1027 for f in self.rel.through._meta.fields: 1025 1028 if hasattr(f,'rel') and f.rel and f.rel.to == related.model: 1026 setattr(self, cache_attr, getattr(f, attr)) 1027 return getattr(self, cache_attr) 1029 if not self.source_fk_name or self.source_fk_name == f.name: 1030 setattr(self, cache_attr, getattr(f, attr)) 1031 return getattr(self, cache_attr) 1028 1032 1029 1033 def _get_m2m_reverse_attr(self, related, attr): 1030 1034 "Function that can be curried to provide the related accessor or DB column name for the m2m table" … … 1034 1038 found = False 1035 1039 for f in self.rel.through._meta.fields: 1036 1040 if hasattr(f,'rel') and f.rel and f.rel.to == related.parent_model: 1037 if related.model == related.parent_model:1041 if not self.target_fk_name and related.model == related.parent_model: 1038 1042 # If this is an m2m-intermediate to self, 1039 1043 # the first foreign key you find will be 1040 1044 # the source column. Keep searching for … … 1044 1048 break 1045 1049 else: 1046 1050 found = True 1047 el se:1051 elif not self.target_fk_name or self.target_fk_name == f.name: 1048 1052 setattr(self, cache_attr, getattr(f, attr)) 1049 1053 break 1050 1054 return getattr(self, cache_attr) -
django/core/management/validation.py
160 160 ) 161 161 ) 162 162 else: 163 if rel_to == from_model :163 if rel_to == from_model and (not getattr(f, 'source_fk_name', None) or f.source_fk_name == inter_field.name): 164 164 if seen_from: 165 165 e.add(opts, "Intermediary model %s has more " 166 166 "than one foreign key to %s, which is " 167 "ambiguous and is not permitted." % ( 167 "ambiguous and is not permitted. Add an source_fk_name " 168 "argument to the definition for %s." % ( 168 169 f.rel.through._meta.object_name, 169 from_model._meta.object_name 170 from_model._meta.object_name, 171 f.name 170 172 ) 171 173 ) 172 174 else: 173 175 seen_from = True 174 elif rel_to == to_model :176 elif rel_to == to_model and (not getattr(f, 'target_fk_name', None) or f.target_fk_name == inter_field.name): 175 177 if seen_to: 176 178 e.add(opts, "Intermediary model %s has more " 177 "than one foreign key to %s , which is"178 "a mbiguous and is not permitted." % (179 "than one foreign key to %s. Add a target_fk_name " 180 "argument to the definition for %s." % ( 179 181 f.rel.through._meta.object_name, 180 rel_to._meta.object_name 182 rel_to._meta.object_name, 183 f.name 181 184 ) 182 185 ) 183 186 else: -
docs/topics/db/models.txt
433 433 434 434 There are a few restrictions on the intermediate model: 435 435 436 * Your intermediate model must contain one - and *only* one - foreign key 437 to the target model (this would be ``Person`` in our example). If you 438 have more than one foreign key, a validation error will be raised. 436 * To automatically detect the target foreign key, your intermediate model 437 must contain one - and *only* one - foreign key to the target model (this 438 would be ``Person`` in our example). If you have more than one foreign 439 key, you will need to specify the field name by specifying a 440 :attr:`~django.db.models.ManyToManyField.target_fk_name`. 439 441 440 * Your intermediate model must contain one - and *only* one - foreign key 441 to the source model (this would be ``Group`` in our example). If you 442 have more than one foreign key, a validation error will be raised. 442 * To automatically detect the source foreign key, your intermediate model 443 must contain one - and *only* one - foreign key to the source model (this 444 would be ``Group`` in our example). If you have more than one foreign key, 445 you will need to specify the field name by specifying a 446 :attr:`~django.db.models.ManyToManyField.source_fk_name`. 443 447 444 448 * The only exception to this is a model which has a many-to-many 445 449 relationship to itself, through an intermediary model. In this