Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The first thing that comes to my mind is that in the following comment:</p> <pre><code> # Make this object the descriptor for field access. setattr(cls, self.name, self) </code></pre> <p>you state that your field instance should act as a descriptor, yet it does not implement <code>__get__</code> nor <code>__set__</code>, which are required for the descriptor protocol. Note that <code>ForeignKey</code> itself also does not implement those, instead, it uses a <code>ReverseSingleRelatedObjectDescriptor</code>.</p> <p>Now, what happens in your case is that the serializer sees that the field is a ForeignKey, therefore it expects a model instance to be sitting in its name on the model instance. It calls <code>getattr(obj, field.name)</code> which would normally invoke the <code>ReverseSingleRelatedObjectDescriptor</code>'s <code>__get__</code> method and return an instance of the related model. In your case that particular <code>getattr</code> call returns your field instance (since it lacks <code>__get__</code>) instead of a <code>TreeItem</code> instance and that is when things go wrong.</p> <p>So, to help you with your problem, I'd choose a completely different approach. From your code it seems to me that all you need is a few convenient methods accessible from the instances containing your <code>AutoTreeItemField</code> that work automatically with a related <code>TreeItem</code> pointed to by a <code>ForeignKey</code>.</p> <p>I'd rather keep the field a regular <code>ForeignKey</code> and instead attach the convenience methods to your model class. If you need them in several models, you can always create a mixin and if you want it to be really neat, you can make a custom <code>ForeignKey</code> subclass that would only override its <code>contribute_to_class</code> to automatically add the mixin to <code>cls.__bases__</code>.</p> <p>If you need the <code>ForeignKey</code>s to be in different field names, you can even go as far as dynamically create the names of your methods by prepending them with your field's name and currying them to supply the field name as a parameter. The possibilities are almost endless.</p> <p><strong>EDIT</strong>: This can be done, for example, by creating a mixin class containing all your handy extra methods with names prefixed by <code>_TREEITEM</code>. You'll also have to make them accept all your extra parameters, like <code>year_format</code>, <code>month_format</code>, <code>inmenu</code> etc. as keyword arguments. Save these in your <code>ForeignKey</code> subclass' <code>__init__</code> method as you do currently, then in its <code>contribute_to_class</code> do something like this:</p> <pre><code>from django.utils.functional import curry ... def contribute_to_class(self, cls, name): super(...).contribute_to_class(cls, name) cls.__bases__ += (TreeItemMixin,) # Now curry all your handy methods to pass your extra parameters to them. extra_kwargs = { 'year_format': self.year_format, # ... } setattr(cls, '%s_get_year' % (self.name,), curry(cls._TREEITEM_get_year, **extra_kwargs)) # Repeat the previous line for all your methods. </code></pre> <p>Also, in your <code>ForeignKey</code> subclass you can keep your <code>pre_save</code> and your signal handler, just remember to call the appropriate methods on your model instance. When you want to call them from within your views or your business logic, you have the handy curried auto-generated aliases available on your model instances, like <code>obj.myfield_get_year()</code>.</p> <p>The other possibility is to implement the descriptor protocol in your <code>AutoTreeItemField</code> to return valid <code>TreeItem</code> instances but in that case you won't be able to access its extra methods since the descriptor will return model instances instead of itself.</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. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      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