Django允许覆盖verbose_name
的{{1}}和verbose_name_plural
,这允许我们为非英语语言指定正确的复数形式的Model
名称(例如{{} 1}}作为Model
的复数而不是默认的Kandydaci
,在波兰语中看起来很奇怪。)
然而,对于具有语法案例的语言来说,这远远不够。例如,Django Admin兴高采烈地向我们展示了类似的内容:
(其中Kandydat
代表Kandydats
- Zaznacz kandydat do zmiany
是Select kandydat to change
的名称
这是不正确的。在这句话中,模型名称应该显示在accusative case中,即Kandydat
。但是,我不能简单地指定此Model
的{{1}}为kandydata
,因为这也会影响所有预期nominative case的地方 - 我找到了一个这样的地方所以远,这是表格列的标题:
这是不可理解的,因为表格标题应该被称为verbose_name
而不是Model
。
如何解决这个问题?
答案 0 :(得分:2)
The string 'Select <verbose_name> to change'
is declared inside the admin's main view
self.title = title % force_text(self.opts.verbose_name)
as a {{ title }}
template variable
{% block content_title %}{% if title %}<h1>{{ title }}</h1>{% endif %}{% endblock %}
So, touching the built-in view is out of question. But there is another way of doing it! You see, Django Admin templates are full of {% block %}
s acting as placeholders in order to override them. Read more at the official docs about overriding Admin templates.
So, to your question.
templates
(if it doesn't exists already).my_project/templates/
create another one, admin
.my_project/templates/admin/
create a file change_list.html
.Inside my_project/templates/admin/change_list.html
put these:
{% extends 'admin/change_list.html' %}
{% load myutils_filters %}
{% comment %}
You have to create an app that will hold all common tags/filters
that are re-usable across your entire project.
The model class itself is passed as cl.model
{% endcomment %}
{% block content_title %}{{ block.super|to_accusative:cl.model }}{% endblock %}
Inside your myutils/templatetags/myutils_filters.py
file put these:
from django import template
from django.utils.html import format_html
from django.utils.encoding import force_text
register = template.Library()
@register.filter()
def to_accusative(value, model):
verbose_name = model._meta.verbose_name # declared in Meta
new_name = force_text(model.accusative case()) # a custom class method (lives in your Model)
return format_html(value.replace(verbose_name, new_name))
Finally, under your app's models.py
, under each model class
define a classmethod
method like this:
from django.db import models
from django.utils.translation import ugettext_lazy as _
class MyModel(models.Model):
# model fields here
def __str__():
return self.a_field
class Meta:
verbose_name = 'verbose name'
verbose_name_plural = 'verbose name plural'
# accusative_case = 'accusative name case' # BAD. Raises error. Implement a class method intead ;)
@classmethod
def accusative_case(cls):
# You'll define the Polish translation as soon as you run makemessages
return _('Name in english of the accusative case')
Run manage.py makemessages
, manage.py compilemessages
, reload your browser and voila!
Note: The above may look a little hackish but it works brilliant. Tested locally and works.