question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unable to Make existing fields translatable

See original GitHub issue

Hello,

I think I just found a problem in the documentation at: https://django-parler.readthedocs.io

I am trying to translate my model fields and when I try to follow the procedure described in the docs, all I get is: raise TypeError("Translatable model {} does not appear to inherit from TranslatableModel".format(shared_model)) TypeError: Translatable model <class '__fake__.Product'> does not appear to inherit from TranslatableModel

When I try to follow the docs, Python complains that the fields that are in translations = TranslatedFields are duplicated, so the first part of the doc does not work. No idea how to continue at this point, as this is complete road block for me.

Please find below the relevant data classes where I attempt to perform the translations.

from django.db import models
from django.urls import reverse
from parler.models import TranslatableModel, TranslatedFields

class Category(TranslatableModel):

    translations = TranslatedFields(
        name = models.CharField(max_length=200, db_index=True),
        slug = models.SlugField(max_length=200, db_index=True, unique=True))

    class Meta:

        verbose_name = 'category'
        verbose_name_plural = 'categories'

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('shop:product_list_by_category',
                       args=[self.slug])

class Product(TranslatableModel):

    translations = TranslatedFields(
        name = models.CharField(max_length=200, db_index=True),
        slug = models.SlugField(max_length=200, db_index=True),
        description = models.TextField(blank=True)
        )
    category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
    image = models.ImageField(upload_to='products/%Y/%m/%d', blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    available = models.BooleanField(default=True)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    # Commented for model translations.
    # class Meta:
    #
    #     ordering = ('name',)
    #     index_together = (('id', 'slug'),)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('shop:product_detail', args=[self.id, self.slug])

Related admin classes:

from django.contrib import admin
from .models import Category, Product
from parler.admin import TranslatableAdmin

@admin.register(Category)
class CategoryAdmin(TranslatableAdmin):
    list_display = ['name', 'slug']

    def get_prepopulated_fields(self, request, obj=None):
        return {'slug': ('name',)}

@admin.register(Product)
class ProductAdmin(TranslatableAdmin):
    list_display = ['name', 'slug', 'price', 'available', 'created', 'updated']
    list_filter = ['available', 'created', 'updated']

    list_editable = ['price', 'available']

    def get_prepopulated_fields(self, request, obj=None):
        return {'slug': ('name',)}
(venv) 192:myshop Username$ python manage.py makemigrations shop --name "add_translation_model"
Traceback (most recent call last):
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/parler/models.py", line 942, in contribute_translations
    base = shared_model._parler_meta
AttributeError: type object 'Product' has no attribute '_parler_meta'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "manage.py", line 21, in <module>
    main()
  File "manage.py", line 17, in main
    execute_from_command_line(sys.argv)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/core/management/base.py", line 328, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/core/management/base.py", line 369, in execute
    output = self.handle(*args, **options)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/core/management/base.py", line 83, in wrapped
    res = handle_func(*args, **kwargs)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/core/management/commands/makemigrations.py", line 168, in handle
    migration_name=self.migration_name,
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/autodetector.py", line 43, in changes
    changes = self._detect_changes(convert_apps, graph)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/autodetector.py", line 128, in _detect_changes
    self.old_apps = self.from_state.concrete_apps
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/state.py", line 213, in concrete_apps
    self.apps = StateApps(self.real_apps, self.models, ignore_swappable=True)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/state.py", line 272, in __init__
    self.render_multiple([*models.values(), *self.real_models])
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/state.py", line 307, in render_multiple
    model.render(self)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/state.py", line 578, in render
    return type(self.name, bases, body)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/models/base.py", line 320, in __new__
    new_class._meta.apps.register_model(new_class._meta.app_label, new_class)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/state.py", line 338, in register_model
    self.do_pending_operations(model)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/apps/registry.py", line 424, in do_pending_operations
    function(model)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/apps/registry.py", line 403, in apply_next_model
    self.lazy_model_operation(next_function, *more_models)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/apps/registry.py", line 415, in lazy_model_operation
    apply_next_model(model_class)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/apps/registry.py", line 403, in apply_next_model
    self.lazy_model_operation(next_function, *more_models)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/apps/registry.py", line 389, in lazy_model_operation
    function()
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/models/fields/related.py", line 317, in resolve_related_class
    field.do_related_class(related, model)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/models/fields/related.py", line 388, in do_related_class
    self.contribute_to_related_class(other, self.remote_field)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/parler/fields.py", line 58, in contribute_to_related_class
    self.model.contribute_translations(cls)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/parler/models.py", line 944, in contribute_translations
    raise TypeError("Translatable model {} does not appear to inherit from TranslatableModel".format(shared_model))
TypeError: Translatable model <class '__fake__.Product'> does not appear to inherit from TranslatableModel
(venv) 192:myshop Username$ 

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:2
  • Comments:10

github_iconTop GitHub Comments

14reactions
milkomedacommented, Mar 24, 2020

@HappyMiner please use latest django-parler>=2.0.1.

In addition you need to set bases manually on your migrations where these models were initially added/created.

Consider e.g. a file myapp/migrations/0001_initial.py

migrations.CreateModel(
    name='AttachmentType',
    fields=[
        ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
    ],
    options={
        'verbose_name': 'Attachment type',
        'verbose_name_plural': 'Attachment types',
    },
    bases=(parler.models.TranslatableModelMixin, models.Model),
),
migrations.CreateModel(
    name='AttachmentTypeTranslation',
    fields=[
        ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
        ('language_code', models.CharField(db_index=True, max_length=15, verbose_name='Language')),
        ('name', models.CharField(max_length=500, unique=True, verbose_name='Name')),
        ('master', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='jobportal.AttachmentType')),
    ],
    options={
        'verbose_name': 'Attachment type Translation',
        'db_table': 'jobportal_attachmenttype_translation',
        'db_tablespace': '',
        'managed': True,
        'default_permissions': (),
    },
    bases=(parler.models.TranslatedFieldsModelMixin, models.Model),
),

In particular if you changed your model e.g. AttachmentType later to be translatable and inheriting from TranslatableModel. You have to manually check the migrations for the bases attributes and add these if not present.

bases=(parler.models.TranslatableModelMixin, models.Model), for e.g. AttachmentType model

and

bases=(parler.models.TranslatedFieldsModelMixin, models.Model), for the automatically created AttachmentTypeTranslation model/table.

The documentation lacks for this information.

Feel free to contact me if you have any further questions.

11reactions
Abuba-osscommented, Feb 10, 2021

Hello,

I think I just found a problem in the documentation at: https://django-parler.readthedocs.io

I am trying to translate my model fields and when I try to follow the procedure described in the docs, all I get is: raise TypeError("Translatable model {} does not appear to inherit from TranslatableModel".format(shared_model)) TypeError: Translatable model <class '__fake__.Product'> does not appear to inherit from TranslatableModel

When I try to follow the docs, Python complains that the fields that are in translations = TranslatedFields are duplicated, so the first part of the doc does not work. No idea how to continue at this point, as this is complete road block for me.

Please find below the relevant data classes where I attempt to perform the translations.

from django.db import models
from django.urls import reverse
from parler.models import TranslatableModel, TranslatedFields

class Category(TranslatableModel):

    translations = TranslatedFields(
        name = models.CharField(max_length=200, db_index=True),
        slug = models.SlugField(max_length=200, db_index=True, unique=True))

    class Meta:

        verbose_name = 'category'
        verbose_name_plural = 'categories'

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('shop:product_list_by_category',
                       args=[self.slug])

class Product(TranslatableModel):

    translations = TranslatedFields(
        name = models.CharField(max_length=200, db_index=True),
        slug = models.SlugField(max_length=200, db_index=True),
        description = models.TextField(blank=True)
        )
    category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
    image = models.ImageField(upload_to='products/%Y/%m/%d', blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    available = models.BooleanField(default=True)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    # Commented for model translations.
    # class Meta:
    #
    #     ordering = ('name',)
    #     index_together = (('id', 'slug'),)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('shop:product_detail', args=[self.id, self.slug])

Related admin classes:

from django.contrib import admin
from .models import Category, Product
from parler.admin import TranslatableAdmin

@admin.register(Category)
class CategoryAdmin(TranslatableAdmin):
    list_display = ['name', 'slug']

    def get_prepopulated_fields(self, request, obj=None):
        return {'slug': ('name',)}

@admin.register(Product)
class ProductAdmin(TranslatableAdmin):
    list_display = ['name', 'slug', 'price', 'available', 'created', 'updated']
    list_filter = ['available', 'created', 'updated']

    list_editable = ['price', 'available']

    def get_prepopulated_fields(self, request, obj=None):
        return {'slug': ('name',)}
(venv) 192:myshop Username$ python manage.py makemigrations shop --name "add_translation_model"
Traceback (most recent call last):
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/parler/models.py", line 942, in contribute_translations
    base = shared_model._parler_meta
AttributeError: type object 'Product' has no attribute '_parler_meta'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "manage.py", line 21, in <module>
    main()
  File "manage.py", line 17, in main
    execute_from_command_line(sys.argv)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/core/management/__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/core/management/base.py", line 328, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/core/management/base.py", line 369, in execute
    output = self.handle(*args, **options)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/core/management/base.py", line 83, in wrapped
    res = handle_func(*args, **kwargs)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/core/management/commands/makemigrations.py", line 168, in handle
    migration_name=self.migration_name,
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/autodetector.py", line 43, in changes
    changes = self._detect_changes(convert_apps, graph)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/autodetector.py", line 128, in _detect_changes
    self.old_apps = self.from_state.concrete_apps
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/state.py", line 213, in concrete_apps
    self.apps = StateApps(self.real_apps, self.models, ignore_swappable=True)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/state.py", line 272, in __init__
    self.render_multiple([*models.values(), *self.real_models])
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/state.py", line 307, in render_multiple
    model.render(self)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/state.py", line 578, in render
    return type(self.name, bases, body)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/models/base.py", line 320, in __new__
    new_class._meta.apps.register_model(new_class._meta.app_label, new_class)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/migrations/state.py", line 338, in register_model
    self.do_pending_operations(model)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/apps/registry.py", line 424, in do_pending_operations
    function(model)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/apps/registry.py", line 403, in apply_next_model
    self.lazy_model_operation(next_function, *more_models)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/apps/registry.py", line 415, in lazy_model_operation
    apply_next_model(model_class)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/apps/registry.py", line 403, in apply_next_model
    self.lazy_model_operation(next_function, *more_models)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/apps/registry.py", line 389, in lazy_model_operation
    function()
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/models/fields/related.py", line 317, in resolve_related_class
    field.do_related_class(related, model)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/django/db/models/fields/related.py", line 388, in do_related_class
    self.contribute_to_related_class(other, self.remote_field)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/parler/fields.py", line 58, in contribute_to_related_class
    self.model.contribute_translations(cls)
  File "/Users/Username/Projects/Python/Django/Django2ByExample/myshop/venv/lib/python3.7/site-packages/parler/models.py", line 944, in contribute_translations
    raise TypeError("Translatable model {} does not appear to inherit from TranslatableModel".format(shared_model))
TypeError: Translatable model <class '__fake__.Product'> does not appear to inherit from TranslatableModel
(venv) 192:myshop Username$ 

I had the same problem and i had change the migrations field of the translation
from : bases=(parler.models.TranslatableModelMixin, models.Model), to : bases=(parler.models.TranslatableModel, models.Model), and it worked perfectly… it should when you do it that way.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Making existing fields translatable(Django) - Stack Overflow
I am trying to translate already existing fields on a model class. I got stuck at the very first step, which is subclassing...
Read more >
Making existing fields translatable - django-parler
The following guide explains how to make existing fields translatable, and migrate the data from the old fields to translated fields.
Read more >
Unable to change non-translatable field value on ... - Drupal
My issue is about the original (EN) form. The new option 'Hide non translatable fields on translation forms' mentioned at https://www.drupal.org ...
Read more >
Translate Sites Built with Advanced Custom Fields (ACF)
In case you need to set translation preferences for existing fields, go to WPML → Settings and scroll down to the Custom Fields...
Read more >
Translate a webpage in Safari on Mac - Apple Support
If the webpage can be translated, the Smart Search field displays the ... You may be able to make more languages available in...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found