4. Modeling a Multilingual Product¶
Let’s extend our previous SmartCard
model to internationalize our shop site. Normally the name
of a Smart Card model is international anyway, say “Ultra Plus micro SDXC”, so it probably won’t
make much sense to use a translatable field here. The model attribute which certainly makes sense
to be translated into different languages, is the description
field.
4.1. Run the Multilingual Demo¶
To test this example, set the shell environment variable export DJANGO_SHOP_TUTORIAL=i18n_smartcard
,
then apply the modified models to the database schema:
./manage.py migrate myshop
Alternatively recreate the database as explained in Create a database for the demo.
Afterwards start the demo server:
./manage.py runserver
4.2. The Multilingal Product Model¶
DjangoSHOP uses the library django-parler for model translations. We therefore shall rewrite our model as:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
from djangocms_text_ckeditor.fields import HTMLField
from parler.managers import TranslatableManager, TranslatableQuerySet
from parler.models import TranslatableModelMixin, TranslatedFieldsModel
from parler.fields import TranslatedField
from polymorphic.query import PolymorphicQuerySet
from shop.money.fields import MoneyField
from shop.models.product import BaseProductManager, BaseProduct, CMSPageReferenceMixin
from shop.models.defaults.order import Order
from ..manufacturer import Manufacturer
__all__ = ['SmartCard', 'Order']
class ProductManager(BaseProductManager, TranslatableManager):
queryset_class = ProductQuerySet
def get_queryset(self):
card_type = models.CharField(_("Card Type"), choices=CARD_TYPE, max_length=15)
SPEED = ((str(s), "{} MB/s".format(s)) for s in (4, 20, 30, 40, 48, 80, 95, 280))
def get_price(self, request):
return self.unit_price
class SmartCardTranslation(TranslatedFieldsModel):
master = models.ForeignKey(SmartCard, related_name='translations', null=True)
caption = HTMLField(verbose_name=_("Caption"),
configuration='CKEDITOR_SETTINGS_CAPTION',
help_text=_("Short description used in the catalog's list view of products."))
description = HTMLField(verbose_name=_("Description"),
configuration='CKEDITOR_SETTINGS_DESCRIPTION',
help_text=_("Full description used in the catalog's detail view of Smart Cards."))
class Meta:
unique_together = [('language_code', 'master')]
|
In comparison to the simple Smart Card model, the field description
can now accept text in
different languages.
In order to work properly, a model with translations requires an additional model manager and a
table storing the translated fields. Accessing an instance of this model behaves exactly the same
as an untranslated model. Therefore it can be used as a drop-in replacement for our simple
SmartCard
model.
4.3. Translatable model in Django Admin¶
The admin requires only a small change. Its class must additionally inherit from
TranslatableAdmin
. This adds a tab for each configured language to the top of the detail
editor. Therefore it is recommended to group all multilingual fields into one fieldset to emphasize
that these fields are translatable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | from django.contrib import admin
from django.utils.translation import ugettext_lazy as _
from adminsortable2.admin import SortableAdminMixin
from parler.admin import TranslatableAdmin
from shop.admin.product import CMSPageAsCategoryMixin, ProductImageInline
from myshop.models import SmartCard
@admin.register(SmartCard)
class SmartCardAdmin(SortableAdminMixin, TranslatableAdmin,
CMSPageAsCategoryMixin, admin.ModelAdmin):
fieldsets = (
(None, {
'fields': ('product_name', 'slug', 'product_code', 'unit_price', 'active',),
}),
(_("Translatable Fields"), {
'fields': ('caption', 'description',)
}),
(_("Properties"), {
'fields': ('manufacturer', 'storage', 'card_type',)
}),
)
inlines = (ProductImageInline,)
prepopulated_fields = {'slug': ('product_name',)}
list_display = ('product_name', 'product_code', 'unit_price', 'active',)
search_fields = ('product_name',)
|
Extend our discrete product type, to polymorphic models which are able to support many different product types: Products with Different Properties.