Note that there are some explanatory texts on larger screens.

plurals
  1. POA custom field inheriting from ForeignKey throws an exception on save
    primarykey
    data
    text
    <p>I have written the following custom field:</p> <pre><code>from django.core.urlresolvers import reverse from django.db import models from django.db.models import signals from sitetree.models import Tree, TreeItem from south.modelsinspector import introspector class AutoTreeItemField(models.ForeignKey): def __init__(self, *args, **kwargs): super(AutoTreeItemField, self).__init__(TreeItem, null=True) self.date_field = kwargs['date_field'] self.__should_appear = kwargs['should_appear'] self.year_menu_item_url = kwargs['year_menu_item_url'] self.month_menu_item_url = kwargs['month_menu_item_url'] self.item_menu_item_url = kwargs['item_menu_item_url'] self.year_format = kwargs.get('year_format', '%Y') self.month_format = kwargs.get('month_format', '%B') self.inmenu = kwargs.get('inmenu', True) self.inbreadcrumbs = kwargs.get('inbreadcrumbs', True) self.insitetree = kwargs.get('insitetree', True) self.item_title = kwargs.get('title', 'title') def contribute_to_class(self, cls, name): super(AutoTreeItemField, self).contribute_to_class(cls, name) # Make this object the descriptor for field access. setattr(cls, self.name, self) self.tree = self.__get_or_create_tree(cls._meta.verbose_name_plural.lower()) # Delete menu item after the instance is deleted signals.post_delete.connect(self.__delete, cls, True) def pre_save(self, model_instance, add): super(AutoTreeItemField, self).pre_save(model_instance, add) if self.should_appear(model_instance): year_menu_item = self.__get_or_create_year_tree_item(model_instance) month_menu_item = self.__get_or_create_month_tree_item(model_instance, year_menu_item) menu_item = self.__save_menu_item(model_instance, month_menu_item) setattr(model_instance, self.get_attname(), menu_item.id) return menu_item.id else: self.__delete_orphans(model_instance) return None def __delete(self, **kwargs): self.__delete_orphans(kwargs['instace']) def __get_or_create_tree(self, alias): try: return Tree.objects.get(alias=alias) except Tree.DoesNotExist: return Tree.objects.create(alias=alias) def should_appear(self, instance): if isinstance(self.__should_appear, str): return getattr(instance, self.__should_appear) elif callable(self.__should_appear): return self.__should_appear() def south_field_triple(self): """Returns a suitable description of this field for South.""" args, kwargs = introspector(self) kwargs.update({'date_field': 'None'}) return ('website.blog.fields.AutoTreeItemField', args, kwargs) def __get_or_create_year_tree_item(self, model_instance): year = self.__get_year(model_instance) try: return TreeItem.objects.get(title=year, tree=self.tree) except TreeItem.DoesNotExist: return TreeItem.objects.create(title=year, url=reverse(self.year_menu_item_url, args = [year]), tree=self.tree, inmenu=self.inmenu, inbreadcrumbs=self.inbreadcrumbs, insitetree=self.insitetree, parent=None) def __get_year(self, model_instance): return getattr(model_instance, self.date_field).strftime(self.year_format) def __get_or_create_month_tree_item(self, model_instance, year_menu_item): month = self.__get_month(model_instance) try: return TreeItem.objects.get(title=month, tree=self.tree, parent=year_menu_item) except TreeItem.DoesNotExist: return TreeItem.objects.create(title=month, url=reverse(self.month_menu_item_url, args = [getattr(model_instance, self.date_field).year, getattr(model_instance, self.date_field).month]), tree=self.tree, inmenu=self.inmenu, inbreadcrumbs=self.inbreadcrumbs, insitetree=self.insitetree, parent=year_menu_item) def __get_month(self, model_instance): return getattr(model_instance, self.date_field).strftime(self.month_format) def __save_menu_item(self, model_instance, month_tree_item): try: item = self.__get_menu_item(model_instance) item.title = getattr(model_instance, self.item_title) item.url = model_instance.get_absolute_url() item.parent = month_tree_item return item except TreeItem.DoesNotExist: return TreeItem.objects.create(title=getattr(model_instance, self.item_title), url=model_instance.get_absolute_url(), tree=self.tree, inmenu=self.inmenu, inbreadcrumbs=self.inbreadcrumbs, insitetree=self.insitetree, parent=month_tree_item) def __get_year_tree_item(self, model_instance): year = self.__get_year(model_instance) return TreeItem.objects.filter(title=year, tree=self.tree) def __delete_orphans(self, model_instance): menu_item = self.__get_menu_item(model_instance) try: if menu_item is not None: month_menu_item = menu_item.parent menu_item.delete() if TreeItem.objects.filter(parent=month_menu_item, parent__parent=self.__get_year_tree_item(model_instance), tree=self.tree).count(): year_menu_item = month_menu_item.parent month_menu_item.delete() if TreeItem.objects.filter(parent=year_menu_item, tree=self.tree).count() == 0: year_menu_item.delete() except TreeItem.DoesNotExist: pass def __get_menu_item(self, model_instance): menu_item_id = getattr(model_instance, self.get_attname()) return TreeItem.objects.get(id=menu_item_id) </code></pre> <p>But when I'm attempting to save it I am getting: </p> <pre><code>'AutoTreeItemField' object has no attribute '_meta' </code></pre> <p>Here's the full stacktrace: </p> <pre><code>Environment: Request Method: POST Request URL: http://127.0.0.1:8000/admin/blog/draftpost/add/ Django Version: 1.3 Python Version: 2.7.1 Installed Applications: ['django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.admin', 'django.contrib.sites', 'django.contrib.flatpages', 'tagging', 'reversion', 'south', 'sitetree', 'dojango', 'disqus', 'website.blog', 'website.cms'] 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', 'dojango.middleware.DojoCollector', 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware') Traceback: File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response 111. response = callback(request, *callback_args, **callback_kwargs) File "C:\Python27\lib\site-packages\django\contrib\admin\options.py" in wrapper 307. return self.admin_site.admin_view(view)(*args, **kwargs) File "C:\Python27\lib\site-packages\django\utils\decorators.py" in _wrapped_view 93. response = view_func(request, *args, **kwargs) File "C:\Python27\lib\site-packages\django\views\decorators\cache.py" in _wrapped_view_func 79. response = view_func(request, *args, **kwargs) File "C:\Python27\lib\site-packages\django\contrib\admin\sites.py" in inner 197. return view(request, *args, **kwargs) File "C:\Python27\lib\site-packages\django\db\transaction.py" in inner 217. res = func(*args, **kwargs) File "C:\Python27\lib\site-packages\reversion\revisions.py" in _create_on_success 352. self.end() File "C:\Python27\lib\site-packages\reversion\revisions.py" in end 274. revision_set = self.follow_relationships(models) File "C:\Python27\lib\site-packages\reversion\revisions.py" in follow_relationships 244. map(_follow_relationships, object_dict) File "C:\Python27\lib\site-packages\reversion\revisions.py" in _follow_relationships 243. _follow_relationships(parent_obj) File "C:\Python27\lib\site-packages\reversion\revisions.py" in _follow_relationships 213. result_dict[obj] = self.get_version_data(obj, VERSION_CHANGE) File "C:\Python27\lib\site-packages\reversion\revisions.py" in get_version_data 254. serialized_data = serializers.serialize(registration_info.format, [obj], fields=registration_info.fields) File "C:\Python27\lib\site-packages\django\core\serializers\__init__.py" in serialize 91. s.serialize(queryset, **options) File "C:\Python27\lib\site-packages\django\core\serializers\base.py" in serialize 48. self.handle_fk_field(obj, field) File "C:\Python27\lib\site-packages\django\core\serializers\python.py" in handle_fk_field 53. if field.rel.field_name == related._meta.pk.name: Exception Type: AttributeError at /admin/blog/draftpost/add/ Exception Value: 'AutoTreeItemField' object has no attribute '_meta' </code></pre> <p>Can anyone exlpain to me how can this be? What could be done to remedy this issue?<br> The wierd thing is that it happens after the transaction ends and it saves everything I need to the database.</p> <p>EDIT:<br> The error is caused by reversion trying to serialize my instance into json. However, this is still my problem because the _meta attribute should have been there and it isn't. How can this be resolved?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload