I have a model like this one:
class MyReport(models.Model): group_id = models.PositiveIntegerField(blank=False, null=False) test = models.ForeignKey(Test, on_delete=models.CASCADE) owner = models.ForeignKey(User, editable=False, default=get_current_user, on_delete=models.CASCADE) user_objects = UserFilterManager() @property def location(self): return self.test.location
to which I added a location property. I get this error at run-time. I pasted only parts below my latest call, which was to len() in this case (I know, use count instead).
File "C:\Python27\Lib\site-packages\django\db\models\query.py", line 240, in __len__ self._fetch_all() File "C:\Python27\Lib\site-packages\django\db\models\query.py", line 1074, in _fetch_all self._result_cache = list(self.iterator()) File "C:\Python27\Lib\site-packages\django\db\models\query.py", line 75, in __iter__ setattr(obj, attr_name, row[col_pos]) AttributeError: can't set attribute
I cannot figure why the error? If I call it locationx then there is no error.
Are there some special property definition rules for Django?
How could I debug this?
I added the property since I added the test indirection and want to change as little code as possible. I could, of course, just change each report.location
to report.test.location
, but that's a nuisance. It would be great if I could define an alias for DB searches so I would need to change those either.
EDIT: To answer the comments:
report.location
instead adding an indirection report.test.location
(don't want to change existing code where location was inside the report model).self.test.location
and report.test.location
work, and also reports.locationx
works as well.len(MyReport.objects.all())
. Here is a full trace from the Eclipse console:
Traceback (most recent call last): File "C:\Eclipse-SDK-4.2.1-win32-x86_64\plugins\org.python.pydev_2.7.1.2012100913\pysrc\pydevd_comm.py", line 765, in doIt result = pydevd_vars.evaluateExpression(self.thread_id, self.frame_id, self.expression, self.doExec) File "C:\Eclipse-SDK-4.2.1-win32-x86_64\plugins\org.python.pydev_2.7.1.2012100913\pysrc\pydevd_vars.py", line 378, in evaluateExpression sys.stdout.write('%s\n' % (result,)) File "C:\Python27\Lib\site-packages\django\db\models\query.py", line 234, in __repr__ data = list(self[:REPR_OUTPUT_SIZE + 1]) File "C:\Python27\Lib\site-packages\django\db\models\query.py", line 258, in __iter__ self._fetch_all() File "C:\Python27\Lib\site-packages\django\db\models\query.py", line 1074, in _fetch_all self._result_cache = list(self.iterator()) File "C:\Python27\Lib\site-packages\django\db\models\query.py", line 75, in __iter__ setattr(obj, attr_name, row[col_pos]) AttributeError: can't set attribute
How is it possible? The explanation you are getting this error is that you are naming the setter method mistakenly. You have named the setter method as set_x which is off base, this is the reason you are getting the Attribute Error.
Namedtuples are immutable objects, so you cannot change the attribute values. But standard Python classes are mutable, so they can be changed arbitrarily. Specifically, you can change an existing attribute's value and even dynamically add a new attribute to an existing object.
The problem was a name clash.
Apparently when querying the DB I had:
objs = MyReport.objects.annotate(location=F('test__location'))
This added location
to the objects (didn't see it in __dict__
, but maybe I just missed it). This means I could give up the property since I could call report_instance.location
. Of course, this means that all places that access MyReport I need to add the annotation (a special manager?).
I have the same problem. I solved it by
@location.setter def location(self, val): pass
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With