2

我正在将 Django CMS 与 Django Parler 一起使用,并且遇到了一个让我发疯的问题,所以如果有人能提供帮助,将不胜感激!

所以我正在创建一个简单的博客应用程序,它将 slug 作为可翻译字段。这是简化的模型:

from parler.models import TranslatableModel, TranslatedFields

class Article(TranslatableModel):
    ...
    translations = TranslatedFields(
        ...
        slug = models.SlugField(_('slug'), max_length=255, blank=True, allow_unicode=True),
        meta = {'unique_together': (('language_code', 'slug'),)}
    )

    ...

    def get_absolute_url(self):
        return reverse('blog:article_detail', kwargs={'slug': self.slug})

以下是网址:

from django.conf.urls import include, url

from .views import ArticleDetailView

urlpatterns = [
    ...
    url(r'^(?P<slug>\w[-\w]*)/$', ArticleDetailView.as_view(), name='article_detail'),
]

最后是视图:

from django.views.generic import DetailView
from parler.views import TranslatableSlugMixin

from .models import Article

class ArticleDetailView(TranslatableSlugMixin, DetailView):
    model = Article
    template_name = 'blog/_article.html'

我创建了一篇英文、法文和德文的文章,每种语言都有不同的 slug,我们称之为:

/en/blog/english-slug
/fr/blog/french-slug
/de/blog/german-slug

我可以正确导航到所有这些,但在 Django CMS 中,您在顶部有语言菜单,英语页面上的链接显示为:

/en/blog/english-slug
/fr/blog/english-slug
/de/blog/english-slug

这很好,因为这就是视图中的 TranslatableSlugMixin 处理的内容(请参见此处http://django-parler.readthedocs.io/en/latest/api/parler.views.html)。

因此,当我单击其中一个链接(比如法语链接)时,视图会正确找到正确的文章并将我重定向到正确的 url。所以点击:

/fr/blog/english-slug

正确地将我带到:

/fr/blog/french-slug

但这就是一切都出错的地方。我现在想导航回英文页面,显示为:

/en/blog/french-slug

但是,当我单击该链接时,它会导航到 404。如果我从法语 URL 导航到德语 URL,情况也是如此。但是,如果我立即从英语转到德语,它就可以工作。

抱歉,我知道这很难解释,但似乎翻译从基本/默认到其他语言的一种方式工作,但在语言之间交换或返回基本/默认时无法正常工作。

肯定 TranslatableSlugMixin 是为了让这种情况发生而设计的?!那么我在这里错过了什么吗?

任何帮助将非常感激。如有必要,很乐意提供更多信息。

谢谢

4

1 回答 1

2

好的,所以我已经想出了如何使这项工作,结果证明它是多种事物的组合...

  1. 使用默认的 Django CMS 选择器是一个错误:

    {% language_chooser "menu/language_chooser.html" %}
    

    这导致了我上面描述的 URL:

    /en/blog/english-slug
    /fr/blog/english-slug
    /de/blog/english-slug
    

    阅读 Django Parler 文档使我使用了他们的语言导航菜单:

    {% for lang_code, title in LANGUAGES %}
            {% get_language_info for lang_code as lang %}
            {% get_translated_url lang_code as tr_url %}
            {% if tr_url %}<li{% if lang_code == LANGUAGE_CODE %} class="is-selected"{% endif %}><a href="{{ tr_url }}" hreflang="{{ lang_code }}">{{ lang.name_local|capfirst }}</a></li>{% endif %}
    {% endfor %}
    

    这会导致 url 指向正确的位置:

    /en/blog/english-slug
    /fr/blog/french-slug
    /de/blog/german-slug
    
  2. 为了让 Django Parler 导航正常工作,我需要更新模型中的 get_absolute_url() 以处理不同的语言。我这样做如下:

    from django.utils.translation import get_language
    
    from parler.models import TranslatableModel, TranslatedFields
    
    class Article(TranslatableModel):
    
        ...
    
        def get_absolute_url(self):
            language = get_language()
            if self.has_translation(language):
                slug = self.safe_translation_getter('slug', language_code=language)
                return reverse('blog:article_detail', kwargs={'slug': slug})
            # no translation so fallback to all article list
            return reverse('blog:article_list')
    

呸!那真是头疼!希望这对将来的其他人有所帮助!

PS 在我的研究过程中,我遇到了这个看起来非常棒的博客应用程序:

https://github.com/nephila/djangocms-blog

它帮助我走出了这场噩梦!

更新

查看 djangocms-blog 中的 get_absolute_url() (上面的链接),他们对这个问题有更好的解决方案。他们的实现是:

from django.utils.translation import get_language

from parler.models import TranslatableModel, TranslatedFields

class Article(TranslatableModel):

    ...

    def get_absolute_url(self, lang=None):
        if not lang or lang not in self.get_available_languages():
            lang = self.get_current_language()
        if not lang or lang not in self.get_available_languages():
            lang = get_language()
        with switch_language(self, lang):
            slug = self.safe_translation_getter('slug', language_code=lang, any_language=True)
            return reverse('blog:article_detail', kwargs={'slug': slug})

谢谢 nephila,这让我免于遭受很多诅咒和挫折:)

于 2016-05-27T15:10:25.700 回答