Skip to content

Instantly share code, notes, and snippets.

@vdboor
Last active February 25, 2021 12:29
Show Gist options
  • Save vdboor/46348490c7cd1a5b08f4 to your computer and use it in GitHub Desktop.
Save vdboor/46348490c7cd1a5b08f4 to your computer and use it in GitHub Desktop.
A quick overview how to combine django-parler with django-oscar. This assumes you are familliar with the "Customising Oscar" topics (https://django-oscar.readthedocs.org/en/latest/topics/customisation.html). A screenshot of the integration was shown at DjangoConEU 2014 (http://django-fluent.org/blog/2014/05/lightning-talk-djangocon-eu-2014/)
from oscar.apps.catalogue.abstract_models import AbstractProduct,
from parler.models import TranslatableModel, TranslatedFields
class Product(AbstractProduct, TranslatableModel):
"""
Add translations to the product model.
"""
# Provide translated fields.
# Consider renaming tr_title to `title` and see if you can replace the original title field this way.
translations = TranslatedFields(
tr_title = models.CharField(_('Translated Title'), max_length=255, blank=True, null=True, help_text=_(u"The title can be highlighted by <strong>*surrounding words*</strong> with an asterisk.")),
description = models.TextField(_('Translated Description'), blank=True, null=True),
)
def get_title(self):
tr_title = self.safe_translation_getter('tr_title', default=None)
if not tr_title:
return super(Product, self).get_title()
else:
return tr_title
from oscar.apps.dashboard.catalogue import app as oscar_app
from . import views
class CatalogueApplication(oscar_app.CatalogueApplication):
# Override Oscar views
product_createupdate_view = views.ProductCreateUpdateView
application = CatalogueApplication()
from django import forms
from django.forms.models import inlineformset_factory, BaseInlineFormSet
from oscar.core.loading import get_model
from parler.forms import TranslatableModelForm
from oscar.apps.dashboard.catalogue import forms as oscar_forms
Product = get_model('catalogue', 'Product')
class ProductForm(TranslatableModelForm, oscar_forms.ProductForm):
# Exports for template
translation_field_names = (
'tr_title',
'tr_description',
)
class Meta(oscar_forms.ProductForm.Meta):
model = Product # django-parler needs this:
#exclude = oscar_forms.ProductForm.Meta.exclude
widgets = oscar_forms.ProductForm.Meta.widgets
def visible_fields(self):
# Hide the translated fields at the main tab.
hide_fields = self._get_translated_fields() # HACK: private method call
hide_fields.append('description') # use "tr_description instead
hide_fields.extend(self.external_reviews_names)
return [field for field in self if not field.is_hidden and not field.name in hide_fields]
def translation_fields(self):
return [self[name] for name in self.translation_field_names]
from oscar.apps.dashboard.catalogue import views as oscar_views
from parler.views import TranslatableModelFormMixin
class ProductCreateUpdateView(TranslatableModelFormMixin, oscar_views.ProductCreateUpdateView):
"""
Updated product create view, that supports translations
"""
def get_context_data(self, **kwargs):
context = super(ProductCreateUpdateView, self).get_context_data(**kwargs)
context['has_custom_language'] = 'language' in self.request.GET
return context
{% extends "oscar/dashboard/catalogue/product_update.html" %}
{% load i18n form_tags %}
{% comment %}
This is some serious hacking to get translated fields in the Oscar template due to a lack of blocks.
Also, currently there is no form class in django-parler so edit all translated fields in a single form,
so the language tabs will still refresh the entire page. Improvements are welcome here.
{% endcomment %}
{% block tab_nav %}
<div class="span3">
<div data-spy="affix" class="affix-top" data-offset-top="200">
<div class="table-header">
<h3>{% trans "Sections" %}</h3>
</div>
<ul class="nav nav-list bs-docs-sidenav" id="product_update_tabs">
{% if product %}
<li{% if not has_custom_language %} class="active"{% endif %}><a href="#overview" data-toggle="tab">{% trans 'Overview' %}</a></li>
{% endif %}
<li{% if not product and not has_custom_language %} class="active"{% endif %}><a href="#product_details" data-toggle="tab">{% trans 'Product details' %}</a></li>
{# NOTE: added this tab #}
{% if not product.parent_id %}<li><a{% if has_custom_language %} class="active"{% endif %} href="#product_translations" data-toggle="tab">{% trans 'Product detail page & translations' %}</a></li>{% endif %}
{% if not product.parent_id %}<li><a href="#product_recommended" data-toggle="tab">{% trans 'Recommended Products' %}</a></li>{% endif %}
{% if not product.parent_id and product.variants.exists %}
<li><a href="#product_variants" data-toggle="tab">{% trans 'Product variants' %}</a></li>
{% endif %}
<li><a href="#product_attributes" data-toggle="tab">{% trans 'Product attributes' %}</a></li>
<li><a href="#product_category" data-toggle="tab">{% trans 'Product category' %}</a></li>
<li><a href="#product_images" data-toggle="tab">{% trans 'Product images' %}</a></li>
<li><a href="#product_stock" data-toggle="tab">{% trans 'Product stock' %}</a></li>
</ul>
</div>
</div>
{% endblock tab_nav %}
{% block product_details %}
{{ block.super }}
<div class="tab-pane {% if not product %}active{% endif %}" id="product_translations">
{% if language_tabs %}
<ul class="parler-language-tabs nav nav-tabs {% if language_tabs.css_class %} {{ language_tabs.css_class }}{% endif %}">
{% for url,name,code,status in language_tabs %}
{% if status == 'current' %}
<input type="hidden" class="language_button selected" name="language" value="{{ code }}" />
<li class="active"><a href="#">{{ name }}</a></li>
{% else %}
<li class="{{ status }}"><a href="{{ url }}">{{ name }}</a></li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
<div class="table-header">
<h3>{% trans "Translations" %}</h3>
</div>
<div class="well product-translations">
{% for field in form.translation_fields %}
{% annotate_form_field field %}
{% include 'partials/form_field.html' with field=field %}
{% endfor %}
</div>
</div>
{% endblock %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment