django-modeltranslation
django-modeltranslation copied to clipboard
Translated model SelectField not sorted in the correct language
Hi, I have a Select with objects that are countries, so model is called Country with a "name" and "code" attributes. Names are perfectly translated but their order in a select box rendered from a model form, sorted alphabetically in english (default language), whatever I select in languages (except english of course)...
Code from models.py :
class Country(models.Model):
code = models.CharField(max_length=4, unique=True)
name = models.CharField(max_length=255)
def __str__(self):
return (self.name)
class Meta:
ordering = ['name']
Code from translations.py
class CountryTranslationOptions(TranslationOptions):
fields = ('name',)
translator.register(Country, CountryTranslationOptions)
Code from forms.py
class CountriesSelectForm(forms.Form):
country = forms.ModelChoiceField(queryset=Country.objects.all().order_by("name"),
widget=forms.Select(),
label=_('Country'),
required=False)
)
Hi @EParisot, did you find a solution to this issue?
Nop, we decided it was not vital but the problem is still there...
@antoiloui in fact I just came accross it today, and fixed it by sorting the select options on the client side. See following js code (usage: sortSelect(document.getElementById("select_id"));)
function sortSelect(selElem) {
var selected = selElem.options[selElem.selectedIndex].value;
var tmpAry = new Array();
for (var i=0;i<selElem.options.length;i++) {
tmpAry[i] = new Array();
tmpAry[i][0] = selElem.options[i].text;
tmpAry[i][1] = selElem.options[i].value;
}
tmpAry.sort();
if (selElem.options.length > 0) {
selElem.options[0] = null;
}
for (var i=0;i<tmpAry.length;i++) {
var op = new Option(tmpAry[i][0], tmpAry[i][1]);
selElem.options[i] = op;
if (tmpAry[i][1] == selected) {
selElem.selectedIndex = i;
}
}
return;
}
Amazing, thanks for sharing your solution @EParisot!
For future reference, one way to do this server-side is to Coalesce
the translated fields together. Here is a gist showcasing this approach:
https://gist.github.com/LeMinaw/cdc9c92113f5d5a0af067c5846e90f32
@LeMinaw thank you for showing how it can be done.
Does it mean that using order_by()
with a translated field is not supported by django-modeltranslation
if not all your DB entries have a translation for the field?
For example all the entries have a value for english (default language), but not all have a french translation. Is it possible to get a correct ordering for french, i.e. the ordering is based on french and if not available, it defaults to english?
If I understood correctly, this is what your code achieves, but I'm confused as why it wouldn't be the default behaviour.
Yes, what you describe is roughly what the above code does.
To me modeltranslation not ordering querysets this way by default sound reasonable: ordering and querysets annotations have a performance cost, and it is clearly stated in the docs that the status of original translated fields is unspecified.
Now one can discuss if the library should provide a way to perform this kind of ordering through the translated model manager.