django-parler / django-parler Goto Github PK
View Code? Open in Web Editor NEWEasily translate "cheese omelet" into "omelette au fromage".
License: Apache License 2.0
Easily translate "cheese omelet" into "omelette au fromage".
License: Apache License 2.0
First of all, thanks for the nice package.
I'm having trouble to make sense of this code in the docs' section with the title above:
class TranslatableSite(TranslatableModel, Site):
class Meta:
proxy = True
translations = TranslatedFields()
What exactly should be wrapped in TranslatedFields()?
On the same subject, I found a gist on integrating django-oscar with django-parler -- a good example of tweaking existing models for translation:
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),
)
In this case the contents of TranslatedFields is provided; but then, having to redefine a field in the untranslated model and/or rename it (tr_title) strikes me as less than ideal. Am I missing something? Could parler provide a function that moves fields across classes to avoid field redefinition:
class Product(AbstractProduct, TranslatableModel):
...
translations = TranslatedFields(
title = move_field(AbstractProduct, 'title'),
description = move_field(AbstractProduct, 'description'),
)
Not sure if this is possible given model metaclass semantics in Django though.
thanks in advance,
Kaleb
In [4]: from django.conf import settings
In [5]: settings.PARLER_LANGUAGES
Out[5]:
{2: ({'code': 'fr', 'fallback': 'fr', 'hide_untranslated': False},
{'code': 'en', 'fallback': 'fr', 'hide_untranslated': False}),
'default': {'code': 'fr', 'fallback': 'fr', 'hide_untranslated': False}}
In [6]: settings.SITE_ID
Out[6]: 2
In [7]: mv.safe_translation_getter('text_field', language_code='fr')
Out[7]: u'text fr'
In [8]: mv.safe_translation_getter('text_field', language_code='en')
In [9]: mv.set_current_language('en')
In [10]: mv.safe_translation_getter('text_field', language_code='en')
Out[10]: u'text fr'
The issue in my case is that https://github.com/edoburu/django-parler/blob/master/parler/models.py#L651 can raise TranslationDoesNotExist (and does) without trying to fallback on fr.
Guys, come on. Your tagline has a translation mistake
"Cheese Omelet" is not "Omelette du fromage".
In English, "Omelette du fromage" would be "Omelet of the Cheese".
You're looking for "Omelette au fromage".
Let's say I have a model:
from parler.models import TranslatableModel, TranslatedFields
...
class House(TranslatableModel, models.Model):
global_name = models.SlugField(max_length=255, db_index=True)
translations = TranslatedFields(
name=models.CharField(max_length=255),
description=models.CharField(max_length=255, blank=True),
)
Registering this model with Reversion is generally as easy as:
from reversion import VersionAdmin
class HouseAdmin(VersionAdmin):
...
This won't follow fk or m2m relations by default, so I have added this to a common app:
reversion.register(HouseTranslation)
and this to the models.py
described above:
reversion.register(House, follow=["translations"])
which doesn't seem to restore properly. It is always displaying the most recent revision/versions no matter which historical revision you view. Via the command line, I can see that the correct data appears to be written to the revision, including a version for the parent model, and a version for the translated attributes model. Is this at all the correct way to do this, or is there some alternative method? I am looking into VersionAdapters to do this in a custom way, but want to see if there are simpler methods.
Proxy model for models with existing data raises AttributeError: 'TranslatableDictionaryWord' object has no attribute '_current_language'
Traceback (most recent call last):
File "local/lib/python2.7/site-packages/django/core/handlers/base.py", line 113, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 372, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File "local/lib/python2.7/site-packages/django/utils/decorators.py", line 91, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "local/lib/python2.7/site-packages/django/views/decorators/cache.py", line 89, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "local/lib/python2.7/site-packages/django/contrib/admin/sites.py", line 202, in inner
return view(request, *args, **kwargs)
File "local/lib/python2.7/site-packages/django/utils/decorators.py", line 25, in _wrapper
return bound_func(*args, **kwargs)
File "local/lib/python2.7/site-packages/django/utils/decorators.py", line 91, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "local/lib/python2.7/site-packages/django/utils/decorators.py", line 21, in bound_func
return func(self, *args2, **kwargs2)
File "local/lib/python2.7/site-packages/django/contrib/admin/options.py", line 1285, in changelist_view
'selection_note': _('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)},
File "local/lib/python2.7/site-packages/django/db/models/query.py", line 106, in __len__
self._result_cache = list(self.iterator())
File "local/lib/python2.7/site-packages/parler/managers.py", line 103, in iterator
for obj in base_iterator:
File "local/lib/python2.7/site-packages/django/db/models/query.py", line 327, in iterator
obj = model(*row_data)
File "local/lib/python2.7/site-packages/parler/models.py", line 223, in __init__
super(TranslatableModel, self).__init__(*args, **kwargs)
File "local/lib/python2.7/site-packages/django/db/models/base.py", line 348, in __init__
setattr(self, field.attname, val)
File "local/lib/python2.7/site-packages/parler/fields.py", line 99, in __set__
translation = instance._get_translated_model(use_fallback=False, auto_create=True)
File "local/lib/python2.7/site-packages/parler/models.py", line 304, in _get_translated_model
language_code = self._current_language
AttributeError: 'TranslatableDictionaryWord' object has no attribute '_current_language'
Sending PR to fix it shortly...
Hello.
As I tried to find solution, I was unable to find how to define/switch language during adding/editing of items in Admin. I'm using django-suit and was thinking that this was the cause but even after turning it of I didn't find any control/link to switch language as it was possible with django-hvad.
Am I missing something ?
Hi Diederik,
It looks like parler does not conform Django 1.7 requirements, does it?
I've got the following error:
"(admin.E016) The value of 'form' must inherit from 'BaseModelForm'."
In your example ArticleAdminForm inherits TranslatableModelForm, which inherits forms.ModelForm, but not BaseModelForm..
Thanks
Iho
Hi,
I started using this package and it's really awesome !
I found a problem that 0 pk are never supported.
The Exception "<class 'parler.models.DoesNotExist'>' will be raised.
with the message fomatted like '{1} does not have a translation for the current language!'
I'm not sure if this is by design or just a bug.
What solved me the problem (and what I suggest as fix is):
In models.py line 386 change from:
if not self._state.adding and self.pk:
to
if not self._state.adding and self.pk is not None:
what do you think?
cheers
Lior.
I might be doing something wrong here but it looks like the fallback doesn't work when the translation exists for a different field.
I have a model like:
class MyModel(TranslatableModel):
title = TranslatedField(any_language=True)
description = TranslatedField(any_language=True)
translations = TranslatedFields(
title=models.CharField(max_length=255),
description=models.TextField(blank=True),
)
If I create an object with a translation for both fields in 'en', then add a translated description for 'de', when I retrieve that object in 'de' I would expect to have the German description and the English title (as a fallback). What happens instead is that, since the German translation exists, I get the German description and an empty title.
I took a quick look at the tests and it appears this case is not covered, since they all seem to deal with a single "title" field. Of course, maybe I'm just doing something wrong, in which case please let me know.
French translation for “cheese omelet” is « omelette au fromage » 😉
Based on the reports #38 and #39.
It's not possible to redefine fields as translatable if they also exist on the shared model.
The following could be improved:
django.db.model.Options.add_field()
.title = TranslatedField(redefine_field=True)
Today I tried to upgrade to Django-1.7. Unfortunately this does not work, and I have no clue why. I then boiled my project down to a very simply Django installation and am still able to reproduce it.
My environment:
Django==1.7.1
django-parler==1.2.1
django-polymorphic==0.6
...and unimportant stuff...
in settings.py:
INSTALLED_APPS = (
'polymorphic',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.admin',
'django.contrib.staticfiles',
'parler',
'my_demo',
)
Then I used the demo model.py from the docs:
# -*- coding: utf-8 -*-
from django.db import models
from django.utils.encoding import python_2_unicode_compatible, force_text
from parler.models import TranslatableModel, TranslatedFields
from polymorphic import PolymorphicModel
from parler.managers import TranslatableManager
class Product(PolymorphicModel):
code = models.CharField(blank=False, default='', max_length=16)
price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
@python_2_unicode_compatible
class Pen(TranslatableModel, Product):
default_manager = TranslatableManager()
translations = TranslatedFields(
identifier=models.CharField(blank=False, default='', max_length=255)
)
def __str__(self):
return force_text(self.identifier)
but I'am not able to even bootstrap this demo app:
(... snip - bootstrapping ...)
File ".../django/db/models/base.py", line 299, in add_to_class
value.contribute_to_class(cls, name)
File ".../parler/models.py", line 195, in contribute_to_class
create_translations_model(cls, name, self.meta, **self.fields)
File ".../parler/models.py", line 158, in create_translations_model
translations_model = TranslatedFieldsModelBase(name, (TranslatedFieldsModel,), attrs)
File ".../parler/models.py", line 677, in __new__
new_class = super(TranslatedFieldsModelBase, mcs).__new__(mcs, name, bases, attrs)
File ".../django/db/models/base.py", line 170, in __new__
new_class.add_to_class(obj_name, obj)
File ".../django/db/models/base.py", line 299, in add_to_class
value.contribute_to_class(cls, name)
File ".../django/db/models/fields/related.py", line 1585, in contribute_to_class
super(ForeignObject, self).contribute_to_class(cls, name, virtual_only=virtual_only)
File ".../django/db/models/fields/related.py", line 272, in contribute_to_class
add_lazy_relation(cls, self, other, resolve_related_class)
File ".../django/db/models/fields/related.py", line 84, in add_lazy_relation
operation(field, model, cls)
File ".../django/db/models/fields/related.py", line 271, in resolve_related_class
field.do_related_class(model, cls)
File ".../django/db/models/fields/related.py", line 307, in do_related_class
self.set_attributes_from_rel()
File ".../django/db/models/fields/related.py", line 304, in set_attributes_from_rel
self.rel.set_field_name()
File ".../django/db/models/fields/related.py", line 1256, in set_field_name
self.field_name = self.field_name or self.to._meta.pk.name
AttributeError: 'NoneType' object has no attribute 'name'
BTW, the same happens if I use the Book
example.
I saw that polymorphic/query.py
attempts to handle something:
# We might assume that self.model._meta.pk.name gives us the name of the primary key field,
# but it doesn't. Therefore we use polymorphic_primary_key_name, which we set up in base.py.
but adding a breakpoint into that method is never triggered.
If you want, I can put a reference implementation on GitHub.
I was recently thinking about the idea behind PARLER_LANGUAGES
. As settings.SITE_ID
and settings.PARLER_LANGUAGES
are both rather static I wonder if it really makes sense that PARLER_LANGUAGES
is a dict containing all sites.
If one really wants to keep the configuration of multiple sites in one settings file it would be really simple to do so without having parler to include any site logic:
SITE_ID = int(environ['DJANGO_SITE_ID'])
LANGUAGES = {
1: [
{'code': 'en'},
{'code': 'fr'},
],
2: [
{'code': 'en'},
{'code': 'de'},
{'code': 'ru'},
]
}[settings.SITE_ID]
Personally I would use a separate settings_site1.py
and settings_site2.py
file which could import common settings from a settings_base.py
, but this really is a matter of taste.
How about using the LANGUAGES
by default for creating the admin tabs? A multi lingual site usually configures LANGUAGES
anyways and just having to duplicate the language codes for parler should not be necessary if the user is happy with the per language defaults, no?
I also wonder why there is a PARLER_DEFAULT_LANGUAGE_CODE
and PARLER_LANGUAGES['default']['fallback']
. Why having two different ways of configuring things? Having a PARLER_DEFAULT_FALLBACK
and PARLER_HIDE_UNTRANSLATED
would make way more sense than having two styles of configuring things.
I'm a big fan of having one configuration dict per app (simmilar to DATABASES
). For parler this could look like the following:
PARLER = {
'DEFAULT_LANGUAGE_CODE': 'en',
'DEFAULT_FALLBACK': 'en',
'HIDE_UNTRANSLATED': False,
'LANGUAGES': [
'en': {},
'en-us': {'FALLBACK': ['en']},
'en-gb': {'FALLBACK': ['en']},
'de: {}',
'de-de': {'FALLBACK': ['de']},
'de-at': {'FALLBACK': ['de']},
'de-ch': {'FALLBACK': ['de']},
]
}
Now if someone really wants to have different settings per site it could simply be done by placing custom logic in the settings. Parler does not need to add explicit support for this to work.
If you want to have truly dynamic settings I would rather allow PARLER
to point to a callable which can then create truly dynamic configuration 100% customizable by the user. In the end I really wonder if someone has such use case.
I might be missing an important point, but right now the parler configuration looks a bit clunky with the site specific settings mixed with a default
key while other settings are direct attributes of the settings
with a PARLER_
prefix.
For backwards compatibility PARLER_*
settings could be deprecated in favor of the new PARLER
setting.
My default language is en-au
according to Django and Parler settings. But objects created from the interactive shell or a data migration have a default language of en-us
.
This caused much confusion as I logged into the admin and clicked through to edit the object I had created in my data migration and found that all of its translated fields were empty in the form.
But in the change list, it showed me the en-us
translation, causing even more confusion.
>>> from django.conf import settings
>>> from django.contrib.auth import get_user_model
>>> from fluent_pages.models import PageLayout
>>> from fluent_pages.pagetypes.fluentpage.models import FluentPage
>>> from parler import appsettings
>>> User = get_user_model()
>>> settings.LANGUAGE_CODE
'en-au'
>>> appsettings.PARLER_DEFAULT_LANGUAGE_CODE
'en-au'
>>> admin = User.objects.get(username='admin')
>>> home = PageLayout.objects.get(key='home')
>>> page = FluentPage.objects.create(
author=admin,
title='Home Page',
status='p',
layout=home,
override_url='/',
)
>>> page.get_current_language()
u'en-us'
See this: c450348#commitcomment-10963488
After confirming deletion you are redirected to "admin:changelist" page, maybe "admin:change" is more obvious choice?
This might be going a bit far, but would it be possible to switch between the languages without reloading the page? Ideally it would be nice for the user to be able to edit any of the different languages and hit "Save" and have them all save at once.
What do you think? Is this possible? Or very difficult?
Hello :-)
You gave nice demo during your presentation at the conference, would you please share how to start parler with Oscar or if you have any examples to start with? On gist or so would be great.
Best Regards,
Bashar
Hi
I find this is very interesting django module to work with, thanks for nice job...
I have an issue with my translation, being a new django user i am not able figure out where exactly i had gone wrong in my code... pls refer my code here... https://gist.github.com/gowram
I would like to know why translation not working when i change the language choice in my template page... is there some parts need to be done in my view or url...
Thanks & Regards
Rama
Would it be possible to use a language code parameter when building a TranslatableModelForm, so that the resulting form will display and save the translated fields, maybe creating them if they don't exist?
Or is the expected workflow to use with switch_language(model, lang): MForm(instance=model)
?
Using the pattern of existing models with multiple inheritance and Meta.proxy = True
wrongly causes TranslatableModel to not fetch existing language instances when saving.
Fixed in #39 - plus test case.
The issue is that whenever a translated model made by a proxy is changed, the following happens:
Hello,
if all translation fields are only optional and user do not fulfill values in Django admin, translation object is not created. Is possible to force creation of object?
Example of model:
class Author(TranslatableModel):
translations = TranslatedFields(
name = models.ForeignKey('AuthorName', blank=True, null=True),
description = models.TextField(blank=True),
like_count = models.BigIntegerField(default=0),
quote_count = models.BigIntegerField(default=0),
)
TranslatedFieldsModel
does self._original_values = self._get_field_values()
in the constructor, which causes an additional query to fetch master
(if it's not in _master_cache
, (which it can't be as the object hasn't been initialized yet...)).
This causes N queries when querying Translations by hand, which is not nice.
I think that _get_field_values
should at the very least exclude master
(master_id
is enough, isn't it?) or maybe simply use get_translated_fields
.
Am I missing something there?
Hi,
Just noticed the automatically generated translation model benefits from a unique_together ('language_code', 'master').
There is no such constraint in the examples of the documentation about manual translation models: http://django-parler.readthedocs.org/en/latest/advanced/manual-models.html
I noticed that because I ended up with two translation instances for the same master model, probably my fault.
Hey everyone.
I got a M2M field included in TranslatedFields to show up fairly easily on the shared model, by adding a call to cls._meta.get_m2m_with_model()
in a couple of places. However, now I'm getting this error:
"<CardTranslation: #None, cy, master: #None>" needs to have a value for field
"cardtranslation" before this many-to-many relationship can be used.
I kind of have an idea why this is happening and was considering taking it upon myself to implementing M2M support (depends whether my current project will end up needing it, I guess). I wanted to hear your thoughts on this first, though. I've only started reading the Parler code today -- maybe someone more experienced could share a few caveats?
At least when attempting to use the latest master branch of django-parler
with django-fluent-pages
.
Here's a traceback of the last few recursions.
File "/Users/tailee/.virtualenvs/fluent-demo/src/django-parler/parler/admin.py" in get_form
205. form_class = super(TranslatableAdmin, self).get_form(request, obj, **kwargs)
File "/Users/tailee/.virtualenvs/fluent-demo/src/django/django/contrib/admin/options.py" in get_form
503. fields = flatten_fieldsets(self.get_fieldsets(request, obj))
File "/Users/tailee/.virtualenvs/fluent-demo/lib/python2.7/site-packages/polymorphic/admin.py" in get_fieldsets
478. other_fields = self.get_subclass_fields(request, obj)
File "/Users/tailee/.virtualenvs/fluent-demo/lib/python2.7/site-packages/polymorphic/admin.py" in get_subclass_fields
497. form = self.get_form(request, obj, exclude=exclude)
File "/Users/tailee/.virtualenvs/fluent-demo/lib/python2.7/site-packages/polymorphic/admin.py" in get_form
412. return super(PolymorphicChildModelAdmin, self).get_form(request, obj, **kwargs)
File "/Users/tailee/.virtualenvs/fluent-demo/src/django-parler/parler/admin.py" in get_form
205. form_class = super(TranslatableAdmin, self).get_form(request, obj, **kwargs)
File "/Users/tailee/.virtualenvs/fluent-demo/src/django/django/contrib/admin/options.py" in get_form
503. fields = flatten_fieldsets(self.get_fieldsets(request, obj))
File "/Users/tailee/.virtualenvs/fluent-demo/lib/python2.7/site-packages/polymorphic/admin.py" in get_fieldsets
478. other_fields = self.get_subclass_fields(request, obj)
File "/Users/tailee/.virtualenvs/fluent-demo/lib/python2.7/site-packages/polymorphic/admin.py" in get_subclass_fields
497. form = self.get_form(request, obj, exclude=exclude)
File "/Users/tailee/.virtualenvs/fluent-demo/lib/python2.7/site-packages/polymorphic/admin.py" in get_form
412. return super(PolymorphicChildModelAdmin, self).get_form(request, obj, **kwargs)
File "/Users/tailee/.virtualenvs/fluent-demo/src/django-parler/parler/admin.py" in get_form
205. form_class = super(TranslatableAdmin, self).get_form(request, obj, **kwargs)
File "/Users/tailee/.virtualenvs/fluent-demo/src/django/django/contrib/admin/options.py" in get_form
503. fields = flatten_fieldsets(self.get_fieldsets(request, obj))
File "/Users/tailee/.virtualenvs/fluent-demo/lib/python2.7/site-packages/polymorphic/admin.py" in get_fieldsets
478. other_fields = self.get_subclass_fields(request, obj)
File "/Users/tailee/.virtualenvs/fluent-demo/lib/python2.7/site-packages/polymorphic/admin.py" in get_subclass_fields
497. form = self.get_form(request, obj, exclude=exclude)
File "/Users/tailee/.virtualenvs/fluent-demo/lib/python2.7/site-packages/polymorphic/admin.py" in get_form
412. return super(PolymorphicChildModelAdmin, self).get_form(request, obj, **kwargs)
File "/Users/tailee/.virtualenvs/fluent-demo/src/django-parler/parler/admin.py" in get_form
205. form_class = super(TranslatableAdmin, self).get_form(request, obj, **kwargs)
Exception Type: RuntimeError at /admin/fluent_pages/page/add/
Exception Value: maximum recursion depth exceeded in cmp
Using version 1.0.
Django's auth.Permission.name is limited to 50 chars, but parler can generate permission names longer than that.
For example with a model labelled "Terms and conditions", "Can add version of the Terms and conditions Translation" is 55 chars. Even 58 with "Can change" and "Can delete" permissions.
Using parler 1.0
Hi again,
I have a model A with a translation table, and another model B that inherits from A, but with more translated fields.
I came up with this:
# -*- coding: utf-8 -*-
from django.db import models
from parler import models as parler_models
class MyModel(parler_models.TranslatableModel):
title = parler_models.TranslatedField()
class MyModelTranslation(parler_models.TranslatedFieldsModel):
master = models.ForeignKey(MyModel, related_name='translations', null=True)
title = models.CharField(max_length=200)
class MyRicherModel(MyModel):
description = parler_models.TranslatedField()
class MyRicherModelTranslation(parler_models.TranslatedFieldsModel):
master = models.ForeignKey(MyRicherModel, related_name='translation', null=True)
title = models.CharField(max_length=200)
description = models.TextField()
But the model B is already registered to the model A's translation table, according to parler:
$ ./manage.py syncdb --noinput
No handlers could be found for logger "parler.models"
Traceback (most recent call last):
File "./manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/Users/herve/.virtualenvs/testcase-parler-inheritance/lib/python2.7/site-packages/django/core/management/__init__.py", line 399, in execute_from_command_line
utility.execute()
File "/Users/herve/.virtualenvs/testcase-parler-inheritance/lib/python2.7/site-packages/django/core/management/__init__.py", line 392, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/herve/.virtualenvs/testcase-parler-inheritance/lib/python2.7/site-packages/django/core/management/base.py", line 242, in run_from_argv
self.execute(*args, **options.__dict__)
File "/Users/herve/.virtualenvs/testcase-parler-inheritance/lib/python2.7/site-packages/django/core/management/base.py", line 284, in execute
self.validate()
File "/Users/herve/.virtualenvs/testcase-parler-inheritance/lib/python2.7/site-packages/django/core/management/base.py", line 310, in validate
num_errors = get_validation_errors(s, app)
File "/Users/herve/.virtualenvs/testcase-parler-inheritance/lib/python2.7/site-packages/django/core/management/validation.py", line 34, in get_validation_errors
for (app_name, error) in get_app_errors().items():
File "/Users/herve/.virtualenvs/testcase-parler-inheritance/lib/python2.7/site-packages/django/db/models/loading.py", line 196, in get_app_errors
self._populate()
File "/Users/herve/.virtualenvs/testcase-parler-inheritance/lib/python2.7/site-packages/django/db/models/loading.py", line 75, in _populate
self.load_app(app_name, True)
File "/Users/herve/.virtualenvs/testcase-parler-inheritance/lib/python2.7/site-packages/django/db/models/loading.py", line 99, in load_app
models = import_module('%s.models' % app_name)
File "/Users/herve/.virtualenvs/testcase-parler-inheritance/lib/python2.7/site-packages/django/utils/importlib.py", line 40, in import_module
__import__(name)
File "/Users/herve/dev/testcaseparlerinheritance/testcaseparlerinheritance/models.py", line 22, in <module>
class MyRicherModelTranslation(parler_models.TranslatedFieldsModel):
File "/Users/herve/.virtualenvs/testcase-parler-inheritance/lib/python2.7/site-packages/parler/models.py", line 550, in __new__
shared_model = _validate_master(new_class)
File "/Users/herve/.virtualenvs/testcase-parler-inheritance/lib/python2.7/site-packages/parler/models.py", line 577, in _validate_master
raise TypeError(msg)
TypeError: The model 'MyRicherModel' already has an associated translation table!
(This is a minimal app to reproduce the issue, the actual app even has a third model.)
Is it a known limitation of parler?
I consider writing a single translation model with all the fields combined to bypass this. Parler will just query the fields it is looking for.
class ConnectionType(TranslatableModel):
translations = TranslatedFields(
# дома, квартиры...
name=models.CharField(_(u'Name'), max_length=50),
)
slug = models.SlugField(
_(u'Slug'),
unique=True,
blank=True,
help_text=_(u"если не заполнить, то будет заполнено на основе названия")
)
this will dump data with 'name' field which is not loadable
Hi,
How's the integration with the new version of Rest Framework?
The docs mention a TranslatableModelSerializer, but the parler.contrib
package is empty...
The project seems really neat, but Rest Framework compatibility is a must for us.
Thanks!
If - say - Portuguese is my currently set language, i.e. that I'm in /pt/admin/app/translatable-model/123/?language=de and I add or edit the German version, the Portuguese version is also overwritten. I have no idea if this behaviour is linked to the change, but it only happens on proxy models. Normal model inheritors of TranslatableModel have no problems under the same setup.
class ModelWithoutTranslations(models.Model):
original_field = models.CharField(
default="untranslated",
max_length=255,
)
class ExistingModelWithTranslations(TranslatableModel, ModelWithoutTranslations):
translations = TranslatedFields(
original_field=models.CharField(default="translated", max_length=255)
)
class Meta:
proxy = True
The following test case proves the error:
def test_proxy_model_saving(self):
"""
This test checks that contents of proxy models are correctly saved
and do not affect other models or instances, see #41
"""
translation.activate(translation.get_language())
x = ModelWithoutTranslations(original_field="lalala")
x.save()
x = ExistingModelWithTranslations.objects.get(original_field="lalala")
x.set_current_language(self.other_lang1)
x.original_field = "test lang1"
x.save()
# Change the active language to other_lang1 and try to refetch the object
translation.activate(self.other_lang1)
x = ExistingModelWithTranslations.objects.get(original_field="test lang1")
# Check that original is still untouched
x = ModelWithoutTranslations.objects.get(original_field="lalala")
translation.activate(translation.get_language())
models.py
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
from parler.models import TranslatableModel, TranslatedFields
class Category(MPTTModel, TranslatableModel):
translations = TranslatedFields(
name = models.TextField(unique=True)
)
order_num = models.IntegerField(default=10)
parent = TreeForeignKey('self',
null=True, blank=True, related_name='children')
def __unicode__(self):
return self.name
admin.py
from parler.admin import TranslatableAdmin
from mptt.admin import MPTTModelAdmin
from .models import Category
class CategoryAdmin(MPTTModelAdmin, TranslatableAdmin):
pass
admin.site.register(Category, CategoryAdmin)
When I come to admin and try to open Categories list I get an error:
Request Method: GET
Request URL: http://127.0.0.1:8000/admin/articles/category/
Django Version: 1.7.2
Python Version: 2.7.6
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'parler',
'articles')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware')
Traceback:
File "/home/alex/.virtualenvs/tests/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
111. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/alex/.virtualenvs/tests/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in wrapper
583. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/alex/.virtualenvs/tests/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
105. response = view_func(request, *args, **kwargs)
File "/home/alex/.virtualenvs/tests/local/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
52. response = view_func(request, *args, **kwargs)
File "/home/alex/.virtualenvs/tests/local/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
206. return view(request, *args, **kwargs)
File "/home/alex/.virtualenvs/tests/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
29. return bound_func(*args, **kwargs)
File "/home/alex/.virtualenvs/tests/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
105. response = view_func(request, *args, **kwargs)
File "/home/alex/.virtualenvs/tests/local/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
25. return func.__get__(self, type(self))(*args2, **kwargs2)
File "/home/alex/.virtualenvs/tests/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in changelist_view
1485. self.list_max_show_all, self.list_editable, self)
File "/home/alex/.virtualenvs/tests/local/lib/python2.7/site-packages/django/contrib/admin/views/main.py" in __init__
75. self.root_queryset = model_admin.get_queryset(request)
File "/home/alex/.virtualenvs/tests/local/lib/python2.7/site-packages/django_parler-1.2.1-py2.7.egg/parler/admin.py" in get_queryset
158. raise ImproperlyConfigured("{0} class does not inherit from TranslatableQuerySet".format(qs.__class__.__name__))
Exception Type: ImproperlyConfigured at /admin/articles/category/
Exception Value: QuerySet class does not inherit from TranslatableQuerySet
Steps:
Error is:
FieldError at /fr/admin/article/article/add/
Unknown field(s) (content, slug, title) specified for Article
The current code is:
class ArticleAdmin(TranslatableAdmin):
# ...
# declared_fieldsets works in django1.4, contrary to fieldsets
declared_fieldsets = (
(None, {
'fields': ('title', 'slug', 'published', 'category'),
}),
("Contents", {
'fields': ('content',),
})
)
So for some reason, the admin can't find the translated fields.
In django admin when deleting translation following error occurs (delete-translation/de/):
type object 'WysiwygWidgetFormFormSet' has no attribute 'fk'
Location: parler/admin.py in _get_inline_translations, line 503
Problem is with formset pk which doesn't exist:
fk = inline.get_formset(request, obj).fk
rel_name = 'master__{0}'.format(fk.name)
Do we actually need rel_name filter?
Any plans for this ?
Thanks !
https://github.com/edoburu/django-parler/blob/master/docs/configuration.rst
The section PARLER_ENABLE_CACHING
(Line 110 I believe) states:
If needed, caching can be disabled. This is likely not needed.
I find the latter sentence confusing. Are you stating that the configuration line PARLER_ENABLE_CACHING = True
is probably not needed, or that it is likely that one doesn't want to disable caching?
You might argue that my English comprehension is lacking, which I will not disagree. However, in my opinion documentation should be as unambiguous as possible and assuming that most people using your django app are non-native English speakers, you might want to communicate this point differently.
I can't explain why this happened, but I switched on caching and got this on the first try. It worked afterwards.
...
File ".../parler/models.py", line 418, in _get_translated_model
object = get_cached_translation(self, language_code, related_name=meta.rel_name, use_fallback=use_fallback)
File ".../parler/cache.py", line 71, in get_cached_translation
values = _get_cached_values(instance, translated_model, language_code, use_fallback)
File ".../parler/cache.py", line 119, in _get_cached_values
if values.get('__FALLBACK__', False):
AttributeError: 'str' object has no attribute 'get'
It looks like values
can be a non-empty string at some point(?) before properly initialized in the cache(?). Feel free to close this, as I could not repeat it.
I think that on row 138 of file forms.py
the last parameter is meant to be **attrs[f_name].kwargs
instead of **translated_fields[f_name].kwargs
.
Besides that, I'm having issues getting the field rendered: I'd like to use a CKEditor widget, and that does not seem to work, but even if I remove the custom widget setting the label is rendered as %(contents)s:
instead of simply contents
.
edit: the label thing was totally a (stupid) error on my side, but I still can't get the custom widget to work.
Is there any way I could fix this?
edit: well disregard all of that, I am a tool.
Thanks
I'm using Admin sortable 2 in admin to order models by dragging them around. Parler works well with SortableAdminMixin but it doesn't work with SortableInlineAdminMixin. So basically, if the model is both translatable and inline, the two apps are not compatible. Just wonder if there's any tip or plan on integrating Admin sortable 2's SortableInlineAdminMixin.
Deleting translation and broken breadcrumb, see screenshot
Home -> /admin/fluent_pages/ ( should be /admin/ )
Fluentpage -> /admin/fluent_pages/page/ ( should be /admin/fluent_pages/ )
Pages -> /admin/fluent_pages/page/1/ ( should be /admin/fluent_pages/page/)
Spanish: testa -> /admin/fluent_pages/1/delete-translation/ ( should be /admin/fluent_pages/page/1/ or /admin/fluent_pages/page/1/?language=es )
Hello,
I'm using python 2.7, Django 1.7 with an SQLite3 database and parler 1.1. I have written this small setup:
# testapp/models.py
class TestBlob(TranslatableModel):
translations = TranslatedFields(
name=django.db.models.CharField(max_length=10)
)
# testapp/tests.py
class ParlerTest(TestCase):
def test_a(self):
testblob = TestBlob.objects.language("en").create(name="english")
self.assertEqual("en", testblob.get_current_language())
self.assertEqual(set(["en"]), set(testblob.get_available_languages()))
with switch_language(testblob, "de"):
testblob.name = "deutsch"
testblob.save()
self.assertEqual("de", testblob.get_current_language())
self.assertEqual("deutsch", testblob.name)
self.assertEqual(set(["en", "de"]), set(testblob.get_available_languages())) # test fails here
The following error appears during testing:
...$ python manage.py test testapp.tests.ParlerTest.test_a testapp.tests.ParlerTest.test_a -v2
test_a (testapp.tests.ParlerTest) ... ok
test_a (testapp.tests.ParlerTest) ... FAIL
======================================================================
FAIL: test_a (testapp.tests.ParlerTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "testapp/tests.py", line 23, in test_a
self.assertEqual(set(["en", "de"]), set(testblob.get_available_languages()))
AssertionError: Items in the first set but not the second:
u'de'
----------------------------------------------------------------------
Ran 2 tests in 0.017s
The error does not seem to appear if I use parler 1.0 or use PostgreSQL or have PARLER_ENABLE_CACHING=False in my settings.
Can you please help me?
unique_together parameter is not checked at the admin level with def validate_unique()
, and it raises an IntegrityError
when hit the database.
I defined the model as follows:
class SimpleModel(TranslatableModel):
text = models.CharField(_('name'), max_length=255),
translations = TranslatedFields(
name=models.CharField(_('name'), max_length=255),
slug=models.SlugField(_('slug'), blank=True, db_index=True),
meta={'unique_together': (('language_code', 'slug'),)}
)
Hi,
I find out that this should be the best package to use with django-shop. But I don't know what is necessary to make products attribute name multilingual? Is anywhere some example?
Thanks a lot.
For technical reasons the primary key of a translatable model needs to be a charfield, but when I try to retrieve the translation, the function get_translation_cache_key fails due to long(master_id)
There is some justification, to use long in this place? Any idea to solve this issue?
I really want to use this package in my project, and I'm also hoping to use django 1.8 since this is a new project and 1.8 is the next LTS release due out in just a few days.
I get errors like this when trying to create a TranslatableModel in my app:
Also, I noticed that the django.template.loader.find_template() function used in parler.template should be replaced with django.template.loader.get_template() for 1.8.
This will probably be where the problem is coming from:
https://docs.djangoproject.com/en/dev/ref/models/meta/#migrating-from-the-old-api
I am able to create translatable polymorphic models, by creating a model class which inherits from two classes TranslatableModel
and another class derived from PolymorphicModel
. If I create an admin interface for each type of model, the admin backend works fine.
django-polymorphic allows to create an admin interface which can handle more than one type of model. However, if I try to create an admin class which inherits from TranslatableAdmin
and PolymorphicChildModelAdmin
and I try to save the form, this form is rejected.
Is there any receipt on how to mix them?
Given this dummy model, I want to retrieve and display a list of these models performing only one query:
class Dummy(TranslatableModel):
translations = TranslatedFields(
a = models.CharField(max_length=50),
)
b = models.CharField(max_length=50)
Trying with the following code does not yield the expected results (N+1 queries):
In [2]: from django.utils import translation
In [3]: translation.activate('en')
In [4]: from blog.models import Dummy
In [5]: Dummy.objects.all()
(0.002) SELECT "blog_dummy"."id", "blog_dummy"."b" FROM "blog_dummy" LIMIT 21; args=()
(0.000) SELECT "blog_dummy_translation"."id", "blog_dummy_translation"."language_code", "blog_dummy_translation"."a", "blog_dummy_translation"."master_id" FROM "blog_dummy_translation" WHERE ("blog_dummy_translation"."master_id" = 1 AND "blog_dummy_translation"."language_code" = en ); args=(1, 'en')
(0.000) SELECT "blog_dummy_translation"."id", "blog_dummy_translation"."language_code", "blog_dummy_translation"."a", "blog_dummy_translation"."master_id" FROM "blog_dummy_translation" WHERE ("blog_dummy_translation"."master_id" = 2 AND "blog_dummy_translation"."language_code" = en ); args=(2, 'en')
Out[5]: [<Dummy: a1>, <Dummy: a2>]
The only way I found to do this, is querying directly the TranslatedModel:
In [6]: DummyTranslation=Dummy.translations.related.model
In [7]: DummyTranslation.objects.select_related('master').filter(language_code='en')
(0.000) SELECT "blog_dummy_translation"."id", "blog_dummy_translation"."language_code", "blog_dummy_translation"."a", "blog_dummy_translation"."master_id", "blog_dummy"."id", "blog_dummy"."b" FROM "blog_dummy_translation" LEFT OUTER JOIN "blog_dummy" ON ("blog_dummy_translation"."master_id" = "blog_dummy"."id") WHERE "blog_dummy_translation"."language_code" = en LIMIT 21; args=('en',)
Out[7]: [<DummyTranslation: #1, en, master: #1>, <DummyTranslation: #2, en, master: #2>]
But then I have to access the shared model's fields through "master" (e.g. dummy.master.b
).
Is there a better way to do this? What am I doing wrong?
Thanks
Hi,
The repo description says:
Easily translate "cheese omelet" into "omelette du fromage".
The "du" is wrong. It should be:
Easily translate "cheese omelet" into "omelette au fromage".
Cheers
Hi Diederik,
Thank you for your nice parler.
I know this is piece of work, but maybe you have intent to write Translatable Serializers for Django-Rest-Framework? It would be great..
Thanks
Iho
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.