mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixes #2216 -- Added extra tests for model validity, and cleaned up warning messages for existing tests. Models are now invalid if the query string required to access a field (or related object) would clash with the name of another field (or related object). Previous tests only checked the accessor names, not the query string.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@3215 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -863,18 +863,29 @@ def get_validation_errors(outfile, app=None): | |||||||
|                     e.add(opts, "'%s' has relation with model %s, which has not been installed" % (f.name, rel_opts.object_name)) |                     e.add(opts, "'%s' has relation with model %s, which has not been installed" % (f.name, rel_opts.object_name)) | ||||||
|  |  | ||||||
|                 rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name() |                 rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name() | ||||||
|  |                 rel_query_name = f.related_query_name() | ||||||
|                 for r in rel_opts.fields: |                 for r in rel_opts.fields: | ||||||
|                     if r.name == rel_name: |                     if r.name == rel_name: | ||||||
|                         e.add(opts, "'%s' accessor name '%s.%s' clashes with another field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) |                         e.add(opts, "Accessor for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) | ||||||
|  |                     if r.name == rel_query_name: | ||||||
|  |                         e.add(opts, "Reverse query name for field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) | ||||||
|                 for r in rel_opts.many_to_many: |                 for r in rel_opts.many_to_many: | ||||||
|                     if r.name == rel_name: |                     if r.name == rel_name: | ||||||
|                         e.add(opts, "'%s' accessor name '%s.%s' clashes with a m2m field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) |                         e.add(opts, "Accessor for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) | ||||||
|  |                     if r.name == rel_query_name: | ||||||
|  |                         e.add(opts, "Reverse query name for field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) | ||||||
|                 for r in rel_opts.get_all_related_many_to_many_objects(): |                 for r in rel_opts.get_all_related_many_to_many_objects(): | ||||||
|                     if r.get_accessor_name() == rel_name: |                     if r.get_accessor_name() == rel_name: | ||||||
|                         e.add(opts, "'%s' accessor name '%s.%s' clashes with a related m2m field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) |                         e.add(opts, "Accessor for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) | ||||||
|  |                     if r.get_accessor_name() == rel_query_name: | ||||||
|  |                         e.add(opts, "Reverse query name for field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) | ||||||
|                 for r in rel_opts.get_all_related_objects(): |                 for r in rel_opts.get_all_related_objects(): | ||||||
|                     if r.get_accessor_name() == rel_name and r.field is not f: |                     if r.field is not f: | ||||||
|                         e.add(opts, "'%s' accessor name '%s.%s' clashes with another related field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) |                         if r.get_accessor_name() == rel_name: | ||||||
|  |                             e.add(opts, "Accessor for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) | ||||||
|  |                         if r.get_accessor_name() == rel_query_name: | ||||||
|  |                             e.add(opts, "Reverse query name for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) | ||||||
|  |  | ||||||
|                  |                  | ||||||
|         for i, f in enumerate(opts.many_to_many): |         for i, f in enumerate(opts.many_to_many): | ||||||
|             # Check to see if the related m2m field will clash with any |             # Check to see if the related m2m field will clash with any | ||||||
| @@ -884,18 +895,28 @@ def get_validation_errors(outfile, app=None): | |||||||
|                 e.add(opts, "'%s' has m2m relation with model %s, which has not been installed" % (f.name, rel_opts.object_name)) |                 e.add(opts, "'%s' has m2m relation with model %s, which has not been installed" % (f.name, rel_opts.object_name)) | ||||||
|  |  | ||||||
|             rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name() |             rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name() | ||||||
|  |             rel_query_name = f.related_query_name() | ||||||
|             for r in rel_opts.fields: |             for r in rel_opts.fields: | ||||||
|                 if r.name == rel_name: |                 if r.name == rel_name: | ||||||
|                     e.add(opts, "'%s' m2m accessor name '%s.%s' clashes with another field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) |                     e.add(opts, "Accessor for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) | ||||||
|  |                 if r.name == rel_query_name: | ||||||
|  |                     e.add(opts, "Reverse query name for m2m field '%s' clashes with field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) | ||||||
|             for r in rel_opts.many_to_many: |             for r in rel_opts.many_to_many: | ||||||
|                 if r.name == rel_name: |                 if r.name == rel_name: | ||||||
|                     e.add(opts, "'%s' m2m accessor name '%s.%s' clashes with a m2m field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) |                     e.add(opts, "Accessor for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) | ||||||
|  |                 if r.name == rel_query_name: | ||||||
|  |                     e.add(opts, "Reverse query name for m2m field '%s' clashes with m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.name, f.name)) | ||||||
|             for r in rel_opts.get_all_related_many_to_many_objects(): |             for r in rel_opts.get_all_related_many_to_many_objects(): | ||||||
|                 if r.get_accessor_name() == rel_name and r.field is not f: |                 if r.field is not f: | ||||||
|                     e.add(opts, "'%s' m2m accessor name '%s.%s' clashes with a related m2m field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) |                     if r.get_accessor_name() == rel_name: | ||||||
|  |                         e.add(opts, "Accessor for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) | ||||||
|  |                     if r.get_accessor_name() == rel_query_name: | ||||||
|  |                         e.add(opts, "Reverse query name for m2m field '%s' clashes with related m2m field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) | ||||||
|             for r in rel_opts.get_all_related_objects(): |             for r in rel_opts.get_all_related_objects(): | ||||||
|                 if r.get_accessor_name() == rel_name: |                 if r.get_accessor_name() == rel_name: | ||||||
|                     e.add(opts, "'%s' m2m accessor name '%s.%s' clashes with another related field. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) |                     e.add(opts, "Accessor for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) | ||||||
|  |                 if r.get_accessor_name() == rel_query_name: | ||||||
|  |                     e.add(opts, "Reverse query name for m2m field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) | ||||||
|  |  | ||||||
|         # Check admin attribute. |         # Check admin attribute. | ||||||
|         if opts.admin is not None: |         if opts.admin is not None: | ||||||
|   | |||||||
| @@ -17,17 +17,19 @@ class FieldErrors(models.Model): | |||||||
|  |  | ||||||
| class Target(models.Model): | class Target(models.Model): | ||||||
|     tgt_safe = models.CharField(maxlength=10) |     tgt_safe = models.CharField(maxlength=10) | ||||||
|  |     clash1 = models.CharField(maxlength=10) | ||||||
|  |     clash2 = models.CharField(maxlength=10) | ||||||
|  |  | ||||||
|     clash1_set = models.CharField(maxlength=10) |     clash1_set = models.CharField(maxlength=10) | ||||||
|  |  | ||||||
| class Clash1(models.Model): | class Clash1(models.Model): | ||||||
|     src_safe = models.CharField(maxlength=10) |     src_safe = models.CharField(maxlength=10, core=True) | ||||||
|  |  | ||||||
|     foreign = models.ForeignKey(Target) |     foreign = models.ForeignKey(Target) | ||||||
|     m2m = models.ManyToManyField(Target) |     m2m = models.ManyToManyField(Target) | ||||||
|  |  | ||||||
| class Clash2(models.Model): | class Clash2(models.Model): | ||||||
|     src_safe = models.CharField(maxlength=10) |     src_safe = models.CharField(maxlength=10, core=True) | ||||||
|  |  | ||||||
|     foreign_1 = models.ForeignKey(Target, related_name='id') |     foreign_1 = models.ForeignKey(Target, related_name='id') | ||||||
|     foreign_2 = models.ForeignKey(Target, related_name='src_safe') |     foreign_2 = models.ForeignKey(Target, related_name='src_safe') | ||||||
| @@ -36,6 +38,7 @@ class Clash2(models.Model): | |||||||
|     m2m_2 = models.ManyToManyField(Target, related_name='src_safe') |     m2m_2 = models.ManyToManyField(Target, related_name='src_safe') | ||||||
|  |  | ||||||
| class Target2(models.Model): | class Target2(models.Model): | ||||||
|  |     clash3 = models.CharField(maxlength=10) | ||||||
|     foreign_tgt = models.ForeignKey(Target) |     foreign_tgt = models.ForeignKey(Target) | ||||||
|     clashforeign_set = models.ForeignKey(Target) |     clashforeign_set = models.ForeignKey(Target) | ||||||
|  |  | ||||||
| @@ -43,6 +46,8 @@ class Target2(models.Model): | |||||||
|     clashm2m_set = models.ManyToManyField(Target) |     clashm2m_set = models.ManyToManyField(Target) | ||||||
|  |  | ||||||
| class Clash3(models.Model): | class Clash3(models.Model): | ||||||
|  |     src_safe = models.CharField(maxlength=10, core=True) | ||||||
|  |      | ||||||
|     foreign_1 = models.ForeignKey(Target2, related_name='foreign_tgt') |     foreign_1 = models.ForeignKey(Target2, related_name='foreign_tgt') | ||||||
|     foreign_2 = models.ForeignKey(Target2, related_name='m2m_tgt') |     foreign_2 = models.ForeignKey(Target2, related_name='m2m_tgt') | ||||||
|  |  | ||||||
| @@ -56,7 +61,8 @@ class ClashM2M(models.Model): | |||||||
|     m2m = models.ManyToManyField(Target2) |     m2m = models.ManyToManyField(Target2) | ||||||
|  |  | ||||||
| class SelfClashForeign(models.Model): | class SelfClashForeign(models.Model): | ||||||
|     src_safe = models.CharField(maxlength=10) |     src_safe = models.CharField(maxlength=10, core=True) | ||||||
|  |     selfclashforeign = models.CharField(maxlength=10) | ||||||
|  |  | ||||||
|     selfclashforeign_set = models.ForeignKey("SelfClashForeign") |     selfclashforeign_set = models.ForeignKey("SelfClashForeign") | ||||||
|     foreign_1 = models.ForeignKey("SelfClashForeign", related_name='id') |     foreign_1 = models.ForeignKey("SelfClashForeign", related_name='id') | ||||||
| @@ -64,11 +70,14 @@ class SelfClashForeign(models.Model): | |||||||
|  |  | ||||||
| class SelfClashM2M(models.Model): | class SelfClashM2M(models.Model): | ||||||
|     src_safe = models.CharField(maxlength=10) |     src_safe = models.CharField(maxlength=10) | ||||||
|  |     selfclashm2m = models.CharField(maxlength=10) | ||||||
|  |  | ||||||
|     selfclashm2m_set = models.ManyToManyField("SelfClashM2M") |     selfclashm2m_set = models.ManyToManyField("SelfClashM2M") | ||||||
|     m2m_1 = models.ManyToManyField("SelfClashM2M", related_name='id') |     m2m_1 = models.ManyToManyField("SelfClashM2M", related_name='id') | ||||||
|     m2m_2 = models.ManyToManyField("SelfClashM2M", related_name='src_safe') |     m2m_2 = models.ManyToManyField("SelfClashM2M", related_name='src_safe') | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| error_log = """invalid_models.fielderrors: "charfield": CharFields require a "maxlength" attribute. | error_log = """invalid_models.fielderrors: "charfield": CharFields require a "maxlength" attribute. | ||||||
| invalid_models.fielderrors: "floatfield": FloatFields require a "decimal_places" attribute. | invalid_models.fielderrors: "floatfield": FloatFields require a "decimal_places" attribute. | ||||||
| invalid_models.fielderrors: "floatfield": FloatFields require a "max_digits" attribute. | invalid_models.fielderrors: "floatfield": FloatFields require a "max_digits" attribute. | ||||||
| @@ -78,42 +87,69 @@ invalid_models.fielderrors: "choices": "choices" should be iterable (e.g., a tup | |||||||
| invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-tuples. | invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-tuples. | ||||||
| invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-tuples. | invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-tuples. | ||||||
| invalid_models.fielderrors: "index": "db_index" should be either None, True or False. | invalid_models.fielderrors: "index": "db_index" should be either None, True or False. | ||||||
| invalid_models.clash1: 'foreign' accessor name 'Target.clash1_set' clashes with another field. Add a related_name argument to the definition for 'foreign'. | invalid_models.clash1: Accessor for field 'foreign' clashes with field 'Target.clash1_set'. Add a related_name argument to the definition for 'foreign'. | ||||||
| invalid_models.clash1: 'foreign' accessor name 'Target.clash1_set' clashes with a related m2m field. Add a related_name argument to the definition for 'foreign'. | invalid_models.clash1: Accessor for field 'foreign' clashes with related m2m field 'Target.clash1_set'. Add a related_name argument to the definition for 'foreign'. | ||||||
| invalid_models.clash1: 'm2m' m2m accessor name 'Target.clash1_set' clashes with another field. Add a related_name argument to the definition for 'm2m'. | invalid_models.clash1: Reverse query name for field 'foreign' clashes with field 'Target.clash1'. Add a related_name argument to the definition for 'foreign'. | ||||||
| invalid_models.clash1: 'm2m' m2m accessor name 'Target.clash1_set' clashes with another related field. Add a related_name argument to the definition for 'm2m'. | invalid_models.clash1: Accessor for m2m field 'm2m' clashes with field 'Target.clash1_set'. Add a related_name argument to the definition for 'm2m'. | ||||||
| invalid_models.clash2: 'foreign_1' accessor name 'Target.id' clashes with another field. Add a related_name argument to the definition for 'foreign_1'. | invalid_models.clash1: Accessor for m2m field 'm2m' clashes with related field 'Target.clash1_set'. Add a related_name argument to the definition for 'm2m'. | ||||||
| invalid_models.clash2: 'foreign_1' accessor name 'Target.id' clashes with a related m2m field. Add a related_name argument to the definition for 'foreign_1'. | invalid_models.clash1: Reverse query name for m2m field 'm2m' clashes with field 'Target.clash1'. Add a related_name argument to the definition for 'm2m'. | ||||||
| invalid_models.clash2: 'foreign_2' accessor name 'Target.src_safe' clashes with a related m2m field. Add a related_name argument to the definition for 'foreign_2'. | invalid_models.clash2: Accessor for field 'foreign_1' clashes with field 'Target.id'. Add a related_name argument to the definition for 'foreign_1'. | ||||||
| invalid_models.clash2: 'm2m_1' m2m accessor name 'Target.id' clashes with another field. Add a related_name argument to the definition for 'm2m_1'. | invalid_models.clash2: Accessor for field 'foreign_1' clashes with related m2m field 'Target.id'. Add a related_name argument to the definition for 'foreign_1'. | ||||||
| invalid_models.clash2: 'm2m_1' m2m accessor name 'Target.id' clashes with another related field. Add a related_name argument to the definition for 'm2m_1'. | invalid_models.clash2: Reverse query name for field 'foreign_1' clashes with field 'Target.id'. Add a related_name argument to the definition for 'foreign_1'. | ||||||
| invalid_models.clash2: 'm2m_2' m2m accessor name 'Target.src_safe' clashes with another related field. Add a related_name argument to the definition for 'm2m_2'. | invalid_models.clash2: Reverse query name for field 'foreign_1' clashes with related m2m field 'Target.id'. Add a related_name argument to the definition for 'foreign_1'. | ||||||
| invalid_models.clash3: 'foreign_1' accessor name 'Target2.foreign_tgt' clashes with another field. Add a related_name argument to the definition for 'foreign_1'. | invalid_models.clash2: Accessor for field 'foreign_2' clashes with related m2m field 'Target.src_safe'. Add a related_name argument to the definition for 'foreign_2'. | ||||||
| invalid_models.clash3: 'foreign_1' accessor name 'Target2.foreign_tgt' clashes with a related m2m field. Add a related_name argument to the definition for 'foreign_1'. | invalid_models.clash2: Reverse query name for field 'foreign_2' clashes with related m2m field 'Target.src_safe'. Add a related_name argument to the definition for 'foreign_2'. | ||||||
| invalid_models.clash3: 'foreign_2' accessor name 'Target2.m2m_tgt' clashes with a m2m field. Add a related_name argument to the definition for 'foreign_2'. | invalid_models.clash2: Accessor for m2m field 'm2m_1' clashes with field 'Target.id'. Add a related_name argument to the definition for 'm2m_1'. | ||||||
| invalid_models.clash3: 'foreign_2' accessor name 'Target2.m2m_tgt' clashes with a related m2m field. Add a related_name argument to the definition for 'foreign_2'. | invalid_models.clash2: Accessor for m2m field 'm2m_1' clashes with related field 'Target.id'. Add a related_name argument to the definition for 'm2m_1'. | ||||||
| invalid_models.clash3: 'm2m_1' m2m accessor name 'Target2.foreign_tgt' clashes with another field. Add a related_name argument to the definition for 'm2m_1'. | invalid_models.clash2: Reverse query name for m2m field 'm2m_1' clashes with field 'Target.id'. Add a related_name argument to the definition for 'm2m_1'. | ||||||
| invalid_models.clash3: 'm2m_1' m2m accessor name 'Target2.foreign_tgt' clashes with another related field. Add a related_name argument to the definition for 'm2m_1'. | invalid_models.clash2: Reverse query name for m2m field 'm2m_1' clashes with related field 'Target.id'. Add a related_name argument to the definition for 'm2m_1'. | ||||||
| invalid_models.clash3: 'm2m_2' m2m accessor name 'Target2.m2m_tgt' clashes with a m2m field. Add a related_name argument to the definition for 'm2m_2'. | invalid_models.clash2: Accessor for m2m field 'm2m_2' clashes with related field 'Target.src_safe'. Add a related_name argument to the definition for 'm2m_2'. | ||||||
| invalid_models.clash3: 'm2m_2' m2m accessor name 'Target2.m2m_tgt' clashes with another related field. Add a related_name argument to the definition for 'm2m_2'. | invalid_models.clash2: Reverse query name for m2m field 'm2m_2' clashes with related field 'Target.src_safe'. Add a related_name argument to the definition for 'm2m_2'. | ||||||
| invalid_models.clashforeign: 'foreign' accessor name 'Target2.clashforeign_set' clashes with another field. Add a related_name argument to the definition for 'foreign'. | invalid_models.clash3: Accessor for field 'foreign_1' clashes with field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'foreign_1'. | ||||||
| invalid_models.clashm2m: 'm2m' m2m accessor name 'Target2.clashm2m_set' clashes with a m2m field. Add a related_name argument to the definition for 'm2m'. | invalid_models.clash3: Accessor for field 'foreign_1' clashes with related m2m field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'foreign_1'. | ||||||
| invalid_models.target2: 'foreign_tgt' accessor name 'Target.target2_set' clashes with a related m2m field. Add a related_name argument to the definition for 'foreign_tgt'. | invalid_models.clash3: Reverse query name for field 'foreign_1' clashes with field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'foreign_1'. | ||||||
| invalid_models.target2: 'foreign_tgt' accessor name 'Target.target2_set' clashes with a related m2m field. Add a related_name argument to the definition for 'foreign_tgt'. | invalid_models.clash3: Reverse query name for field 'foreign_1' clashes with related m2m field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'foreign_1'. | ||||||
| invalid_models.target2: 'foreign_tgt' accessor name 'Target.target2_set' clashes with another related field. Add a related_name argument to the definition for 'foreign_tgt'. | invalid_models.clash3: Accessor for field 'foreign_2' clashes with m2m field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'foreign_2'. | ||||||
| invalid_models.target2: 'clashforeign_set' accessor name 'Target.target2_set' clashes with a related m2m field. Add a related_name argument to the definition for 'clashforeign_set'. | invalid_models.clash3: Accessor for field 'foreign_2' clashes with related m2m field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'foreign_2'. | ||||||
| invalid_models.target2: 'clashforeign_set' accessor name 'Target.target2_set' clashes with a related m2m field. Add a related_name argument to the definition for 'clashforeign_set'. | invalid_models.clash3: Reverse query name for field 'foreign_2' clashes with m2m field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'foreign_2'. | ||||||
| invalid_models.target2: 'clashforeign_set' accessor name 'Target.target2_set' clashes with another related field. Add a related_name argument to the definition for 'clashforeign_set'. | invalid_models.clash3: Reverse query name for field 'foreign_2' clashes with related m2m field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'foreign_2'. | ||||||
| invalid_models.target2: 'm2m_tgt' m2m accessor name 'Target.target2_set' clashes with a related m2m field. Add a related_name argument to the definition for 'm2m_tgt'. | invalid_models.clash3: Accessor for m2m field 'm2m_1' clashes with field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'm2m_1'. | ||||||
| invalid_models.target2: 'm2m_tgt' m2m accessor name 'Target.target2_set' clashes with another related field. Add a related_name argument to the definition for 'm2m_tgt'. | invalid_models.clash3: Accessor for m2m field 'm2m_1' clashes with related field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'm2m_1'. | ||||||
| invalid_models.target2: 'm2m_tgt' m2m accessor name 'Target.target2_set' clashes with another related field. Add a related_name argument to the definition for 'm2m_tgt'. | invalid_models.clash3: Reverse query name for m2m field 'm2m_1' clashes with field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'm2m_1'. | ||||||
| invalid_models.target2: 'clashm2m_set' m2m accessor name 'Target.target2_set' clashes with a related m2m field. Add a related_name argument to the definition for 'clashm2m_set'. | invalid_models.clash3: Reverse query name for m2m field 'm2m_1' clashes with related field 'Target2.foreign_tgt'. Add a related_name argument to the definition for 'm2m_1'. | ||||||
| invalid_models.target2: 'clashm2m_set' m2m accessor name 'Target.target2_set' clashes with another related field. Add a related_name argument to the definition for 'clashm2m_set'. | invalid_models.clash3: Accessor for m2m field 'm2m_2' clashes with m2m field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'm2m_2'. | ||||||
| invalid_models.target2: 'clashm2m_set' m2m accessor name 'Target.target2_set' clashes with another related field. Add a related_name argument to the definition for 'clashm2m_set'. | invalid_models.clash3: Accessor for m2m field 'm2m_2' clashes with related field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'm2m_2'. | ||||||
| invalid_models.selfclashforeign: 'selfclashforeign_set' accessor name 'SelfClashForeign.selfclashforeign_set' clashes with another field. Add a related_name argument to the definition for 'selfclashforeign_set'. | invalid_models.clash3: Reverse query name for m2m field 'm2m_2' clashes with m2m field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'm2m_2'. | ||||||
| invalid_models.selfclashforeign: 'foreign_1' accessor name 'SelfClashForeign.id' clashes with another field. Add a related_name argument to the definition for 'foreign_1'. | invalid_models.clash3: Reverse query name for m2m field 'm2m_2' clashes with related field 'Target2.m2m_tgt'. Add a related_name argument to the definition for 'm2m_2'. | ||||||
| invalid_models.selfclashforeign: 'foreign_2' accessor name 'SelfClashForeign.src_safe' clashes with another field. Add a related_name argument to the definition for 'foreign_2'. | invalid_models.clashforeign: Accessor for field 'foreign' clashes with field 'Target2.clashforeign_set'. Add a related_name argument to the definition for 'foreign'. | ||||||
| invalid_models.selfclashm2m: 'selfclashm2m_set' m2m accessor name 'SelfClashM2M.selfclashm2m_set' clashes with a m2m field. Add a related_name argument to the definition for 'selfclashm2m_set'. | invalid_models.clashm2m: Accessor for m2m field 'm2m' clashes with m2m field 'Target2.clashm2m_set'. Add a related_name argument to the definition for 'm2m'. | ||||||
| invalid_models.selfclashm2m: 'm2m_1' m2m accessor name 'SelfClashM2M.id' clashes with another field. Add a related_name argument to the definition for 'm2m_1'. | invalid_models.target2: Accessor for field 'foreign_tgt' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'foreign_tgt'. | ||||||
| invalid_models.selfclashm2m: 'm2m_2' m2m accessor name 'SelfClashM2M.src_safe' clashes with another field. Add a related_name argument to the definition for 'm2m_2'. | invalid_models.target2: Accessor for field 'foreign_tgt' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'foreign_tgt'. | ||||||
|  | invalid_models.target2: Accessor for field 'foreign_tgt' clashes with related field 'Target.target2_set'. Add a related_name argument to the definition for 'foreign_tgt'. | ||||||
|  | invalid_models.target2: Accessor for field 'clashforeign_set' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'clashforeign_set'. | ||||||
|  | invalid_models.target2: Accessor for field 'clashforeign_set' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'clashforeign_set'. | ||||||
|  | invalid_models.target2: Accessor for field 'clashforeign_set' clashes with related field 'Target.target2_set'. Add a related_name argument to the definition for 'clashforeign_set'. | ||||||
|  | invalid_models.target2: Accessor for m2m field 'm2m_tgt' clashes with related field 'Target.target2_set'. Add a related_name argument to the definition for 'm2m_tgt'. | ||||||
|  | invalid_models.target2: Accessor for m2m field 'm2m_tgt' clashes with related field 'Target.target2_set'. Add a related_name argument to the definition for 'm2m_tgt'. | ||||||
|  | invalid_models.target2: Accessor for m2m field 'm2m_tgt' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'm2m_tgt'. | ||||||
|  | invalid_models.target2: Accessor for m2m field 'm2m_tgt' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'm2m_tgt'. | ||||||
|  | invalid_models.target2: Accessor for m2m field 'm2m_tgt' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'm2m_tgt'. | ||||||
|  | invalid_models.target2: Accessor for m2m field 'clashm2m_set' clashes with related field 'Target.target2_set'. Add a related_name argument to the definition for 'clashm2m_set'. | ||||||
|  | invalid_models.target2: Accessor for m2m field 'clashm2m_set' clashes with related field 'Target.target2_set'. Add a related_name argument to the definition for 'clashm2m_set'. | ||||||
|  | invalid_models.target2: Accessor for m2m field 'clashm2m_set' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'clashm2m_set'. | ||||||
|  | invalid_models.target2: Accessor for m2m field 'clashm2m_set' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'clashm2m_set'. | ||||||
|  | invalid_models.target2: Accessor for m2m field 'clashm2m_set' clashes with related m2m field 'Target.target2_set'. Add a related_name argument to the definition for 'clashm2m_set'. | ||||||
|  | invalid_models.selfclashforeign: Accessor for field 'selfclashforeign_set' clashes with field 'SelfClashForeign.selfclashforeign_set'. Add a related_name argument to the definition for 'selfclashforeign_set'. | ||||||
|  | invalid_models.selfclashforeign: Reverse query name for field 'selfclashforeign_set' clashes with field 'SelfClashForeign.selfclashforeign'. Add a related_name argument to the definition for 'selfclashforeign_set'. | ||||||
|  | invalid_models.selfclashforeign: Accessor for field 'foreign_1' clashes with field 'SelfClashForeign.id'. Add a related_name argument to the definition for 'foreign_1'. | ||||||
|  | invalid_models.selfclashforeign: Reverse query name for field 'foreign_1' clashes with field 'SelfClashForeign.id'. Add a related_name argument to the definition for 'foreign_1'. | ||||||
|  | invalid_models.selfclashforeign: Accessor for field 'foreign_2' clashes with field 'SelfClashForeign.src_safe'. Add a related_name argument to the definition for 'foreign_2'. | ||||||
|  | invalid_models.selfclashforeign: Reverse query name for field 'foreign_2' clashes with field 'SelfClashForeign.src_safe'. Add a related_name argument to the definition for 'foreign_2'. | ||||||
|  | invalid_models.selfclashm2m: Accessor for m2m field 'selfclashm2m_set' clashes with m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument to the definition for 'selfclashm2m_set'. | ||||||
|  | invalid_models.selfclashm2m: Reverse query name for m2m field 'selfclashm2m_set' clashes with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the definition for 'selfclashm2m_set'. | ||||||
|  | invalid_models.selfclashm2m: Accessor for m2m field 'm2m_1' clashes with field 'SelfClashM2M.id'. Add a related_name argument to the definition for 'm2m_1'. | ||||||
|  | invalid_models.selfclashm2m: Accessor for m2m field 'm2m_2' clashes with field 'SelfClashM2M.src_safe'. Add a related_name argument to the definition for 'm2m_2'. | ||||||
|  | invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_1' clashes with field 'SelfClashM2M.id'. Add a related_name argument to the definition for 'm2m_1'. | ||||||
|  | invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_2' clashes with field 'SelfClashM2M.src_safe'. Add a related_name argument to the definition for 'm2m_2'. | ||||||
| """ | """ | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| 27. Many-to-many relationships between the same two tables | 27. Many-to-many relationships between the same two tables | ||||||
|  |  | ||||||
| In this example, A Person can have many friends, who are also people. Friendship is a | In this example, A Person can have many friends, who are also people. Friendship is a | ||||||
| symmetrical relationshiup - if I am your friend, you are my friend. | symmetrical relationship - if I am your friend, you are my friend. | ||||||
|  |  | ||||||
| A person can also have many idols - but while I may idolize you, you may not think | A person can also have many idols - but while I may idolize you, you may not think | ||||||
| the same of me. 'Idols' is an example of a non-symmetrical m2m field. Only recursive | the same of me. 'Idols' is an example of a non-symmetrical m2m field. Only recursive | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user