Django多站点配置不同默认语言的实现方案问询
Django多站点动态配置默认语言解决方案
嘿,我之前刚好做过类似的多站点Django项目,要实现每个站点独立设置默认语言且能随时修改,完全不需要动settings.py,下面是一套经过验证的方案:
1. 创建存储站点语言配置的数据库模型
首先我们需要把每个站点的语言配置存在数据库里,这里假设你已经启用了django.contrib.sites(如果是自定义站点模型,替换成你的模型即可):
# your_app/models.py from django.db import models from django.contrib.sites.models import Site from django.utils.translation import gettext_lazy as _ from django.conf import settings # 用Django内置的语言选项作为可选值,避免输入错误 LANGUAGE_CHOICES = settings.LANGUAGES class SiteLanguageConfig(models.Model): site = models.OneToOneField(Site, on_delete=models.CASCADE, related_name='language_config') default_language = models.CharField( _('默认语言'), max_length=10, choices=LANGUAGE_CHOICES, default=settings.LANGUAGE_CODE ) class Meta: verbose_name = _('站点语言配置') verbose_name_plural = _('站点语言配置') def __str__(self): return f"{self.site.name} - {self.default_language}"
写完模型别忘了执行数据库迁移:
python manage.py makemigrations python manage.py migrate
2. 自定义中间件处理动态语言切换
Django的语言设置是通过中间件处理的,我们需要写一个自定义中间件,在请求到达时根据当前站点的配置激活对应的语言:
# your_app/middleware.py from django.utils.deprecation import MiddlewareMixin from django.utils.translation import activate from django.contrib.sites.models import Site from .models import SiteLanguageConfig class DynamicSiteLanguageMiddleware(MiddlewareMixin): def process_request(self, request): # 获取当前请求对应的站点(如果是自定义站点识别逻辑,替换这里) current_site = Site.objects.get_current(request) try: # 从数据库获取该站点的默认语言 site_lang = current_site.language_config.default_language except SiteLanguageConfig.DoesNotExist: # 如果没有配置,用settings里的默认值做降级 site_lang = settings.LANGUAGE_CODE # 激活语言环境 activate(site_lang) # 把语言设置到request对象,方便后续视图/模板使用 request.LANGUAGE_CODE = site_lang
然后把这个中间件加到settings.py的MIDDLEWARE列表里,注意要放在LocaleMiddleware之前,确保我们的动态设置优先生效:
# settings.py MIDDLEWARE = [ # ... 其他中间件 'your_app.middleware.DynamicSiteLanguageMiddleware', 'django.middleware.locale.LocaleMiddleware', # ... 其他中间件 ]
3. 在自定义管理应用中添加配置界面
因为你用的是自定义管理应用,只需要给SiteLanguageConfig做一个表单和视图,让管理员可以修改:
第一步:写配置表单
# your_app/forms.py from django import forms from .models import SiteLanguageConfig class SiteLanguageConfigForm(forms.ModelForm): class Meta: model = SiteLanguageConfig fields = ['default_language']
第二步:写管理视图
# your_app/views.py from django.shortcuts import get_object_or_404, render, redirect from django.contrib.auth.decorators import user_passes_test from django.contrib.sites.models import Site from .models import SiteLanguageConfig from .forms import SiteLanguageConfigForm # 替换成你的管理员权限判断逻辑 def is_admin(user): return user.is_authenticated and user.is_staff @user_passes_test(is_admin) def site_language_settings(request, site_id): site = get_object_or_404(Site, id=site_id) # 获取或创建该站点的配置(避免首次访问报错) config, created = SiteLanguageConfig.objects.get_or_create(site=site) if request.method == 'POST': form = SiteLanguageConfigForm(request.POST, instance=config) if form.is_valid(): form.save() return redirect('site_language_settings', site_id=site_id) else: form = SiteLanguageConfigForm(instance=config) return render(request, 'your_app/site_language_settings.html', { 'site': site, 'form': form })
第三步:简单的配置模板
<!-- your_app/templates/your_app/site_language_settings.html --> <h1>{{ site.name }} 站点语言设置</h1> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">保存设置</button> </form>
4. 额外注意事项
- 实时生效:修改配置后不需要重启Django服务,下次请求进来就会自动加载新的语言设置
- 降级处理:中间件里做了容错,如果站点没有配置语言,会自动用
settings.py里的LANGUAGE_CODE - 翻译文件:确保你已经为需要的语言准备好了对应的
.po/.mo翻译文件,Django的翻译机制才能正常工作 - 自定义站点识别:如果你没有用
django.contrib.sites,而是自己通过域名/请求参数识别站点,只需要修改中间件里获取current_site的逻辑即可
内容的提问来源于stack exchange,提问作者Nazkter
相关产品推荐
相关产品推荐

