在Django模型中为管理站点返回HTML代码

0 投票
1 回答
1985 浏览
提问于 2025-04-17 21:57

我刚开始学习Django,想用下面的代码来显示自从某个东西提交到我的网站以来已经过去了多少时间,但我遇到了一个KeyError错误,可能是因为返回的HTML代码片段不正确。有没有什么建议?

错误信息:

异常类型:KeyError

异常值:u'<span>39 minutes ago.</span>'

这是我的代码:

class Poll(models.Model):
    question = models.CharField(max_length=140)
    description = models.TextField() #if too many words make it collapsible? must i define a method for this or use css?
    likes = models.IntegerField()

    pub_date = models.DateTimeField('date published', auto_now_add=True)
    #
    #def save(self, *args, **kwargs):
    #    #to make pub_date editable for testing purposes?
    #    if not self.id:
    #        self.pub_date = datetime.datetime.today()
    #    self.modified = datetime.datetime.today()
    #    return super(User, self).save(*args, **kwargs)
    #
    #
    def time_since_published(self):
        #return seconds only, minutes only, or days ago like reddit!
        timedelta = timezone.now() - self.pub_date
        if timedelta.seconds < 10:
            s = 'Just Now'
        else:
            mins = timedelta.seconds / 60
            secs = timedelta.seconds % 60
            hours = mins / 60
            mins = mins % 60
            days = hours / 24
            hours = hours % 24
            if not mins and not hours and secs:
                s = '%s seconds ago.' % secs
            elif mins and not hours:
                s = '%s minutes ago.' % mins
            elif mins and hours:
                s = '%s hours ago.' % hours
            elif days:
                s = '%s days ago.' % days

        return format_html(u'<span>{0}</span>',s)

    time_since_published.admin_order_field = 'pub_date'
    time_since_published.boolean = True #this is for some pretty icon to appear instead of true or false lol
    time_since_published.short_description = 'Time Since'
    time_since_published.allow_tags = True

    default_tags_choices = (
        ('none', ''),
        ('nsfw', '[NSFW]'),
        ('serious', '[Serious]')
    )
    default_tags = models.CharField(max_length=15, choices=default_tags_choices, default='None')

编辑:

添加了错误页面

Error during template rendering

In template C:\Python27\lib\site-packages\django\contrib\admin\templates\admin\change_list.html, error at line 91
1 hours ago.
81          {% endif %}
82        {% endblock %}
83  
84        <form id="changelist-form" action="" method="post"{% if cl.formset.is_multipart %} enctype="multipart/form-data"{% endif %}>{% csrf_token %}
85        {% if cl.formset %}
86          <div>{{ cl.formset.management_form }}</div>
87        {% endif %}
88  
89        {% block result_list %}
90            {% if action_form and actions_on_top and cl.full_result_count %}{% admin_actions %}{% endif %}
91            {% result_list cl %}
92            {% if action_form and actions_on_bottom and cl.full_result_count %}{% admin_actions %}{% endif %}
93        {% endblock %}
94        {% block pagination %}{% pagination cl %}{% endblock %}
95        </form>
96      </div>
97    </div>
98  {% endblock %}
99  

1 个回答

3

根据Django的文档

如果你给出的字符串是模型、ModelAdmin的方法,或者是一个可调用的对象,Django默认会对输出进行HTML转义。也就是说,它会把一些特殊字符转换成安全的格式。如果你不想让这个方法的输出被转义,可以给这个方法加一个allow_tags属性,并把它的值设为True

所以,你可以在代码中加上这个:

time_since_published.allow_tags = True

另外,因为你不是在拼接HTML片段,而是有一个固定的HTML字符串,所以你不需要使用mark_safe()。可以试试这样:

return format_html(u'<span>{0}</span>', s)

想了解更多信息,可以查看Django文档中关于format_html()的第二个例子

最后,你应该尝试整理一下你的编码风格。现在的代码有点难读。像这样的行:

mins=timedelta.seconds/60
s= '%s hours ago.'%hours

应该改写成这样:

mins = timedelta.seconds / 60
s = '%s hours ago.' % hours

撰写回答