MCPcopy
hub / github.com/django/django / _check_clashes

Method _check_clashes

django/db/models/fields/related.py:237–369  ·  view source on GitHub ↗

Check accessor and reverse query name clashes.

(self)

Source from the content-addressed store, hash-verified

235 return []
236
237 def _check_clashes(self):
238 """Check accessor and reverse query name clashes."""
239 from django.db.models.base import ModelBase
240
241 errors = []
242 opts = self.model._meta
243
244 # f.remote_field.model may be a string instead of a model. Skip if
245 # model name is not resolved.
246 if not isinstance(self.remote_field.model, ModelBase):
247 return []
248
249 # Consider that we are checking field `Model.foreign` and the models
250 # are:
251 #
252 # class Target(models.Model):
253 # model = models.IntegerField()
254 # model_set = models.IntegerField()
255 #
256 # class Model(models.Model):
257 # foreign = models.ForeignKey(Target)
258 # m2m = models.ManyToManyField(Target)
259
260 # rel_opts.object_name == "Target"
261 rel_opts = self.remote_field.model._meta
262 # If the field doesn't install a backward relation on the target model
263 # (so `is_hidden` returns True), then there are no clashes to check
264 # and we can skip these fields.
265 rel_is_hidden = self.remote_field.hidden
266 rel_name = self.remote_field.accessor_name # i. e. "model_set"
267 rel_query_name = self.related_query_name() # i. e. "model"
268 # i.e. "app_label.Model.field".
269 field_name = "%s.%s" % (opts.label, self.name)
270
271 # Check clashes between accessor or reverse query name of `field`
272 # and any other field name -- i.e. accessor for Model.foreign is
273 # model_set and it clashes with Target.model_set.
274 potential_clashes = rel_opts.fields + rel_opts.many_to_many
275 for clash_field in potential_clashes:
276 if not rel_is_hidden and clash_field.name == rel_name:
277 clash_name = f"{rel_opts.label}.{clash_field.name}"
278 errors.append(
279 checks.Error(
280 f"Reverse accessor '{rel_opts.object_name}.{rel_name}' "
281 f"for '{field_name}' clashes with field name "
282 f"'{clash_name}'.",
283 hint=(
284 "Rename field '%s', or add/change a related_name "
285 "argument to the definition for field '%s'."
286 )
287 % (clash_name, field_name),
288 obj=self,
289 id="fields.E302",
290 )
291 )
292
293 if clash_field.name == rel_query_name:
294 clash_name = f"{rel_opts.label}.{clash_field.name}"

Callers 1

checkMethod · 0.95

Calls 2

related_query_nameMethod · 0.95
appendMethod · 0.45

Tested by

no test coverage detected