What's been done so far:
affpart.damage_types.all()
with a custom function but this is starting to happen more frequently now and is becoming a real pain.Description:
I have two Django apps under one project. One of the apps makes use of models in another app using a many-to-many relationship.
This has been working smoothly for months, and in fact it works fine on my production machine but fails on my development machine. The scenario lately has been that I am asked to add a new feature and when I start to work on it I get a FieldError
in related code which I haven't even touched.
The offending line of code for this latest issue is: for dt in affpart.damage_types.all()
The error is:
Cannot resolve keyword u'affectedpart' into field. Choices are: cgs_damage_code, description, id, reg_exp, sti
The error occurs in the bowels of Django in the query.py
module.
From a high-level, this error occurs when I am trying to use a Many-to-many between models in different Django apps. For example, an affected part can have more than one type of damage and a damage type can be found on different affected parts.
The two apps are: trending
and sitar
sitar
was built first and has the models that I want to use from trending.
In trending
, my models.py
file has an AffectedPart
model something like this:
from sitar.models import (Part, DamageType, Aircraft)
class AffectedPart(models.Model):
.
.
.
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)
.If anyone has a solution to this or knows of best practices for models in one application having many-to-many relationships with models in another application I would love to hear it.
Thanks
affpart.damage_types.all()
from sitar.models import (Part, DamageType, Aircraft)
# this model is in trending.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
1. How did you know!?!
2.I have the same code in production and it was working with no problems. Any idea why?
--
You received this message because you are subscribed to a topic in the Google Groups "Django users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-users/4_Cdw5xpx-w/unsubscribe.
To unsubscribe from this group and all its topics, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/d1617a57-9a60-4727-a610-308e44789db1%40googlegroups.com.