Highlighting custom model field in django template
I extended django-markdown
with a custom model field that allows classes to be defined:
from django.db import models
from django_markdown.fields import MarkdownField
class MyModel(models.Model):
text = MarkdownField()
class MySecondModel(models.Model):
description = MarkdownField()
Now when it comes to rendering these fields in the template, you can do:
{% load markdown_tags %}
{{ model.text|markdown }} {{ model2.description|markdown }}
However, this seems to defeat the custom model field creation object first (to enhance drying) and is advisable to be avoided at all costs.
So, is there a way to do it just {{ model.text }} {{ model2.description }}
without loading template tags and without filtering by defining a method render
on a custom field?
A similar question has already been asked: Is there a way to customize how the value for a custom model field is displayed in the template? but the answer entails adding a method to the model. This would mean adding methods to MyModel
and MySecondModel
, as well as any subsequent ones. Again, this defeats the entire DRY object!
NB Both model classes are subclasses of something else, so defining a mix is โโpossible, but certainly should be better!
source to share
I am in the same situation as you. I figured I could solve it using a mixin for the Model class.
It seems to work as intended, but I'm not sure if it did it correctly. Feels like a dirty hack that I don't quite understand.
You should, of course, replace the _shout () method with something more useful.
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()
source to share