0

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?

Udi
  • 29,222
  • 9
  • 96
  • 129
Philipp
  • 794
  • 1
  • 7
  • 21

2 Answers2

1
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})
Uri
  • 2,992
  • 8
  • 43
  • 86
0

Not sure if this is the right way but with help of Django Documentation “How Django discovers language preference” I came to following solution.

Changing the voting view as follows:

def voting(request, slug):
    '''Takes slug of single voting and returns that voting object in
    corresponding language.
    '''
    if request.LANGUAGE_CODE == 'de':
        voting = get_object_or_404(Voting, slug_de=slug)
    elif request.LANGUAGE_CODE == 'fr':
        voting = get_object_or_404(Voting, slug_fr=slug)
    elif request.LANGUAGE_CODE == 'it':
        voting = get_object_or_404(Voting, slug_it=slug)
    elif request.LANGUAGE_CODE == 'rm':
        voting = get_object_or_404(Voting, slug_rm=slug)
    elif request.LANGUAGE_CODE == 'en':
        voting = get_object_or_404(Voting, slug_en=slug)
    context = {
        'voting': voting
    }
    return render(request, 'votes/single.html', context)
Philipp
  • 794
  • 1
  • 7
  • 21
  • You can use `to_attribute` with `*` to use the `LANGUAGE_CODE` in one line. In this case you don't have to define it 5 times like you did. – Uri Jan 26 '20 at 09:26
  • Something like `get_object_or_404(Voting, **{to_attribute(name='slug'): slug})` – Uri Jan 26 '20 at 09:28
  • If necessary, you can add `language_code=request.LANGUAGE_CODE` to the call to `to_attribute`. – Uri Jan 26 '20 at 09:37