Django库,用于将模型和表单中的转换字符串外部化。

dj-labeler的Python项目详细描述


django模型最烦人的地方是,当你想做正确的事情时,它们的冗长。一旦你 如果有国际观众,你需要开始标记翻译字符串。创建Labeler是为了减少 通过外部化模型的标签、帮助文本和错误消息而产生的噪音。它甚至提供相同的功能 任何Django表格。

预计它将与django 1.8、1.9及更高版本一起使用。

安装

在pypi上,labeler可用作dj-labeler

pip install dj-labeler

示例

想象一下我们的bookstore模型是这样的:

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=200)
    published = models.BooleanField(default=False)
    birthdate = models.DateField(blank=True, null=True)


class Book(models.Model):
    title = models.CharField(max_length=200)
    published_on = models.DateField(blank=True, null=True)
    isbn = models.CharField(max_length=50, unique=True)
    authors = models.ManyToManyField(Author)

现在你想开拓一个讲荷兰语的市场。而不是依赖于django的自动标签创建 根据字段名,您需要显式地声明每个字段的详细名称,并将其标记为 可翻译字符串。为了避免人们对荷兰语翻译产生任何困惑,你需要 提供尽可能多的上下文,因为作者的名称可能不需要与 一个类别。

所以你最终得到了这个:

from django.db import models
from django.utils.translation import pgettext_lazy

class Author(models.Model):
    name = models.CharField(pgettext_lazy('author', 'name'), max_length=200)
    published = models.BooleanField(pgettext_lazy('author', 'published'), editable=False)
    birthdate = models.DateField(pgettext_lazy('author', 'birthdate'), blank=True, null=True)

    class Meta:
        verbose_name = pgettext_lazy('author model', 'Author')
        verbose_name_plural = pgettext_lazy('author model (plural)', 'Authors')


class Book(models.Model):
    title = models.CharField(pgettext_lazy('book', 'title'), max_length=200)
    published_on = models.DateField(pgettext_lazy('book (date)', 'published'), blank=True, null=True)
    isbn = models.CharField(pgettext_lazy('book', 'isbn'), max_length=50, unique=True)
    authors = models.ManyToManyField(Author, verbose_name=pgettext_lazy('book authors', 'authors'))

    class Meta:
        verbose_name = pgettext_lazy('author model', 'Book')
        verbose_name_plural = pgettext_lazy('author model (plural)', 'Books')

现在加上帮助文本,你会有很多噪音,使你很难辨别你作为一个程序员的属性 在开发时关心最多,比如最大长度和字段是可选的还是唯一的。

labeler将使应用程序能够使用噪音更小的可翻译字符串。让我们把字符串移到一个单独的文件中 我们将调用i18n.py(但任何名称都可以)并使用labeler的ModelTranslations

# i18n.py
from django.utils.translation import pgettext_lazy
from labeler import ModelTranslations

author = ModelTranslations(
    labels=dict(
        name=pgettext_lazy('author', 'name'),
        published=pgettext_lazy('author', 'published'),
        birthdate=pgettext_lazy('author', 'birthdate')
    )
    help_texts=dict(
        birthdate=pgettext_lazy('author', 'When was the author born?')
    ),
    name=pgettext_lazy('author model', 'Author'),
    name_plural=pgettext_lazy('author model (plural)', 'Authors')
)

book = ModelTranslations(
    labels=dict(
        title=pgettext_lazy('book', 'title'),
        published_on=pgettext_lazy('book (date)', 'published'),
        isbn=pgettext_lazy('book', 'isbn'),
        authors=pgettext_lazy('book authors', 'authors')
    ),
    help_texts=dict(
        isbn=pgettext_lazy('book', 'The ISBN will be validated against XYZ database')
    ),
    name=pgettext_lazy('author model', 'Book'),
    name_plural=pgettext_lazy('author model (plural)', 'Books')
)

这仍然是一个很大的噪音,但至少我们已经把它隔离到一个单独的文件在我们的应用程序。现在,因为 ModelTranslations只是dict的扩展,您可以开始这样做:

# models.py
from django.db import models
from . import i18n

class Author(models.Model):
    # as above

    class Meta:
        verbose_name = i18n.author['name']
        verbose_name_plural = i18n.author['name_plural']

但这并不能减少噪音。相反,您应该使用^{tt3}的injectmethod/decorator$ (或FormTranslations处理表单时)。这将使我们的模型更精简,意味着:

# models.py
from django.db import models
from . import i18n

@i18n.author.inject
class Author(models.Model):
    name = models.CharField(max_length=200)
    published = models.BooleanField(default=False)
    birthdate = models.DateField(blank=True, null=True)


@i18n.book.inject
class Book(models.Model):
    title = models.CharField(max_length=200)
    published_on = models.DateField(blank=True, null=True, unique=True)
    isbn = models.CharField(max_length=50)
    authors = models.ManyToManyField(Author)

发现与我们最初版本的区别了吗?这个版本仅仅通过装饰我们的模型就使用了可翻译的字符串。 使用我们的模型翻译'inject

用法

使用模型转换转换模型

ModelTranslations是一个简单的dict,上面添加了一些有用的方法和属性。什么都不需要, 但如果指定labelshelp_textserror_messages,则这些词典的键应该引用 对现有模型字段。

ModelTranslations keyTypeMaps toAttribute
^{tt11}$dictfield^{tt15}$
^{tt12}$dictfield^{tt17}$
^{tt13}$dictfieldUpdates ^{tt13}$
^{tt20}$strMeta^{tt15}$
^{tt22}$strMeta^{tt23}$

示例:

from django.utils.translation import ugettext_lazy as _
from labeler import ModelTranslations

article = ModelTranslations(
    # verbose_name of the model's fields
    labels=dict(
        title=_('Title'),
        body=_('Body')
    ),
    # help_text of the model's fields
    help_texts=dict(
        title=_('No clickbait titles please!')
    ),
    # update to the listed fields' error_messages
    error_messages=dict(
        title=dict(
            unique=_('Title already exists')
        )
    ),
    # verbose_name of the model
    name=_('article'),
    # verbose_name_plural of the model
    name_plural=_('articles'),
    # Handy dict of error messages for this model, not field-specific
    errors=dict(
        too_clickbaity=_('Please review the article.')
    ),
    # Handy dict for other kinds of messages
    messages=dict(
        first_publication=_('Congratulations! Your first article has been published')
    ),
    # It's just a dict; add whatever you want
    something_else='abc',
    publication_state={
        'published': _('Published'),
        'draft': _('Draft'),
        'trashed': _('Trashed')
    }
)

当一切就绪,准备就绪时,只需将其注入您的模型:

from . import i18n

@i18n.article.inject
class Article(models.Model):
    # Fields and stuff

嵌套的标签、错误消息、错误消息和帮助文本词典也可用作属性。 这意味着自定义验证可能如下所示:

def clean_fields(self, exclude=None):
    super(MyModel, self).clean_fields(exclude)
    if 'title' not in exclude and calculate_clickbait_level(self.title) > 50:
        raise ValidationError({'title': i18n.article.errors['too_clickbaity']})

如果要处理大量嵌套的dict,可以使用resolve方法:

hard_way = i18n.article.get('errors', {}).get('fieldname', {}).get('invalid', {}).get('state')
easier_way = i18n.article.resolve('errors.fieldname.invalid.state')
easier_way == hard_way

使用formtranslations翻译表单

FormTranslations的工作方式与ModelTranslations完全相同,但它也支持嵌套字典 empty_labels覆盖表单字段上的默认空标签。

FormTranslations keyTypeMaps toAttribute
^{tt11}$dictfield^{tt29}$
^{tt12}$dictfield^{tt17}$
^{tt27}$dictfield^{tt33}$
^{tt13}$dictfieldUpdates ^{tt13}$

用法:

# i18n.py
from django.utils.translation import ugettext_lazy as _
from labeler import FormTranslations

article_form = FormTranslations(
    labels=dict(
        title=_('Title'),
        body=_('Body'),
        published=_('When to publish this article'),
        author=_('Author'),
    ),
    help_texts=dict(
        title=_('Limit to 100 characters please'),
        body=_('Formatting is not supported')
    ),
    empty_labels=dict(
        author=_('Please select an author')
    ),
    error_messages=dict(
        title=dict(
            unique=_('That title has already been used. Be more original!')
        )
    )
)

# forms.py
from django import forms
from . import i18n
from .models import Article

@i18n.article_form.inject
class ArticleForm(forms.ModelForm):

    class Meta:
        model = Article
        fields = ('title', 'body', 'published', 'author')

就这些了。

更改日志

v1.0.1

  • 修复自述文件和项目信息中的代码

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
mongodb查询的Java查询代码   java使用参数动态创建原型对象的实例   java增加Spring MVC服务器上HTML5音频的连接超时   java可以是一个很好的工具。NET 2.0 Web服务是否在缺少SoapAction时处理来自客户端的调用?   java这会使StringBuilder的使用变得多余吗?   使用Java配置和Spring Security 3.2的安全方法注释   java为什么在Spring MVC中对http缓存控制的支持较差?   java如何将包转换为单位   java listView不会从底部填充   使用Eureka服务器AWS Elastic Beanstalk注册java Eureka客户端   java将嵌套对象从fxml映射到对象   使用反射获取java注释   服务器重启期间的java Quartz调度程序