You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中在views.py外部无法检测当前语言的问题解决求助

解决方案:动态在表单实例化时生成翻译后的国家选项

你的问题核心在于模块级别的代码在Django启动阶段就执行了,比如countries_handler.py里的arr_country = get_country(),这时候还没有任何请求,get_language()只能拿到默认的en,自然无法加载对应语言的翻译文件。我们需要把国家选项的生成逻辑移到请求处理阶段,也就是表单实例化的时候,这样才能获取当前请求的语言。

步骤1:重构countries_handler.py,让它支持传入语言参数

把原来模块级别的语言获取逻辑改成可传入参数的函数,这样调用者可以主动传入当前请求的语言:

from django.utils.translation import gettext_lazy as _
import importlib
import json

def readJson(filename):
    with open(filename, 'r', encoding="utf8") as fp:
        return json.load(fp)

# 修改为接受language参数的函数,不再依赖模块加载时的语言
def get_country(language):
    filepath = 'myproj/static/data/countries_states_cities.json'
    all_data = readJson(filepath)
    all_countries = [('----', _("--- Select a Country ---"))]
    
    # 根据传入的语言导入对应的翻译文件
    imp = importlib.import_module(f"countries.translations.countries_{language}")
    
    for x in all_data:
        y = (x['name'], imp.t_countries(x['name']))
        all_countries.append(y)
    return all_countries

删除原来模块末尾的arr_country = get_country(),因为我们不再需要提前生成这个列表。

步骤2:修改forms.py,在表单初始化时动态生成选项

在表单的__init__方法中,获取当前请求的语言,然后调用重构后的get_country()生成翻译后的选项。注意要把request传递给表单,这样能拿到最准确的当前语言(LocaleMiddleware会把语言存在request.LANGUAGE_CODE中):

from django import forms
from .models import Address
from django.utils.translation import gettext_lazy as _, get_language
from .countries_handler import get_country

class AddressForm(forms.ModelForm):
    # 先设置一个默认的空选项,后面会动态覆盖
    country = forms.ChoiceField(
        choices = [('----', _("--- Select a Country ---"))],
        required = False,
        label=_('Company Country Location'),
        widget=forms.Select(attrs={'class':'form-control', 'id': 'id_country'}),
    )

    def __init__(self, *args, **kwargs):
        # 从参数中取出request(如果有的话),不要传给父类
        self.request = kwargs.pop('request', None)
        # 先调用父类的初始化方法
        super().__init__(*args, **kwargs)
        
        # 获取当前语言:优先用request里的LANGUAGE_CODE,备用get_language()
        current_lang = self.request.LANGUAGE_CODE if self.request else get_language()
        # 动态生成翻译后的国家选项并更新字段
        self.fields['country'].choices = get_country(current_lang)

    def get_state_by_country(self, country):
        return return_state_by_country(country)
    def get_city_by_state(self, state):
        return return_city_by_state(state)

    class Meta:
        model = Address
        fields = ['country']

步骤3:修改视图,将request传递给表单

在创建表单实例时,把当前请求对象传进去,这样表单才能拿到正确的语言信息:

from django.shortcuts import render
from .forms import AddressForm
from django.utils.translation import get_language

def load_form(request):
    # 把request作为参数传给表单
    form = AddressForm(request=request)
    return render(request, 'countries/country_form.html', {'form':form, 'lang':get_language()})

为什么之前的方案无效?

你之前尝试在视图里传递arr_country给表单,但问题在于:

  • 如果你还是在模块级别生成arr_country,它依然是启动时的默认语言版本,不会随请求变化;
  • 表单的字段定义应该在类级别,或者在__init__里正确修改字段属性,你之前的__init__写法没有正确覆盖字段的choices,反而可能破坏了表单的正常初始化流程。

验证一下

现在切换URL语言(比如/fr/countries/),表单会在每个请求到来时:

  1. 获取当前请求的语言(fr);
  2. 加载对应的countries_fr.py翻译文件;
  3. 动态生成法语的国家选项列表;
  4. 渲染到页面上。

这样就能实现语言切换时国家列表自动对应翻译的效果了。

内容的提问来源于stack exchange,提问作者ionecum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 12:09:07