Django Dynamic Pages with translations Django.How

Author avatar wrote on 26/05/2022

1.Create a new app

python manage.py startapp pages

2.Add this app to INSTALLED_APPS list in your main settings.py file


INSTALLED_APPS = [
    ...
    'pages.apps.PagesConfig',
    ...
    ]


3.Add to main url.py file of your project


urlpatterns = i18n_patterns(
    ...    
    path('', include('pages.urls')),
)

Better to add this to the end of urlpatterns, in this case django will use it if could not find views in other apps

4.Add urls.py file to this app


from django.urls import path

from . import views

urlpatterns = [
    path('', views.dashboard, name='dashboard'),
    path('/', views.page, name='page'),
]

You can add some static pages to this app as usually

5.Add to models.py:


from django.db import models
        
class PagesContent(models.Model):
    lang_choices = [
        ('en', 'English'),
        ('fr', 'Français'),
        ('es', 'Español'),
        ('dt', 'Deutsch'),
        ('it', 'Italiano'),
        ('ru', 'Русский'),
        ('ua', 'Українська'),
    ]
    page_name = models.CharField(max_length=200)
    lang = models.CharField(
        max_length=2,
        choices=lang_choices,
        default='en',)
    slug = models.CharField(max_length=200)
    page_title = models.CharField(max_length=200, null=True)
    page_description = models.CharField(max_length=300, null=True)
    page_keywords = models.CharField(max_length=200, null=True)
    custom_styles = models.TextField(blank=True, null=True)
    custom_scripts = models.TextField(blank=True, null=True)
    content = models.TextField()

    # Change Name in Admin Panel
    class Meta: 
        verbose_name = "Page Content"
        verbose_name_plural = "Pages Contents"

    def __str__(self):
        return self.page_name

And run migrations commands

python manage.py makemigrations pages

python manage.py migrate pages

6.Add to views.py


from django.shortcuts import get_object_or_404, render

from django.utils import translation
from .models import PagesContent

  '''
    some static views if you have
  '''

def page(request, slug):
    path = request.path
    lang = translation.get_language_from_path(path)

    if request.session.get('lang'):
        lang = request.session['lang']
    else: 
        lang = 'en'

    if slug:
        check_page = PagesContent.objects.filter(slug = slug, lang = lang).count()
        if check_page > 1:
            page = PagesContent.objects.filter(slug = slug, lang = lang).first()
        elif check_page > 0:
            page = PagesContent.objects.get(slug = slug, lang = lang)
        else:
            page = get_object_or_404(PagesContent, slug = slug, lang = 'en')
    
    context = {
        'page': page
    }

    return render(request,'pages/page.html', context)

7.Create middleware.py file in this project folder
add to this file this code:


import time
from django.http import HttpResponse, HttpResponseRedirect, HttpResponsePermanentRedirect
from django.utils import translation
from django.conf import settings

from django.shortcuts import render, get_object_or_404, redirect
from django.urls import resolve, reverse

class BrowserLang():
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if not request.session.get('lang'):
            self.get_browser_language(request)
        return self.get_response(request)

    def is_supported_language(self,language_code):
        supported_languages = dict(settings.LANGUAGES).keys()
        return language_code in supported_languages

    def get_browser_language(self, request):
        path = request.path
        url_parts = resolve(path)
        path_lang = translation.get_language_from_path(path)

        coockie_lang = request.COOKIES.get('user_lang') 

        if coockie_lang != None:
            request.session['lang'] = coockie_lang
            translation.activate(coockie_lang)
        else:
            if self.is_supported_language(path_lang):
                if hasattr(request, 'session'):
                    request.session['lang'] = path_lang                
                    translation.activate(path_lang)
            else:
                browser_language_code = request.META.get('HTTP_ACCEPT_LANGUAGE', None)
                
                if browser_language_code is not None:
                    languages = [language for language in browser_language_code.split(';') if
                                '=' not in language]
                    for language in languages:
                        language_code = language.split('-')[0]
                        if self.is_supported_language(language_code):
                            if hasattr(request, 'session'):
                                request.session['lang'] = language_code

                            translation.activate(language_code)   

                    if not  request.session.get('lang'): 
                        translation.activate('en') 
                        if hasattr(request, 'session'):
                            request.session['lang'] = 'en'

        settings.LOGIN_URL = reverse('login')
        settings.LOGIN_REDIRECT_URL = reverse(url_parts.view_name, kwargs=url_parts.kwargs)

        url = reverse(url_parts.view_name, kwargs=url_parts.kwargs)       
        request.path_info = url
        return request

it will check users default language from browser and saving it to session, if your project don’t have this language in project setting it will set English language by default

8.Register this middleware in settings.py file


MIDDLEWARE = [
    ....
    'django.middleware.locale.LocaleMiddleware',    
    'pages.middleware.BrowserLang',
    ....    
]

9.Add to admins.py file


from django.contrib import admin
from .models import Content, PagesContent
from django_summernote.admin import SummernoteModelAdmin

class PagesContentAdmin(SummernoteModelAdmin):
    summernote_fields = ('content','custom_styles','custom_scripts')
    list_display = ("page_name", "lang", "slug", "page_title","page_description", "page_keywords")
    list_display_links = ('page_name',)
    search_fields = ("page_name", "lang", "slug", "page_title","page_description", "page_keywords")
    list_per_page = 20

    # Remove Delete Seleted
    def get_actions(self, request):
        actions = super().get_actions(request)
        if 'delete_selected' in actions:
            del actions['delete_selected']
        return actions

    # Disallow Delete
    def has_delete_permission(self, request, obj=None):
        return False

    # Make Name Read Only
    #readonly_fields = ["page_name"]


admin.site.register(PagesContent, PagesContentAdmin)

Important: This example using django_summernote package!!! You need to install it using this guide https://github.com/summernote/django-summernote - Connect to preview

Now its done.