django-parler translations for abstract model - python

My django app must be translatable, static pages and models too. For translating models I'm using django-parler app. This works fine, but for simple models, I mean, models that doesn't inherits from an abstract model class.
Let's say that we have a Vehicle abstract model
class Vehicle(TranslatableModel):
translations = TranslatedFields(
description=models.CharField(max_length=100)
)
class Meta:
abstract = True
and a child model which is Car:
class Car(Vehicle)
"""..."""
This raised me this error: TypeError: Can't create TranslatedFieldsModel for abstract class Vehicle.
I'd like still using django model inheritance. So, what can I do for translating my models using django-parler, it support translations for abstract models or I'll need to use another app to achieve this, in that case any suggestion on any?

The problem is, parler implicitly creates an extra db table for the translations which has a ForeignKey to the model that the translated fields are declared on. You cannot have a FK to an abstract model because it does not have its own db table. What if you have two models subclassing this abstract model? Which table is the translation table's FK pointing to?
You could try to implement the translatable fields outside of your model if you want to share the same translatable fields across models and still be relatively DRY:
vehicle_translations = TranslatedFields(
description=models.CharField(max_length=100)
)
class Car(TranslatableModel):
translations = vehicle_translations

The best solution is to use TranslatedField as explained in the docs: https://django-parler.readthedocs.io/en/latest/api/parler.fields.html#the-translatedfield-class

Related

DRF serialisation issue: combining django-simple-history and django-polymorphic

I am using regular Django models but have now started to incorporate a polymorphic model into my DRF REST API project using django-polymorphic and rest-polymorphic. I am also using django-simple-history to track changes to entries in my database. This all works fine for normal models and polymorphic models without a HistoricalRecords() field, but errors when trying to interact with any polymorphic model that has a HistoricalRecords() field:
django.core.exceptions.FieldError: Cannot resolve keyword 'material_ptr_id' into field.
In my serialiser for the polymorphic models, I use the following technique to serialise the history field:
class HistoricalRecordField(serializers.ListField):
child = serializers.DictField()
def to_representation(self, data):
return super().to_representation(data.values())
class ItemSerializer(serializers.ModelSerializer):
history = HistoricalRecordField(read_only=True)
class Meta:
model = Item
fields = ('history')
Is there a way to exclude the material_ptr_id field from being taken into account by the serialiser as it is not part of the parent model but only the child models? Or are there any obvious other mistakes I am making? Thanks for any help with this.

Recombining multiple inheritance in Django models

Been using Django Polymorphic to help me with complex inheritance patterns in my Django model.
I'm having an issue where I need to have a concrete base model (because it needs to have a ForeignKey to itself), and then have multiple models inherit from it, with eventually some model inheriting from multiple of those. The issue is that I'm getting a E005 error:
app.NamedWeightedModel: (models.E005) The field 'basemodel_ptr' from
parent model 'app.namedmodel' clashes with the field 'basemodel_ptr'
from parent model 'app.massmodel'.
The simple example that triggers this is shown below:
from django.db import models
from polymorphic.models import PolymorphicModel
class BaseModel(PolymorphicModel):
parent = models.ForeignKey('self')
class NamedModel(BaseModel):
name = models.CharField(max_length=32)
class MassModel(BaseModel):
weight = models.FloatField()
class NamedWeightedModel(NamedModel, MassModel):
pass
Is there a better way to handle this? Or a standard approach?
My real model is much more complex (an implementation of the UML spec), and I would like to be able to use multiple inheritance (ideally through Polymorphic) to make things easier.
I've considered making any multiple inheritance models be single inheritance with all additional inherited models mapped as OneToOneFields, but this negates some of the nice things that polymorphic does.
Any help you can provide would be greatly appreciated.

Django REST framework serializing model combinations

I'm programming an online game with a JavaScript client and I use Django REST framework for the backend. I have written a quest system for it.
My quests objects are dynamically created from a django model QuestTemplate which stores information like the Quest desription and the titel (the part that is the same for every user); and another model QuestHistory where I put the information about the state of quest for a certain user: so it has fields like user and completed. They also have some nested objects: Tasks and, Rewards which are created in a similar way to the the Quest objects.
I added a pure python class Quest that combines all the fields of those models, and then I wrote a Serializer for this class. The drawback is that I have to define all the fields again in the QuestSerializer
I have seen that for the ModelSerializer you can use a inner class Meta where you specifiy the model and . Is there also a way to do this with a normal python class instead of a model (with my Quest class).
http://www.django-rest-framework.org/api-guide/serializers#specifying-nested-serialization
Or:
Is it possible to specify more than one model in this inner class, so that it takes fields from my model QuestTemplate and some other fields from my model QuestHistory?
(I'm also not sure about whether this structure makes sense and asked about it here: django models and OOP design )
In the class Meta of the ModelSerializer you can specify only one Model as far as I know. However there are possibilities to add custom fields to the serializer. In your case you could maybe try with:
custom_field = serializers.SerializerMethodField('some_method_in_your_serializer')
You should add the method to your serializer like this:
def some_method_in_your_serializer(self, obj):
# here comes your logic to get fields from other models, probably some query
return some_value # this is the value that comes into your custom_field
And add the custom_field to fields in the class Meta:
class Meta:
fields = ('custom_field', 'all_other_fields_you_need')
Take a look in the documentation about SerializerMethodField for deeper understanding.

Django Application: Foreign Key pointing to an abstract class

I am trying to design a framework to help implement complex web flows. The framework would provide with abstract classes which could inherited and implemented by the sub-apps. Now, as you can see my abstract class Action has a Foreign Key with Stage. Since, it has a foreignkey it could not be made abstract due to which it would have its own table. So, If I have 2 implementing application then my first application can see all the Stages for itself as well as for the other application. I could make some tweaks in the queries to avoid this. But I want to know if there is solution so, that my implementing Action class could directly point to the Inheriting Stage class.
parent_app/models.py
class Stage(models.Model):
name = models.CharField(max_length=255)
class Action(models.Model):
stage = models.ForeignKey(Stage)
class Meta:
abstract = True
sub_app1/models.py
class StageImpl1(Stage):
pass
class ActionImpl1(Action):
...
sub_app2/models.py
class StageImpl2(Stage):
pass
class ActionImpl2(Action):
...
Update:
The current situation is:
ActionImpl1 has a foreignkey to Stage
What I would to have is:
ActionImpl1 to have a foreignkey with StageImpl1
An abstract class is a class that doesn't exist. It is used as a basis for other classes. It is never never ever initialized.
Something that does not exist cannot have a foreign key pointing at it!
Something to look at, if you want to have a way to point at several different kinds of classes: generic relations. This is Django's build-in way to have something that looks like a foreign key point at a number of different objects.
It is imposible.
Think what would happen to all the classes with a foreign key pointing A if A is abtract and several classes inherit from A.
I dont know your requirements but I maybe you should consider using multitable inheritance, and point the FK to the parent table.
From the Django documentation:
Multi-table inheritance
https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance
The second type of model inheritance supported by Django is when each
model in the hierarchy is a model all by itself. Each model
corresponds to its own database table and can be queried and created
individually. The inheritance relationship introduces links between
the child model and each of its parents (via an automatically-created
OneToOneField). For example:

Django model class inheritance - default fields and overrides

I'm attempting to have inherited class templates, so that all my models have certain default fields, and all have default overrides for a few functions like save_model()
If I do it like this, I get the overrides, but then have to go and manually set meta data like db_table...
class ModelExtension(models.Model):
altered_by = models.CharField(max_length=64)
class SomeModel(ModelExtension):
class Meta:
db_table = 'app_somemodel'
fields = models.CharField()
...
Is there a way to get this kind of inheritance working right? So far I either have to do extra work to compensate for the drawbacks of this approach, or I'm plagued by MRO errors.2
What's an MRO error? Have you read the django docs on model inheritance? You can either have Abstract Base Classes, Multi-table inheritance, or proxy models.
http://docs.djangoproject.com/en/stable/topics/db/models/#abstract-base-classes
What you've done there is a multi-table inheritance - there's a hidden OneToOneField connecting your two models. I don't know why you think you need the db_table specified - it shouldn't be.
If you are never going to have objects of bare class ModelExtension then you want abstract base classes. In this case you put abstract=True in the Meta section, and then all the fields from the base class are added to the table for the child class. The docs explain it better than I can here.
I often find myself starting to do it one way and then flipping back and forth several times as I think more about my database structure....
If you just want to add new functionality to a model without changing its fields, use a proxy model!

Categories

Resources