Django模板中的自定义模型字段呈现

时间:2014-10-26 02:53:51

标签: django model custom-fields

我已经使用自定义模型字段扩展了django-markdown,允许用户定义类:

from django.db import models
from django_markdown.fields import MarkdownField

class MyModel(models.Model):
    text = MarkdownField()

class MySecondModel(models.Model):
    description = MarkdownField()

现在,在模板中渲染这些字段时,可以这样做:

{% load markdown_tags %}
{{ model.text|markdown }} {{ model2.description|markdown }}

然而,这似乎首先打败了创建自定义模型字段的目标(以增强干燥度),并且最好不惜一切代价避免。

那么,有没有办法在不加载模板标记的情况下只执行{{ model.text }} {{ model2.description }}而不通过某种方式在自定义字段上定义render方法进行过滤?

已经提出类似的问题:Is there a way to customize how the value for a custom Model Field is displayed in a template?,但答案需要在模型中添加方法。这意味着要向MyModelMySecondModel添加方法,以及任何后续方法。这再一次击败了DRY的整个对象!

NB 两个模型类都是其他类的子类,所以定义一个mixin是可行的,但肯定有一个更好的方法!

1 个答案:

答案 0 :(得分:1)

我和你一样。我想我可以使用mixin来解决它到Model类。

它似乎按预期工作,但我不确定这是否是正确的方法。感觉就像我不完全理解的肮脏黑客。

您当然应该使用更有用的方法替换方法_shout()。

from django.utils.safestring import mark_safe
from django.db import models


class LoudModelMixin(object):

    """ adds the 'html' property to a Model
    Lets regular django models be louder!

    Regular field:
    >>> blogpost.title
    'hello world'

    Same field, but louder.
    >>> blogpost.html.title
    '<strong>HELLO WORLD!</strong>'
    """

    @property
    def html(self):
        return self._HTML(self)

    class _HTML(object):

        def __init__(self, parent):
            self.parent = parent

        def __getattr__(self, attr, *args):
            raw_text = getattr(self.parent, attr, *args)
            assert isinstance(raw_text, str), 'only words can be loud.'
            return mark_safe(self._shout(raw_text))

        def _shout(self, raw, tag='strong'):
            """ Do something useful with the text here. """
            return '<{tag}>{text}!</{tag}>'.format(
                tag=tag, text=raw.upper()
            )


class Blogpost(models.Model, LoudModelMixin):
    title = models.CharField(max_length=50)
    body = models.TextField()