Push User.language choices callable to the model

as per the comment: possible from Django 5.0 up
This commit is contained in:
Klaas van Schelven
2025-08-28 21:44:47 +02:00
parent 5cf4591166
commit d155fa2bb2
3 changed files with 35 additions and 24 deletions

View File

@@ -9,8 +9,7 @@ from django.core.exceptions import ValidationError
from django.contrib.auth import password_validation from django.contrib.auth import password_validation
from django.forms import ModelForm from django.forms import ModelForm
from django.utils.html import escape, mark_safe from django.utils.html import escape, mark_safe
from django.utils.translation import gettext_lazy as _, get_language_info from django.utils.translation import gettext_lazy as _
from django.conf import settings
TRUE_FALSE_CHOICES = ( TRUE_FALSE_CHOICES = (
@@ -133,18 +132,6 @@ class SetPasswordForm(BaseSetPasswordForm):
self.fields['new_password2'].help_text = None # "Confirm password" is descriptive enough self.fields['new_password2'].help_text = None # "Confirm password" is descriptive enough
def language_choices():
items = [("auto", _("Auto (browser preference)"))]
for code, _label in settings.LANGUAGES:
info = get_language_info(code)
label = info["name_local"] \
if info["name_local"] == info["name_translated"] \
else f"{info['name_local']} ({info['name_translated']})"
items.append((code, label))
return items
class PreferencesForm(ModelForm): class PreferencesForm(ModelForm):
# I haven't gotten a decent display for checkboxes in forms yet; the quickest hack around this is a ChoiceField # I haven't gotten a decent display for checkboxes in forms yet; the quickest hack around this is a ChoiceField
send_email_alerts = forms.ChoiceField( send_email_alerts = forms.ChoiceField(
@@ -155,12 +142,6 @@ class PreferencesForm(ModelForm):
required=True, required=True,
widget=forms.Select(), widget=forms.Select(),
) )
language = forms.ChoiceField(
label=_("Language"),
choices=language_choices,
required=True,
widget=forms.Select(),
)
class Meta: class Meta:
model = User model = User

View File

@@ -0,0 +1,19 @@
import users.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("users", "0003_user_language"),
]
operations = [
migrations.AlterField(
model_name="user",
name="language",
field=models.CharField(
choices=users.models.language_choices, default="auto", max_length=10
),
),
]

View File

@@ -3,7 +3,19 @@ import secrets
from django.db import models from django.db import models
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.conf import settings from django.conf import settings
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _, get_language_info
def language_choices():
items = [("auto", _("Auto (browser preference)"))]
for code, _label in settings.LANGUAGES:
info = get_language_info(code)
label = info["name_local"] \
if info["name_local"] == info["name_translated"] \
else f"{info['name_local']} ({info['name_translated']})"
items.append((code, label))
return items
class User(AbstractUser): class User(AbstractUser):
@@ -30,10 +42,9 @@ class User(AbstractUser):
blank=False, blank=False,
) )
language = models.CharField( language = models.CharField(
_("Language"),
max_length=10, max_length=10,
# choices intentionally not set, we don't want changes to trigger migrations; the actual choices are set in choices=language_choices,
# forms.py; in Django 5.0 and up we can instead used a callable here
# choices=...
default="auto", default="auto",
blank=False, blank=False,
) )