I have a Django model like this:
class Sections(models.Model):
section_id = models.CharField(max_length=127, null=True, blank=True)
title = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
class Risk(models.Model):
title = models.CharField(max_length=256, null=False, blank=False)
section = models.ForeignKey(Sections, related_name='risks')
class Actions(models.Model):
title = models.CharField(max_length=256, null=False, blank=False)
section = models.ForeignKey(Sections, related_name='actions')
And serializers like that :
class RiskSerializer(serializers.ModelSerializer):
class Meta:
model = Risk
fields = ('id', 'title',)
class ActionsSerializer(serializers.ModelSerializer):
class Meta:
model = Actions
fields = ('id', 'title',)
class RiskActionPerSectionsSerializer(serializers.ModelSerializer):
risks = RiskSerializer(many=True, read_only=True)
actions = ActionsSerializer(many=True, read_only=True)
class Meta:
model = Sections
fields = ('section_id', 'risks', 'actions')
depth = 1
When accessing the RiskActionPerSectionSerializer over a view, I get the following output:
[
{
"actions": [
{
"id": 2,
"title": "Actions 2"
},
{
"id": 1,
"title": "Actions 1"
}
],
"risks": [
{
"id": 2,
"title": "Risk 2"
},
{
"id": 1,
"title": "Risk 1"
}
],
"section_id": "section 1"
}
.....
]
It s fine but I would prefer to have that :
{
"section 1": {
"risks": [
{
"id": 2,
"title": "Risk 2"
},
{
"id": 1,
"title": "Risk 1"
}
],
"actions": [
{
"id": 2,
"title": "Actions 2"
},
{
"id": 1,
"title": "Actions 1"
}
]
}
}
How can I do that with Django Rest Framework ?
You could override to_representation() method of your serializer:
class RiskActionPerSectionsSerializer(serializers.ModelSerializer):
class Meta:
model = Sections
fields = ('section_id', 'risks', 'actions')
depth = 1
def to_representation(self, instance):
response_dict = dict()
response_dict[instance.section_id] = {
'actions': ActionsSerializer(instance.actions.all(), many=True).data,
'risks': RiskSerializer(instance.risks.all(), many=True).data
}
return response_dict
Related
I want to sort by user-defined serializer field, all fields that defined in Serializer class can be sorted except primary key of the model, so I must assign ordering_fields into Class-Based View to solve sort by primary key problem.
views.py
from rest_framework_json_api.views import viewsets
from .serializers import ConjunctionSerializer
from .models import Conjunction
class ConjunctionViewSet(viewsets.ModelViewSet):
queryset = Conjunction.objects.all()
serializer_class = ConjunctionSerializer
permission_classes = [permissions.AllowAny]
ordering_fields = '__all__'
def get_queryset(self):
queryset = super().get_queryset()
report_pk = self.kwargs.get('report_pk')
if report_pk is not None:
queryset = queryset.filter(report__pk=report_pk)
return queryset
serializers.py
from .models import Conjunction
from rest_framework_json_api import serializers, relations
class ConjunctionSerializer(serializers.HyperlinkedModelSerializer):
norad = serializers.IntegerField(source='satellite.norad_cat_id', read_only=True)
name = serializers.CharField(source='satellite.satellite_name', read_only=True)
primary_object = CoordinateSerializer(read_only=True)
secondary_object = CoordinateSerializer(read_only=True)
class Meta:
model = Conjunction
fields = '__all__'
models.py
class SatelliteCategory(models.Model):
class Meta:
managed = False
db_table = 'satellite_category'
ordering = ['norad_cat_id']
norad_cat_id = models.IntegerField(primary_key=True)
object_type = models.CharField(max_length=255, null=True)
satellite_name = models.CharField(max_length=255, null=True)
period = models.FloatField(null=True)
inclination = models.FloatField(null=True)
apogee = models.FloatField(null=True)
perigee = models.FloatField(null=True)
rcs_size = models.CharField(max_length=255, null=True)
tle_line1 = models.CharField(max_length=255, null=True)
tle_line2 = models.CharField(max_length=255, null=True)
last_updated = models.DateTimeField(max_length=6, default=timezone.now)
class Conjunction(models.Model):
class Meta:
managed = False
db_table = 'conjunction'
ordering = ['tca']
conjunction_id = models.IntegerField(primary_key=True)
tca = models.DateTimeField(max_length=3, null=True)
missdt = models.FloatField(null=True)
probability = models.FloatField(null=True)
prob_method = models.CharField(max_length=45, null=True)
satellite = models.OneToOneField(SatelliteCategory, to_field='norad_cat_id', db_column='norad', null=True, on_delete=models.DO_NOTHING)
doy = models.FloatField(null=True)
ephe_id = models.IntegerField(null=True)
primary_object = models.OneToOneField(Coordinate, db_column='pri_obj', related_name='primary_object', null=True, on_delete=models.DO_NOTHING)
secondary_object = models.OneToOneField(Coordinate, db_column='sec_obj', related_name='secondary_object', null=True, on_delete=models.DO_NOTHING)
report = models.ForeignKey(Report, related_name='conjunctions', related_query_name='conjunction', null=True, on_delete=models.DO_NOTHING)
probability_foster = models.FloatField(null=True)
probability_patera = models.FloatField(null=True)
probability_alfano = models.FloatField(null=True)
probability_chan = models.FloatField(null=True)
This is the URL that can do the sorting of relational serializer field.
http://127.0.0.1:8000/api/reports/838/conjunctions/?sort=satellite.norad_cat_id
http://127.0.0.1:8000/api/reports/838/conjunctions/?sort=satellite.satellite_name
PS: if ordering_fields = '__all__' is set in Class-Based View in views.py, these URLs will give an error
ValidationError at /api/reports/838/conjunctions/
[ErrorDetail(string='invalid sort parameter: satellite.norad_cat_id', code='invalid')]
and
ValidationError at /api/reports/838/conjunctions/
[ErrorDetail(string='invalid sort parameter: satellite.satellite_name', code='invalid')]
This is the URL that I expected to use this.
http://127.0.0.1:8000/api/reports/838/conjunctions/?sort=norad
http://127.0.0.1:8000/api/reports/838/conjunctions/?sort=name
but it gives me an error.
ValidationError at /api/reports/838/conjunctions/
[ErrorDetail(string='invalid sort parameter: norad', code='invalid')]
and
ValidationError at /api/reports/838/conjunctions/
[ErrorDetail(string='invalid sort parameter: name', code='invalid')]
My expected output (no difference in object structure, just data sort and ordering)
{
"links": {
"first": "http://127.0.0.1:8000/api/reports/838/conjunctions/?page%5Bnumber%5D=1",
"last": "http://127.0.0.1:8000/api/reports/838/conjunctions/?page%5Bnumber%5D=11",
"next": "http://127.0.0.1:8000/api/reports/838/conjunctions/?page%5Bnumber%5D=2",
"prev": null
},
"data": [
{
"type": "Conjunction",
"id": "78622",
"attributes": {
"norad": 41128,
"name": "NOAA 16 DEB",
"primary_object": {
"x": -32.1790185245947,
"y": 1345.4003381770174,
"z": 7068.234931820495,
"x_dot": 6.236045253937126,
"y_dot": -4.125312219767719,
"z_dot": 0.8121050229582962
},
"secondary_object": {
"x": -36.01819857738044,
"y": 1344.215020772888,
"z": 7061.954966352828,
"x_dot": 6.242581845810764,
"y_dot": 4.137908135793502,
"z_dot": -0.7619825840439509
},
"tca": "2023-01-26T12:23:11.191000Z",
"missdt": 7.455350233311262,
"probability": 3.745886772453588e-07,
"prob_method": "MaxMethod",
"doy": 23024.59659221,
"ephe_id": null,
"probability_foster": 7.791916054339528e-16,
"probability_patera": 0.0,
"probability_alfano": 0.0,
"probability_chan": 0.0
},
"relationships": {
"satellite": {
"data": {
"type": "SatelliteCategory",
"id": "41128"
},
"links": {
"related": "http://127.0.0.1:8000/api/satellite_categories/41128/"
}
},
"report": {
"data": {
"type": "Report",
"id": "838"
},
"links": {
"related": "http://127.0.0.1:8000/api/reports/838/"
}
}
},
"links": {
"self": "http://127.0.0.1:8000/api/conjunctions/78622/"
}
},
# more data...
{
"type": "Conjunction",
"id": "78631",
"attributes": {
"norad": 29918,
"name": "FENGYUN 1C DEB",
"primary_object": {
"x": 149.7916062466496,
"y": 1111.1660784972553,
"z": -7123.690377416994,
"x_dot": 7.476011356717345,
"y_dot": 0.5998462890255432,
"z_dot": 0.25074668689433954
},
"secondary_object": {
"x": 155.26645409251904,
"y": 1111.1736632728805,
"z": -7125.616154255772,
"x_dot": 7.367559835506688,
"y_dot": -1.4044637350807834,
"z_dot": -0.0672452654049058
},
"tca": "2023-01-26T21:43:34.430000Z",
"missdt": 5.80367408604377,
"probability": 3.530097857752286e-07,
"prob_method": "MaxMethod",
"doy": 23025.68032082,
"ephe_id": null,
"probability_foster": 1.060944978095755e-20,
"probability_patera": 8.484424295716666e-47,
"probability_alfano": 2.1338065891406005e-114,
"probability_chan": 3.2889981650941177e-165
},
"relationships": {
"satellite": {
"data": {
"type": "SatelliteCategory",
"id": "29918"
},
"links": {
"related": "http://127.0.0.1:8000/api/satellite_categories/29918/"
}
},
"report": {
"data": {
"type": "Report",
"id": "838"
},
"links": {
"related": "http://127.0.0.1:8000/api/reports/838/"
}
}
},
"links": {
"self": "http://127.0.0.1:8000/api/conjunctions/78631/"
}
}
],
"meta": {
"pagination": {
"page": 1,
"pages": 11,
"count": 107
}
}
}
the problem is this, i've created a snippet and i want to expose it but i don't know how to serialize nested data. here my code:
models.py
#register_snippet
class TeamMember(ClusterableModel):
name = models.CharField(max_length=80)
description = models.CharField(max_length=80)
panels = [
FieldPanel('name'),
InlinePanel('tasks', label=('Tasks')),
]
class Task(Orderable):
team_member = ParentalKey('adm.TeamMember', related_name="tasks")
task_name = models.CharField(max_length=80)
endpoints.py
class TeamMemberAPIEndpoint(BaseAPIViewSet):
model = TeamMember
body_fields = BaseAPIViewSet.body_fields + [
'name',
'description',
'tasks',
]
listing_default_fields = BaseAPIViewSet.listing_default_fields = [
'name',
'description',
'tasks',
]
the result is:
"items": [
{
"name": "python team",
"description": "",
"tasks": [
{
"id": 1,
"meta": {
"type": "adm.Task"
}
},
{
"id": 2,
"meta": {
"type": "adm.Task"
}
}
]
}
how can i resolve this problem?
You have several ways to get the nested data.
provide a dedicated serializer for the nested items within the API Endpoint.
the wagtail way. Define additional api properties.
from rest_framework import serializers
from wagtail.api import APIField
class Task(Orderable):
team_member = ParentalKey('adm.TeamMember', related_name="tasks")
task_name = models.CharField(max_length=80)
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = (
"id",
"task_name",
)
#register_snippet
class TeamMember(ClusterableModel):
name = models.CharField(max_length=80)
description = models.CharField(max_length=80)
panels = [
FieldPanel('name'),
InlinePanel('tasks', label=('Tasks')),
]
api_fields = [
APIField("tasks", serializer=TaskSerializer(many=True)),
]
the response looks like this:
{
"meta": {
"total_count": 1
},
"items": [
{
"name": "Member 1",
"tasks": [
{
"id": 1,
"task_name": "Do this"
},
{
"id": 2,
"task_name": "Do that"
}
]
}
]
}
I've started learning django recently and can't seem to figure out how to get the data I want. I'm looking to build an object that can give me each part name and all of the reports of that part and then get the report data but only for the part I'm currently on
This is an example of the data I would want.
{
"count": 2536,
"next": "http://127.0.0.1:8000/esd/salesreportsdetail2/?page=2",
"previous": null,
"results": [
{
"id": 2,
"name": "A0012",
"sales_report_parts": [
{
"id": 5,
"date": "2021-08-31T00:00:00Z",
"sales_report_items": [
{
"quantity": 1,
"site": "FBA"
},
{
"quantity": 3,
"site": "Vendor"
},
{
"quantity": 4,
"site": "Main"
}
]
}
]
}
]
}
But instead, I keep getting all the sales report items for each item.
{
"count": 2536,
"next": "http://127.0.0.1:8000/esd/salesreportsdetail2/?page=2",
"previous": null,
"results": [
{
"id": 2,
"name": "A0012",
"sales_report_parts": [
{
"id": 5,
"date": "2021-08-31T00:00:00Z",
"sales_report_items": [
{
"quantity": 1,
"site": "FBA"
},
{
"quantity": 3,
"site": "Vendor"
},
{
"quantity": 4,
"site": "Main"
},
{
"quantity": 45,
"site": "FBA"
},
{
"quantity": 102,
"site": "Vendor"
},
{
"quantity": 161,
"site": "Main"
},
{
"quantity": 7,
"site": "FBA"
},... and so on gets me all of the data
Below are my models, views, and serializer. Any help would be greatly appreciated thanks in advance!
models.py
class SalesReport(models.Model):
month = models.PositiveSmallIntegerField(null=False)
year = models.PositiveSmallIntegerField(null=False)
date = models.DateTimeField(null=False)
updated_at = models.DateTimeField(null=True)
parts = models.ManyToManyField(
"Part", through="SalesReportItem", related_name="sales_report_parts"
)
class SalesReportItem(models.Model):
part = models.ForeignKey(
"Part", on_delete=models.CASCADE, related_name="sales_report_part"
)
quantity = models.IntegerField(null=False)
site = models.CharField(max_length=10, choices=SITE_CHOICES, null=False)
sales_report = models.ForeignKey(
SalesReport, on_delete=models.CASCADE, related_name="sales_report_items"
)
class Part(models.Model):
id = models.IntegerField(primary_key=True, null=False)
name = models.CharField(max_length=200, null=False)
updated_at = models.DateTimeField(null=True)
crea`enter code here`ted_at = models.DateTimeField(null=True)
sales_reports = models.ManyToManyField(
SalesReport, through="SalesReportItem", related_name="part_sales_report"
)
views.py
class SalesReportDetailViewSet(ModelViewSet):
queryset = SalesReport.objects.prefetch_related("sales_report_items__part").all()
serializer_class = SalesReportDetailSerializer
class SalesReportDetailViewSet2(ModelViewSet):
queryset = Part.objects.prefetch_related(
"sales_report_parts__sales_report_items"
).all()
serializer_class = PartDetailSerializer
pagination_class = TestPagination
serializers.py
class SalesReportItemDetailSerializer2(serializers.ModelSerializer):
class Meta:
model = SalesReportItem
fields = ["quantity", "site"]
class SalesReportDetailSerializer2(serializers.ModelSerializer):
sales_report_items = SalesReportItemDetailSerializer2(many=True)
class Meta:
model = SalesReport
fields = ["id", "date", "sales_report_items"]
class PartDetailSerializer(serializers.ModelSerializer):
sales_report_parts = SalesReportDetailSerializer2(many=True)
class Meta:
model = Part
fields = ["id", "name", "sales_report_parts"]
I'm working on building a tree-like hierarchical database system using Django Rest Framework and django-polymorphic-tree. I have two models- BaseTreeNode and DescriptionNode (the later one is derived from BaseTreeNode). Specifically, here's my models.py:
class BaseTreeNode(PolymorphicMPTTModel):
parent = PolymorphicTreeForeignKey('self', blank=True, null=True, related_name='children', verbose_name=_('parent'))
title = models.CharField(_("Title"), max_length=200)
def __str__(self):
return "{}>{}".format(self.parent, self.title)
class Meta(PolymorphicMPTTModel.Meta):
verbose_name = _("Tree node")
verbose_name_plural = _("Tree nodes")
# Derived model for the tree node:
class DescriptionNode(BaseTreeNode):
description = models.CharField(_("Description"), max_length=200)
class Meta:
verbose_name = _("Description node")
verbose_name_plural = _("Description nodes")
So, each title field (belonging to BaseTreeNode) has an associated description field (belonging to DescriptionNode) with it.
Now, all I want to have is a JSON that returns a nested representation of my entire tree.
For now, I have only defined a simple serializer with a recursive field.
My serializers.py
from rest_framework_recursive.fields import RecursiveField
class DescriptionNodeSerializer(serializers.ModelSerializer):
class Meta:
model = DescriptionNode
fields = ('description',)
class BaseTreeNodeSerializer(serializers.ModelSerializer):
subcategories = serializers.ListSerializer(source="children",child=RecursiveField())
class Meta:
model = BaseTreeNode
fields = ('id', 'title', 'subcategories')
Which gives me (for BaseTreeNodeSerializer only):
[
{
"id": 1,
"title": "Apple",
"subcategories": [
{
"id": 2,
"title": "Contact Person",
"subcategories": []
},
{
"id": 3,
"title": "Sales Stage",
"subcategories": [
{
"id": 4,
"title": "Suspecting",
"subcategories": [
{
"id": 5,
"title": "Contact verification",
"subcategories": []
}
]
},
{
"id": 6,
"title": "Prospecting",
"subcategories": [
{
"id": 7,
"title": "Client Detail",
"subcategories": []
}
]
}
]
},
{
"id": 9,
"title": "Medium",
"subcategories": [
{
"id": 10,
"title": "Status",
"subcategories": []
}
]
},
{
"id": 13,
"title": "Remainder",
"subcategories": []
}
]
}
]
My question is, how can I include the description field (from the derived model) which is associated with every single title field (from the BaseTreeNode model) in the hierarchy?
Something like:
... {
"id": 5,
"title": "Contact verification",
"description": "Verified"
"subcategories": []
} ...
The Corresponding Model would be as follows:
class DescriptionNode(BaseTreeNode):
basetreenode = models.OneToOneField(BaseTreeNode, related_name="base_tree")
description = models.CharField(_("Description"), max_length=200)
class Meta:
verbose_name = _("Description node")
verbose_name_plural = _("Description nodes")
Serializer would be as follows:
from rest_framework_recursive.fields import RecursiveField
class BaseTreeNodeSerializer(serializers.ModelSerializer):
description = serializers.SerializerMethodField()
subcategories = serializers.ListSerializer(source="children",child=RecursiveField())
class Meta:
model = BaseTreeNode
fields = ('id', 'title', 'description', 'subcategories')
def get_description(self, obj):
return obj.base_tree.description #base_tree is related name of basetreenode field
I have model Product:
class Product(TranslatableModel):
name = models.CharField(max_length=255, unique=True)
translations = TranslatedFields(
description=models.TextField(),
)
and in administration on product detail I have tabs with languages. For example tabs EN, CZ, each includes disctiption. So PUT request looks like:
{
'product': '1',
'id': 1,
'name': 'Name',
'translations': {
'cz': {'desctiption': 'Description cz'},
'en': {'desctiption': 'Description en'}
}
}
I founded in django-hvad TranslationsMixin that allows me to do that request.
in serializers I have:
class ProductTranslationSerializer(serializers.ModelSerializer):
class Meta:
exclude = ['description']
class ProductSerializer(TranslationsMixin, serializers.ModelSerializer):
class Meta:
model = Product
translations_serializer = ProductTranslationSerializer
fields = (
'name',
'description',
)
Question is how will looks ModelViewSet for this request? Can I choose language like 'language_code=en', filter that query and get something like:
[
{
id: 1
name: "name"
descritpion: "descritpion"
},
....
]
Thank you!
the most likely way i achieve is:
models.py
class Product(TranslatableModel):
category = models.ForeignKey('product.ProductCategory',
related_name='product_category',
null=True,
on_delete=models.SET_NULL,
verbose_name=u'category')
cover = models.ImageField(upload_to=product_cover,
null=True,
verbose_name=u'cover')
translations = TranslatedFields(
title=models.CharField(max_length=100,
null=True,
verbose_name=u'title'),
summary=models.TextField(null=True,
verbose_name=u'summary'),
model=models.CharField(max_length=255,
null=True,
blank=True,
verbose_name=u'model'),
price=models.DecimalField(default=0.00,
max_digits=10,
decimal_places=2,
blank=True,
validators=[MinValueValidator(0)],
verbose_name=u'price'),
content=models.TextField(verbose_name=u'content'),
publish_time=models.DateTimeField(default=timezone.now,
verbose_name=u'发布publish_time')
)
view_times = models.IntegerField(default=0,
verbose_name=u'view_times ')
views.py
class ProductViewSet(ModelViewSet):
serializer_class = ProductListSerializer
def get_queryset(self):
if 'language_code' in self.request.GET:
language_code = self.request.GET.get('language_code')
queryset = Product.objects.language(language_code).order_by('-id')
else:
queryset = Product.objects.language().order_by('-id')
return queryset
serializers.py
class ProductCategorySerializer(TranslatableModelSerializer):
class Meta:
model = ProductCategory
fields = '__all__'
class ProductListSerializer(TranslatableModelSerializer):
category = ProductCategorySerializer(read_only=True)
class Meta:
model = Product
exclude = ['is_abandon', 'content', ]
urls.py
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'product', ProductViewSet, base_name='api-product')
...
result:
http://192.168.1.108/api/product/?language_code=zh-hans you get:
{
"count": 1,
"page_num": 1,
"page_no": 1,
"next": "",
"previous": "",
"results": [
{
"id": 2,
"category": {
"id": 2,
"create_time": "2017-08-10 16:49:41",
"update_time": "2017-08-18 08:56:02",
"name": "测试",
"language_code": "zh-hans"
},
"create_time": "2017-08-18 08:53:46",
"update_time": "2017-08-18 08:56:28",
"cover": "http://192.168.1.108/media/product/20170818-085346-518_59.jpg",
"view_times": 0,
"title": "标题",
"summary": "简介",
"model": null,
"price": "90.00",
"publish_time": "2017-08-18 08:53:00",
"language_code": "zh-hans"
}
]
}
http://192.168.1.108/api/product/?language_code=en you get:
{
"count": 1,
"page_num": 1,
"page_no": 1,
"next": "",
"previous": "",
"results": [
{
"id": 2,
"category": {
"id": 2,
"create_time": "2017-08-10 16:49:41",
"update_time": "2017-08-18 08:56:02",
"name": "测试",
"language_code": "zh-hans"
},
"create_time": "2017-08-18 08:53:46",
"update_time": "2017-08-18 09:00:23",
"cover": "http://192.168.1.108/media/product/20170818-085346-518_59.jpg",
"view_times": 0,
"title": "title",
"summary": "summary",
"model": "model",
"price": "91.00",
"publish_time": "2017-08-18 08:56:04",
"language_code": "en"
}
]
}
this way fk will not change language,if you want fk change language too,use:
urls.py
urlpatterns += i18n_patterns(
'''
url(r'^api/', include(router.urls)),
prefix_default_language=False,
)
change language by
http://192.168.1.108/zh-hans/api/product/
to
http://192.168.1.108/en/api/product/
your will get:
{
"count": 1,
"page_num": 1,
"page_no": 1,
"next": "",
"previous": "",
"results": [
{
"id": 2,
"category": {
"id": 2,
"create_time": "2017-08-10 16:49:41",
"update_time": "2017-08-18 08:56:02",
"name": "test",
"language_code": "en"
},
"create_time": "2017-08-18 08:53:46",
"update_time": "2017-08-18 09:00:23",
"cover": "http://192.168.1.108/media/product/20170818-085346-518_59.jpg",
"view_times": 0,
"title": "title",
"summary": "summary",
"model": "model",
"price": "91.00",
"publish_time": "2017-08-18 08:56:04",
"language_code": "en"
}
]
}
Answer from owner of django-hvad github repo #spectras:
If I understand well, you want to use a different serialized form for the collection endpoint and the item endpoint. That is, GET-1, PUT, POST would use the translations mixin, while GET-many would not.
You need two have two different serializers for this:
The one you created
another one that would be, for instance,
class ProductItemSerializer(TranslatableModelSerializer): ...
another one that would be, for instance,
class ProductItemSerializer(TranslatableModelSerializer): ...
Given that, you can add to your ModelViewSet a method that dynamically chooses the serializer class depending on request type:
class SomeModelViewSet(ModelViewSet):
# serializer_class = not needed, we use the method instead
def get_serializer_class(self):
if self.action == 'list':
return ProductItemSerializer
return ProductSerializer
An alternate method, perhaps easier to use on the Javascript side, would be to make 2 viewsets for the Product model, a read-write one being translation aware (using ProductSerializer) and a read-only one not translation aware, using (ProductItemSerializer).
In the same vein, I usually only have translation-unaware serializers and add a /api/product/details/ endpoint that is translation-aware. This way, I only have to handle the complexity of a dict object when going into edit/detailed mode on the client side.