Django yra tikrai patogi žiniatinklio karkasinė sistema Python programavimo kalbai, bet kaip ir kiekviena karkasinė sistema, ši atsineša į programavimo pasaulį savų apribojimų žiniatinklio meistrui. Django turi daug gyvenimą palengvinančių savybių: autentikacijos, sesijų, švarių URL, išvaizdos šablonų, sparčiosios atmintinės valdymą, duomenų bazės programavimo interfeisą, standartinę duomenų administravimo sistemą, statiško turinio vertimų mechanizmą ir kt., tik ne mechanizmą modeliams su daugiakalbiu turiniu, ką kiekvienas meistras turi susikurti savaip.
Trumpai supažindinsiu su Django projektų (svetainių ar žiniatinklio programų) architektūra. Įprastai kiekvienas projektas turi savo kodą, išvaizdos šablonus ir mediją. Kodas susideda iš projekto nustatymų, URL valdymo taisyklių, komandinėj eilutėj vykdomo projekto valdiklio ir atskirų taikomųjų programų (application), kurios kuriamos pagal projekto reikalavimus, pavyzdžiui blogas, forumas, galerija, naujienų prenumerata, meniu sistema, reitingai ar kt. Kiekviena taikomoji programa savo ruožtu turi modelius, reliatyvių URL valdymo taisykles ir peržiūros funkcijas. Modeliai apibūdina esybes, jų savybes, standartinės administravimo sistemos nustatymus. Kiekvieną modelį atitinka atitinka viena duomenų bazės lentelė. Pavyzdžiui toliau aprašytam puslapio modeliui modeliui bus sukurta DB lentelė puslapiai_puslapis(*) su VARCHAR(200) tipo lauku pavadinimas ir TEXT tipo lauku turinys:
# puslapiai/models.py
from django.db import models
class Puslapis(models.Model):
pavadinimas=models.CharField("Pavadinimas", maxlength=200)
turinys=models.TextField("Turinys")
irasyta=models.DateTimeField("Sukūrimo data", auto_now_add=True)
class Meta:
ordering=["pavadinimas", "-irasyta"]
verbose_name="puslapis"
verbose_name_plural="puslapiai"
class Admin:
list_display=["pavadinimas", "turinys", "irasyta"]
def __str__(self):
return self.pavadinimas
Šitam modeliui bus automatiškai sukuriama sritis administravimo sistemoje. Parametras list_display nusako, kad puslapių sąraše bus rodomas pavadinimas, turinys ir sukūrimo data, ordering – kad standartiškai sąrašas bus išrūšiuotas pagal pavadinimą abėcėlės tvarka ir sukūrimo datą nuo naujausio. Daugiau apie modelių kūrimą skaityk Django dokumentacijoj.
Vienas iš paprasčiausių būdų įgyvendinti modelio daugiakalbiškumą būtų tiesiog kiekvienam daugiakalbiam laukui sukurti po grupę kopijų vertimams. Vertimai būtų neprivalomi. Laukai vertimams turėtų plėtinius su dviraidžiu kalbos kodu. Standartinės kalbos laukas neturėtų plėtinio ir būtų privalomas. Jei vertimas nerastas, rodoma standartinės kalbos lauko reikšmė. Kaip tariam, taip ir padarom:
# puslapiai/models.py
from django.db import models
from django.utils import translation
from django.utils.translation import gettext_lazy as _
class Puslapis(models.Model):
pavadinimas=models.CharField("Pavadinimas", maxlength=200)
pavadinimas_en=models.CharField("Title", maxlength=200)
pavadinimas_de=models.CharField("Titel", maxlength=200)
turinys=models.TextField("Turinys")
turinys_en=models.TextField("Content")
turinys_de=models.TextField("Inhalt")
irasyta=models.DateTimeField(_("Sukūrimo data"), auto_now_add=True)
class Meta:
ordering=["pavadinimas", "-irasyta"]
verbose_name=_("puslapis")
verbose_name_plural=_("puslapiai")
class Admin:
list_display=["pavadinimas", "turinys", "irasyta"]
def __str__(self):
return self.gauk_pavadinima()
def gauk_pavadinima(self, kalbos_kodas=None):
return getattr(self, "pavadinimas_%s" % kalbos_kodas or \
translation.get_language()[:2], "") or self.pavadinimas
def gauk_turini(self, kalbos_kodas=None):
return getattr(self, "turinys_%s" % kalbos_kodas or \
translation.get_language()[:2], "") or self.turinys
Viskas būtų kaip ir šaunu, tik va standartinėj administravimo sistemoj objektų sąraše šiuo atveju bus rodomas tik lietuviškas pavadinimas ir turinys, ir objektai bus rūšiuojami pagal lietuvišką pavadinimą, net jei administratorius bus pasirinkęs kitą kalbą administravimui. Iš pirmo žvilgsnio atrodo, kad būtų galima tiesiog Meta klasėj rūšiavimą nurodyti priklausomą nuo šiuo metu pasirinktos kalbos:
ordering = ["lt" == translation.get_language()[:2] and "pavadinimas" \
or "pavadinimas_%s" % translation.get_language()[:2], "irasyta"]
Deja modelio sisteminio analizavimo metu dar nėra žinoma naudotojo (administratoriaus) pasirinkta kalba ir translation.get_language() grąžina standartinę — mūsų atveju lietuvių — kalbą. Naudotojo pasirinkta kalba sistemai sužinoma tik vėliau, apdorojant modelio informaciją ir atvaizduojant jo objektus administravimo sistemoj. Laimei, atviras karkasinės sistemos kodas ir objektiškai orientuota Python prigimtis leidžia pergudrauti apribojimus. Idėja tokia: perrašysiu bazinę sąrašo (list) klasę taip, kad ji grąžintų nuo naudotojo pasirinktos kalbos priklausomus rezultatus tada, kai į ją kreipiamasi. Konstruktorius paims sąrašą simbolių eilučių, kurios nurodys reikalingus laukus. Jei eilutė baigsis vienu pabraukimo simboliu "_", tuomet laukas bus laikomas daugiakalbiu ir vietoj šitos reikšmės bus grąžinamas atitinkamas laukas, priklausantis nuo naudotojo pasirinktos kalbos.
class LaukuSarasas(list):
def __init__(self, sarasas=[]):
self.sarasas = sarasas
def __iter__(self):
return iter(self._gauk_sarasa())
def __getitem__(self, indeksas):
return self._gauk_sarasa()[indeksas]
def __nonzero__(self):
return bool(self.sarasas)
def __len__(self):
return len(self.sarasas)
def __str__(self):
return str(self._gauk_sarasa())
def __repr__(self):
return repr(self._gauk_sarasa())
def _gauk_sarasa(self):
kalbos_kodas = translation.get_language()[:2]
rezultatas = []
for elementas in self.sarasas:
if elementas[:1]=="-":
rusiavimo_tvarka = "-"
elementas = elementas[1:]
else:
rusiavimo_tvarka = ""
if elementas[:2] == "__" or elementas[-1:] != "_":
rezultatas.append(rusiavimo_tvarka + elementas)
else:
if kalbos_kodas == "lt":
rezultatas.append(rusiavimo_tvarka + elementas[:-1])
else:
rezultatas.append(rusiavimo_tvarka + elementas + kalbos_kodas)
return rezultatas
Belieka atnaujinti mūsų pavyzdinį modelį, pasinaudojant šita mandra sąrašo klase.
# puslapiai/models.py
from django.db import models
from django.utils import translation
from django.utils.translation import gettext_lazy as _
class Puslapis(models.Model):
pavadinimas=models.CharField("Pavadinimas", maxlength=200)
pavadinimas_en=models.CharField("Title", maxlength=200)
pavadinimas_de=models.CharField("Titel", maxlength=200)
turinys=models.TextField("Turinys")
turinys_en=models.TextField("Content")
turinys_de=models.TextField("Kontent")
irasyta=models.DateTimeField(_("Sukūrimo data"), auto_now_add=True)
class Meta:
ordering=LaukuSarasas(["pavadinimas_", "-irasyta"])
verbose_name=_("puslapis")
verbose_name_plural=_("puslapiai")
class Admin:
list_display=LaukuSarasas(["pavadinimas_", "turinys_", "irasyta"])
def __str__(self):
return self.gauk_pavadinima()
def gauk_pavadinima(self, kalbos_kodas=None):
return getattr(self, "pavadinimas_%s" % kalbos_kodas or \
translation.get_language()[:2], "") or self.pavadinimas
def gauk_turini(self, kalbos_kodas=None):
return getattr(self, "turinys_%s" % kalbos_kodas or \
translation.get_language()[:2], "") or self.turinys
Tai tiek, mieli programuotojai! Štai jums mano variantas, kaip žaist su daugiakalbiškumu. Gal kas susidomėjot Python’u ir Django? Atsiprašau visų kitų, kurie nieko nesuprato. Ir einu tūsintis
.
(*) Kintamųjų vardai visuomet turėtų būti angliški, kad kodą lengviau suprastų skirtingų šalių žmonės, bet dėl aiškumo (kas yra karkasinės sistemos dalis, o kas — mano kodas) tuos vardus sulietuvinau.






