django 设置指向自己的多对多关系,且要增加额外字段而需自定义关系表,执行py manage.py makemigrations时报fields.E304 错误.related

xiaoxiao2025-06-12  24

 原始代码:

# 邻区多对多关系表 class ZJadjacent(models.Model): cellfrom = models.ForeignKey(ZJcell, on_delete=models.CASCADE) cellto = models.ForeignKey(ZJcell, on_delete=models.CASCADE) # 两个邻区间的距离 distance = models.IntegerField() # 站在源小区,看目标小区的方位角 azi1 = models.IntegerField() # 站在目标小区,看源小区的方位角 azi2 = models.IntegerField()

执行py manage.py makemigrations时报错:

(venv) C:\Users\Administrator\PycharmProjects\cellsmap>py manage.py makemigrations SystemCheckError: System check identified some issues:

ERRORS: dbbackend.ZJadjacent.cellfrom: (fields.E304) Reverse accessor for 'ZJadjacent.cellfrom' clashes with reverse accessor for 'ZJadjacent.cellto'.         HINT: Add or change a related_name argument to the definition for 'ZJadjacent.cellfrom' or 'ZJadjacent.cellto'. dbbackend.ZJadjacent.cellto: (fields.E304) Reverse accessor for 'ZJadjacent.cellto' clashes with reverse accessor for 'ZJadjacent.cellfrom'.         HINT: Add or change a related_name argument to the definition for 'ZJadjacent.cellto' or 'ZJadjacent.cellfrom'.

官网解释:

ManyToManyField.related_name¶

Same as ForeignKey.related_name.

ForeignKey.related_name¶

The name to use for the relation from the related object back to this one. It's also the default value for related_query_name (the name to use for the reverse filter name from the target model). See the related objects documentation for a full explanation and example. Note that you must set this value when defining relations on abstract models; and when you do so some special syntax is available.

 

如果想关闭反查或者反向关系,可将related_name 设为 '+'。

注意:这与多对多字段的对称属性symmetrical=False不同,之前我将多对多字段的对称属性symmetrical=False误认为是关闭反查关系。详见:

https://blog.csdn.net/qq_27361945/article/details/83181900

 

If you'd prefer Django not to create a backwards relation, set related_name to '+' or end it with '+'. For example, this will ensure that the User model won't have a backwards relation to this model:

user = models.ForeignKey( User, on_delete=models.CASCADE, related_name='+', )

虽然没有ManyToManyField的例子,但是也是一样的,ManyToManyField相当于两个ForeignKey。

定义:

from django.db import models class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def __str__(self): return self.name class Author(models.Model): name = models.CharField(max_length=200) email = models.EmailField() def __str__(self): return self.name class Entry(models.Model): blog = models.ForeignKey(Blog, on_delete=models.CASCADE) headline = models.CharField(max_length=255) body_text = models.TextField() pub_date = models.DateField() mod_date = models.DateField() authors = models.ManyToManyField(Author) n_comments = models.IntegerField() n_pingbacks = models.IntegerField() rating = models.IntegerField() def __str__(self): return self.headline

Following relationships "backward"¶

If a model has a ForeignKey, instances of the foreign-key model will have access to a Manager that returns all instances of the first model. By default, this Manager is named FOO_set, where FOO is the source model name, lowercased. This Manager returns QuerySets, which can be filtered and manipulated as described in the "Retrieving objects" section above.

举例:

>>> b = Blog.objects.get(id=1) >>> b.entry_set.all() # Returns all Entry objects related to Blog. # b.entry_set is a Manager that returns QuerySets. >>> b.entry_set.filter(headline__contains='Lennon') >>> b.entry_set.count()

注意:没有定义related_name的外键,反查时用entry_set,即原模型的名字 Entry的小写(class Entry(models.Model):)

一单定义了related_name='entries',反查时用entries代替entry_set。

但是多对多怎么理解?

在反查时,如果指明ZJadjacent关系表中的两个models.ForeignKey(ZJcell, on_delete=models.CASCADE)哪个是源小区,哪个是目标小区,通过ZJcell对象反查邻区关系时:

ZJcell.objects.first().zjadjacent_set

就会发生混淆,因为ZJcell.objects.first()这个实例既可以是源小区,也可以是目标小区,我们到底要从它是源小区的关系表中提取数据,还是从目标小区的关系表中提取数据,从ZJcell.objects.first().zjadjacent_set中看不出来。程序就会混淆。

 

当增加related_name='from_cell_id'后,就可以这样查:

ZJcell.objects.first().from_cell_id

这样就知道是把ZJcell.objects.first()当做源小区,从邻区表中提取数据,而不会提取邻区表中ZJcell.objects.first()是目标小区的数据。

You can override the FOO_set name by setting the related_name parameter in the ForeignKey definition. For example, if the Entry model was altered to blog = ForeignKey(Blog, on_delete=models.CASCADE, related_name='entries'), the above example code would look like this:

>>> b = Blog.objects.get(id=1) >>> b.entries.all() # Returns all Entry objects related to Blog. # b.entries is a Manager that returns QuerySets. >>> b.entries.filter(headline__contains='Lennon') >>> b.entries.count()

 

修改 后的代码:

# 邻区多对多关系表 class ZJadjacent(models.Model): cellfrom = models.ForeignKey(ZJcell, on_delete=models.CASCADE, related_name='from_cell_id') # 因为有两个ZJcell外键,必须对这两个外键命名为不同的名字,否则出现报错fields.E304 cellto = models.ForeignKey(ZJcell, on_delete=models.CASCADE, related_name='to_cell_id') # 两个邻区间的距离 distance = models.IntegerField() # 站在源小区,看目标小区的方位角 azi1 = models.IntegerField() # 站在目标小区,看源小区的方位角 azi2 = models.IntegerField()

当增加related_name='from_cell_id'后,就可以这样查:

ZJcell.objects.first().from_cell_id

这样就知道是把ZJcell.objects.first()当做源小区,从邻区表中提取数据,而不会提取邻区表中ZJcell.objects.first()是目标小区的数据。

https://blog.csdn.net/meylovezn/article/details/46924893

 

 

(venv) C:\Users\Administrator\PycharmProjects\cellsmap>py manage.py makemigrations You are trying to add a non-nullable field 'azi1' to zjadjacent without a default; we can't do that (the database needs something to populate existing rows). Please select a fix:  1) Provide a one-off default now (will be set on all existing rows with a null value for this column)  2) Quit, and let me add a default in models.py Select an option: 2

# 邻区多对多关系表 class ZJadjacent(models.Model): cellfrom = models.ForeignKey(ZJcell, on_delete=models.CASCADE, related_name='from_cell_id') # 因为有两个ZJcell外键,必须对这两个外键命名为不同的名字,否则出现报错fields.E304 cellto = models.ForeignKey(ZJcell, on_delete=models.CASCADE, related_name='to_cell_id') # 两个邻区间的距离 distance = models.IntegerField(default=None) # 站在源小区,看目标小区的方位角 azi1 = models.IntegerField(default=None) # 站在目标小区,看源小区的方位角 azi2 = models.IntegerField(default=None)

 

转载请注明原文地址: https://www.6miu.com/read-5031728.html

最新回复(0)