Search code examples
djangodjango-modelsdjango-viewsdjango-translated-fields

Multilingual slug with django-translated-fields


I am trying to implement a multilingual Django website with help of django-translated-fields.

The project I am working on is based on cookiecutter-django and Docker.

The translation works fine for my model fields – except the slug filed. Actually translation of slug works as well but I am not able to take slug field for getting one single entry.

Excerpt of voting model:

class Voting(models.Model):
    slug =  TranslatedField(
        models.SlugField(
            max_length=80,
            unique=True,
            verbose_name="Voting URL slug",
            blank=True
        ),
        {
            "de": {"blank": True},
            "fr": {"blank": True},
            "it": {"blank": True},
            "rm": {"blank": True},
            "en": {"blank": True},
        },
    )

Full voting model of project can be seen here.

Excerpt of view:

def voting(request, slug):
    voting = get_object_or_404(Voting, slug=slug)
    context = {
        'voting': voting
    }
    return render(request, 'votes/single.html', context)

Full view can be seen here

Since Django translated fields creates slug_en, slug_de and so on I cannot find a solution for getting the slug in corresponding language.

It should be obvious since documentation of Django-translated fields says:

No model field is actually created. The TranslatedField instance is a descriptor which by default acts as a property for the current language's field.

Unfortunately, don’t get it anyway. Any idea how I can change voting model for getting the entry in the specific language?


Solution

  • from translated_fields import to_attribute
    
    def voting(request, slug):
        voting = get_object_or_404(Voting, **{to_attribute(name='slug'): slug})
        context = {
            'voting': voting
        }
        return render(request, 'votes/single.html', context)
    

    If necessary, you can add language_code=request.LANGUAGE_CODE to the call to to_attribute, but usually this is not necessary:

        voting = get_object_or_404(Voting, **{to_attribute(name='slug', language_code=request.LANGUAGE_CODE): slug})