静态网页
Django应用是动态网站,如果网站的流量过大,每次访问时都会进行动态生成,执行各种SQL语句,就会消耗大量服务器资源,可以考虑生成静态网页。
def index(request):
# cache = caches['memcached']
# key = cache.get_or_set('key_word', 'kyyyyy')
context = {'name':'Hello'}
static_html = f'{BASE_DIR}/learning_logs/templates/static_index.html'
if not os.path.exists(static_html):
content = render_to_string('index.html', context)
with open(static_html, 'w') as static_file:
static_file.write(content)
return render(request, static_html)
当没有找到现有的静态网页时就会手动生成,静态网页已经存在时,就不用生成,直接返回这个静态网页。
国际化和本地化
国际化和本地化的目标是让单个Web应用程序针对不同的地区和语言用户提供不同的内容。Django完全支持文本翻译,日期、时间和数字格式以及时区。本质上讲,Django做了两件事:1. 它允许开发者指定要翻译的字符串;2.Django根据特定的访问者的偏好设置 进行调用相应的翻译文本。文本翻译取决于用户所用的语言,格式取决于所在的国家。这些信息可以由HTTP的请求首部字段Accept-Language
决定。但是,时区信息不太容易获得。
所谓的国际化就是指开发人员准备本地化的软件,而本地化就是指翻译人员将内容翻译和进行本地格式化。
在settings中设置
MIDDLEWARE = [
# ...
'django.middleware.locale.LocaleMiddleware',
]
# 翻译文件所在目录
LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale'),
)
LANGUAGES = (
('en', ('English')),
('zh-hans', ('中文简体')),
('zh-hant', ('中文繁體')),
)
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = True
在MIDDLEWARE
必须添加django.middleware.locale.LocaleMiddleware
这项
USE_I18N
:代表Internationalization(国际化),默认为True,启用Django的翻译系统。如果将其设置为False,Django将进行一些优化,以免加载翻译机制;USE_L10N
:代表Location(本地化),默认为True,数字和日期的格式都会按照当地的来;USE_TZ
:默认为False,为True时Django会用当地的时区设置显示的时间;TIME_ZONE
:指定所处的时区;LANGUAGE_CODE
:默认是'en-us'
英语,指定使用的语言,在USE_I18N
设定为True时才有效;LANGUAGES
:所有可用语言的列表,格式:(language code, language name) ,参照django/conf/global_settings.py。
在Python代码中指出要翻译的文本
可以通过gettext
函数,指定某个变量需要翻译,还可以为这个函数使用别名
from django.utils.translation import gettext
# from django.utils.translation import gettext as _
def index(request):
# output = _('Weicome to my site')
output = gettext('Weicome to my site')
context = {'name':output}
return render(request, 'index.html', context)
同时,还支持变量或者python 的named-string格式:
words = ['Welcome', 'to', 'my', 'site.']
output = _(' '.join(words))
# 或
output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d}
Translators
注释关键字
如果要为待翻译的文本添加翻译相关的暗示,可以添加用Translators开头的注释:
# Translators: This message appears on the home page only
output = gettext('Weicome to my site')
然后,注释将出现在与其下方的可翻译构造相关联的结果文件 .po 中,并且还应由大多数翻译工具显示,在模板中也可以使用。
#. Translators: This message appears on the home page only
# path/to/python/file.py:123
msgid "Welcome to my site."
msgstr ""
在模板中标示待翻译文本
在模板文件中要标示一个待翻译的文本,可以使用2个模板标签,但要先在模板顶部加载{% load i18n %}
标签。
{% trans %}
标签可以对字符串或者变量使用
{% load i18n %}
<title>{% trans "This is the title." %}</title>
<title>{% trans myvar %}</title>
使用{% blocktrans %}
标签可以通过使用占位符来标记由文字和可变内容组成的复杂句子进行翻译:
{% blocktrans %}This string will have {{ value }} inside.{% endblocktrans %}
也可在一个{% blocktrans %}标签内部使用多个表达式:
{% comment %}Translators: View verb{% endcomment %}
{% blocktrans with book_t=book|title author_t=author|title %}
This is {{ book_t }} by {{ author_t }}
{% endblocktrans %}
之前提到过的Translators
关键字在模板中的使用。
在URL模式中标示语言
在设置URL patterns 时,可以添加前缀i18n_patterns
,Django会自动将当前活动语言代码添加到i18n_patterns()中定义的所有URL模式。
from django.conf.urls.i18n import i18n_patterns
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('learning_logs.urls', namespace='learning_logs')),
# path('users/', include('users.urls', namespace='users')),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += i18n_patterns(
path('users/', include('users.urls', namespace='users')),
)
可以看到在生成的网页中,users下的网页都有’zh-hans’的前缀了
注意i18n_patterns
只能在 root URLconf
下使用,在app下的urls中使用会报错。
本地化
首先,建立语言文件。通过django-admin makemessages
命令来完成。
在项目的根目录下,也就是包含manage.py的目录下,运行:
python manage.py makemessages -l zh_hans
python manage.py makemessages -l en
python manage.py makemessages -l zh_hant
注意
:
如果项目启用了虚拟环境,那么命令会出错,如:
xgettext: ./venv/lib/python3.6/site-packages/docutils/writers/html5_polyglot/__init__.py:1: Unknown encoding "utf8". Proceeding with ASCII instead.
在venv目录下的所有库文件都被其扫描了,但它们中很多的编码方式:# -*- coding: utf8 -*-
xgettext不会识别utf8
作为utf-8
的别名,所以要使用-i
参数忽略( ignore)venv。
(venv) ulysses@ulysses:~/PycharmProjects/django_ulysses$ python manage.py makemessages -l zh_hans -i venv
processing locale zh_hans
生成的.po文件
(venv) ulysses@ulysses:~/PycharmProjects/django_ulysses/locale$ tree
.
├── en
│ └── LC_MESSAGES
│ └── django.po
└── zh_hans
└── LC_MESSAGES
└── django.po
内容:
#: learning_logs/templates/index.html:12
#: learning_logs/templates/index.html:12
#, python-format
msgid "This string will have %(name)s inside."
msgstr "这个字符串里面有%(name)%"
#. Translators: This message appears on the home page only
#: learning_logs/views.py:22
msgid "Weicome to my site"
msgstr "欢迎来到我的网站"
- 通过注释表达该条要翻译的字符串在视图或模版中的位置,还会有包括指出python格式,翻译关键提示等信息;
- msgid:要翻译的字符串;
- msgstr:翻译后的文本。一开始它是空的,需要翻译人员逐条填写。
接着编译文件:python manage.py compilemessages
编译完之后打开网页,可以看到使用了翻译后的中文版本。
在前面的设置中,通过直接写入中文这种直接的方式实现中文的
通过国际化与本地化设置,可以实现多语言不同版本设置。
这是使用en作为url前缀的效果
添加语言切换功能
Django自带了一个 django.views.i18n.set_language 视图,作用是设置用户语言偏好并重定向返回到前一页面。
在urlpattern添加path(r'^i18n/', include('django.conf.urls.i18n')),
在导航栏添加一个语言选择表单:
{% load i18n %}
<form action="{% url 'set_language' %}" method="post">{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}">
<select name="language">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"{% if language.code == LANGUAGE_CODE %} selected{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
<input type="submit" value="Go">
</form>
效果