到目前为止做了什么:
affpart.damage_types.all()
,但现在这种情况开始变得更加频繁,并且变得非常痛苦。说明
我在一个项目下有两个Django应用程序。其中一个应用程序使用多对多关系在另一个应用程序中使用模型。
这几个月已经顺利运行,事实上它在我的生产机器上工作正常但在我的开发机器上失败了。最近的情况是我被要求添加一个新功能,当我开始处理它时,我得到一个FieldError
相关代码,我甚至没有触及过。
此最新一期的违规行为是:
for dt in affpart.damage_types.all()
错误是:
Cannot resolve keyword u'affectedpart' into field. Choices are: cgs_damage_code, description, id, reg_exp, sti
错误发生在query.py
模块中Django的内容中。
从高级别开始,当我尝试在不同的Django应用程序中使用模型之间的多对多时,会发生此错误。例如,受影响的部件可能有多种类型的损坏,并且可以在不同的受影响部件上找到损坏类型。
这两个应用是:trending
和sitar
sitar
并且拥有了我想要从趋势中使用的模型。
在trending
中,我的models.py
文件的AffectedPart
模型如下:
from sitar.models import (Part, DamageType, Aircraft)
# this model is in trendin.models
class AffectedPart(models.Model):
res = models.ForeignKey(Res, null=True)
arising = models.ForeignKey(Arising, null=True)
aircraft = models.ForeignKey(Aircraft)
# filled out automatically only if part to Damage/Repair type matching done
maintenance_phase = models.CharField(max_length=10,
choices=MAINTENANCE_PHASE_CHOICES)
occurrence_date = models.DateField()
partnumber = models.ForeignKey(Part)
damage_types = models.ManyToManyField(DamageType, null=True, blank=True)
repair_types = models.ManyToManyField(RepairType, null=True, blank=True)
def __unicode__(self, ):
if self.res:
parent = self.res.number
else:
parent = str(self.arising)
return '{0} - {1}'.format(self.partnumber.number, parent)
# The following models are in sitar.models
class Part(models.Model):
''' This model is used to create pick-lists so the user can associate
one or more applicable parts from a pre-defined list to
a tracked item.
It will also allow for regular CRUD functionality which is
implemented by taking advantage of the Django admin interface. '''
# Added to associate a zone with a part
zones = models.ManyToManyField("Zone", null=True, blank=True)
number = models.CharField(max_length=50, unique=True)
description = models.CharField(max_length=100, blank=True)
comments = models.TextField(blank=True)
material = models.CharField(max_length=100, blank=True)
class Meta:
''' Order by part number field (ascending) when presenting data '''
ordering = ['number']
def __unicode__(self):
''' Return unicode description of a part instance '''
if self.description:
return '%s -- %s' % (self.number, self.description)
else:
return self.number
def get_encoded_part_number(self):
'''
This method will remove any '/' in part numbers and replace them
with '~' so that they can be used in URLs.
'''
return self.number.replace('/','~')
class DamageType(models.Model):
description = models.CharField(max_length=50, unique=True)
# a regular expression to account for possible spelling mistakes when
# querying the database
reg_exp = models.CharField(max_length=50, blank=True)
# Added to provide damage code for TRENDING
cgs_damage_code = models.CharField(max_length=10, blank=True,
verbose_name="CGS Damage Code")
def __unicode__(self):
''' Return unicode representation of a DamageType instance. '''
return self.description
class Meta:
''' Order by description field (ascending) when presenting data '''
ordering = ['description']
def save(self):
''' Override the save method of the DamageType model in order to assign
a regexp if one does not exist.'''
# if the tracked item does not have a reg_exp just use
# the description
if not self.reg_exp:
self.reg_exp = self.description
super(DamageType,self).save()
堆栈跟踪
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/trending/trend/
Django Version: 1.6
Python Version: 2.6.7
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'sitar')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')
Traceback:
File "C:\virtual_env\sitar_env2\lib\site-packages\django\core\handlers\base.py" in get_response
114. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\virtual_env\sitar_env2\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view
22. return view_func(request, *args, **kwargs)
File "C:\virtual_env\sitar_env2\cissimp\trending\views.py" in trend
418. list_result = utils.convert_queryset_to_lists(q_results, form)
File "C:\virtual_env\sitar_env2\cissimp\trending\utils.py" in convert_queryset_to_lists
918. for dt in affpart.damage_types.all()]),
File "C:\virtual_env\sitar_env2\lib\site-packages\django\db\models\manager.py" in all
133. return self.get_queryset()
File "C:\virtual_env\sitar_env2\lib\site-packages\django\db\models\fields\related.py" in get_queryset
539. return super(ManyRelatedManager, self).get_queryset().using(db)._next_is_sticky().filter(**self.core_filters)
File "C:\virtual_env\sitar_env2\lib\site-packages\django\db\models\query.py" in filter
590. return self._filter_or_exclude(False, *args, **kwargs)
File "C:\virtual_env\sitar_env2\lib\site-packages\django\db\models\query.py" in _filter_or_exclude
608. clone.query.add_q(Q(*args, **kwargs))
File "C:\virtual_env\sitar_env2\lib\site-packages\django\db\models\sql\query.py" in add_q
1198. clause = self._add_q(where_part, used_aliases)
File "C:\virtual_env\sitar_env2\lib\site-packages\django\db\models\sql\query.py" in _add_q
1232. current_negated=current_negated)
File "C:\virtual_env\sitar_env2\lib\site-packages\django\db\models\sql\query.py" in build_filter
1100. allow_explicit_fk=True)
File "C:\virtual_env\sitar_env2\lib\site-packages\django\db\models\sql\query.py" in setup_joins
1351. names, opts, allow_many, allow_explicit_fk)
File "C:\virtual_env\sitar_env2\lib\site-packages\django\db\models\sql\query.py" in names_to_path
1274. "Choices are: %s" % (name, ", ".join(available)))
Exception Type: FieldError at /trending/trend/
Exception Value: Cannot resolve keyword u'affectedpart' into field. Choices are: cgs_damage_code, description, id, reg_exp, sti
如果有人有解决方案,或者知道一个应用程序中的模型的最佳实践,并且在另一个应用程序中与模型有多对多的关系,我很乐意听到它。
由于
答案 0 :(得分:0)
看起来像是在试图打电话的地方:
damage_type.affectedpart.all()
或类似的东西。 要获得损坏类型的所有受影响部件,您需要执行以下操作:
damage_type.affectedpart_set.all()
您可以在documentation.
中详细了解相关信息如果这不是您的错误,请跟踪有问题的代码。
答案 1 :(得分:0)
您是否已将DamageType
关系从ForeignKey
更改为ManyToMany
?
我猜你做了,Django从未创建过中间表,所以它试图使用DamageType
表。这就是为什么它正在寻找与AffectedPart
的关系。
当您进行模型更改时,您应该使用类似South的内容进行迁移,因为更改为ManyToMany
字段并不像听起来那么简单。
否则,请自行创建"through"表。
答案 2 :(得分:0)
错误发生是因为我忽略了将"trending"
放入INSTALLED_APPS
。
由于它使用完全相同的设置文件在生产中工作,所以我从未想过要看那里。
感谢Collin Anderson在django-users@googlegroups.com论坛上发表的演讲。
Collin感兴趣的一些评论:
2.我在生产中使用相同的代码,它没有任何问题。知道为什么吗? 在开发中,大多数(如果不是全部)代码在启动时和生产中(至少在1.7之前)加载和运行,实际上只是根据需要加载。基本上使用app加载重构和django.setup(),我们终于解决了这样的问题。