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开发者_Python百科 subclass like that. How DO you do this type of thing?
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.
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)
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)
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.
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
精彩评论