如何覆盖Django模型字段中的这个方法

0 投票
2 回答
1194 浏览
提问于 2025-04-16 08:23

我正在尝试修改一个现有的Django Mezzanine设置,以便让我可以用Markdown写博客。Mezzanine有一个“核心”模型,其中的内容是用HtmlField来定义的,具体如下:

 from django.db.models import TextField


 class HtmlField(TextField):
     """
     TextField that stores HTML.
     """

     def formfield(self, **kwargs):
         """
         Apply the class to the widget that will render the field as a
         TincyMCE Editor.
         """
         formfield = super(HtmlField, self).formfield(**kwargs)
         formfield.widget.attrs["class"] = "mceEditor"
         return formfield

问题出在mceEditor的widget.attrs["class"]上。我想的办法是对Blog对象的Content字段进行修改。

class BlogPost(Displayable, Ownable, Content):
    def __init__(self, *args, **kwargs):
        super(BlogPost, self).__init__(*args, **kwargs)
        self._meta.get_field('content').formfield = XXX

我的问题是,我的Python技能还不足以用一个lambda函数来替换一个绑定的方法,并且这个lambda函数需要调用super

formfield是在管理后台需要创建一个字段以便在管理页面上显示时被调用的,所以我需要对它进行修改,以确保BlogPost的widget对象没有mceEditor这个类(我想在其他所有地方保留mceEditor)。

那么,如何编写这个替换函数呢?我很确定我可以用

setattr(self._meta.get_field('content'), 'formfield', method_i_dont_know_how_to_write)

2 个回答

1

我知道这个问题几个月前就有人回答过了,但为了防止其他人遇到同样的问题,Mezzanine现在提供了完全修改所见即所得(WYSIWYG)编辑器字段的功能。你可以在这里查看相关文档:

http://mezzanine.jupo.org/docs/admin-customization.html#wysiwyg-editor

1

你可以在管理员的方法 formfield_for_dbfield 中更改使用的表单字段:

class BlogAdmin(admin.ModelAdmin):

    def formfield_for_dbfield(self, db_field, **kwargs):
        field = super(BlogAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        if db_field.name == 'content':
            field.widget = ....
            field.widget.attrs['class'] = ...
        return field

如果你真的想进行猴子补丁(也就是修改现有代码),可以这样做:

class BlogPost(Displayable, Ownable, Content):
    def __init__(self, *args, **kwargs):
        super(BlogPost, self).__init__(*args, **kwargs)
        def formfield_new(self, *args, **kwargs):
            # do here what you would like to do
            return formfield
        instancemethod = type(self._meta.get_field('content').formfield)
        self._meta.get_field('content').formfield = instancemethod(formfield_new,
                                                                   self, BlogPost)

撰写回答