0

I have the following Django model that extends the Post model from django basic blog:

from django.basic.blog.models import Post
from l10n.utils import lookup_translation

class ExtendedPost(Post):
    class Meta:
        proxy = True
    def translated_title(self, language_code=None):
        return lookup_translation(self, 'title', language_code)

I'm trying to use django basic blog's view by just overriding their template and making use of the new ExtendedPost behaviour in there:

{{ post.extendedpost.translated_title }}

But obviously this doesn't work because you can't just access a subclass like that. How DO you do this type of thing?

pancakes
  • 741
  • 1
  • 7
  • 15

3 Answers3

1

Well, the view would still be referencing the original model, so you'd have to modify the view to pass in the ExtendedPost class.

You can't just define a proxy model and have it magically override the parent class.

  1. Untested idea based on: Can django's auth_user.username be varchar(75)? How could that be done?

    from django.db.models.signals import class_prepared
    
    def add_func(sender, *args, **kwargs):
        if sender.__name__ == "Post" and sender.__module__ == "django-basic-blog-module":
            sender.translated_title = lambda self, language_code=None: lookup_translations(self, 'title', language_code)
    
    class_prepared.connect(add_func)
    
  2. Override sys.modules

    import sys
    from django.basic.blog import models
    
    models.Post.translated_title = lambda self, language_code=None: lookup_translations(self, 'title', language_code)
    
Community
  • 1
  • 1
Yuji 'Tomita' Tomita
  • 115,817
  • 29
  • 282
  • 245
  • Is there a way to modify (reuse) the view without redefining it in my own code? I still want to pick up changes to the django-basic-blog app later on, and don't want to have to merge those changes every time I do. – pancakes Feb 27 '11 at 05:37
  • Understood. Updating post with 2 solutions – Yuji 'Tomita' Tomita Feb 27 '11 at 05:41
0

You can make

{{ post.extendedpost.translated_title }}

work if you use multi-table inheritance rather than a proxy model.

However, introducing a whole new table just to add a function doesn't make a whole lot of sense.

pancakes
  • 741
  • 1
  • 7
  • 15
0

This issue is too old but I found a solution that works for me and I will share it

you can just create a decorator like this:

def connect_proxy_to_model(property_name=None, return_copy=False):
    def get_proxy_func(proxy_class, self):
        if return_copy:
            proxy_obj = copy.deepcopy(self)
        else:
            proxy_obj = self
        proxy_obj.__class__ = proxy_class
        return proxy_obj

    def connect(proxy_class):
        name = property_name if property_name else proxy_class.__name__.lower()
        setattr(proxy_class.__base__, name, property(lambda self: get_proxy_func(proxy_class, self)))

    def wrapper(proxy_class):
        connect(proxy_class)
        return proxy_class

    return wrapper

And then you can decorate your proxy model with this:

from django.basic.blog.models import Post
from l10n.utils import lookup_translation


@connect_proxy_to_model(property_name='extendedpost', return_copy=True)
class ExtendedPost(Post):
    class Meta:
        proxy = True

    def translated_title(self, language_code=None):
        return lookup_translation(self, 'title', language_code)

Now you can use it just doing

{{ post.extendedpost.translated_title }}

The return_copy option that helps you if you want overwrite the current object ty

Amir Mohsen
  • 853
  • 2
  • 9
  • 23