I want to create a seralizer with 3 models and many to many relationship:
# models.py
class Permission(models.Model):
permission_name = models.CharField(max_length=20)
class Feature(models.Model):
feature_name = models.CharField(max_length=40)
class Role(models.Model):
name = models.CharField(max_length=40)
permissions = models.ManyToManyField(Permission, through='RolePermission')
features = models.ManyToManyField(Feature, through='RolePermission')
class RolePermission(models.Model):
role = models.ForeignKey(Role, on_delete=models.CASCADE)
permission = models.ForeignKey(Permission, on_delete=models.CASCADE)
feature = models.ForeignKey(Feature, on_delete=models.CASCADE)
Sample data:
PERMISSION:
1 - add
2 - edit
3 - remove
4 - view
FEATURE:
1 - user
2 - device
ROLE:
1 - ROLE1
2 - ROLE2
data i want to response from view:
[
{
"id": 1,
"name": "ROLE1",
"features": [
{
"id": 1,
"name": "user",
"permissions": [
{
"id": 1,
"name": "add"
},
{
"id": 2,
"name": "edit"
},
{
"id": 3,
"name": "remove"
},
{
"id": 4,
"name": "view"
}
]
},
{
"id": 2,
"name": "device",
"permissions": [
{
"id": 4,
"name": "view"
}
]
}
]
},
{
"id": 2,
"name": "ROLE2",
"features": [
{
"id": 1,
"name": "user",
"permissions": [
{
"id": 4,
"name": "view"
}
]
},
{
"id": 2,
"name": "device",
"permissions": [
{
"id": 4,
"name": "view"
}
]
}
]
}
]
But i cant write the serializer correctly?
Any help is appreciated.
I guess you should use this code, maybe there is different field_names
class PermisionSerializer(serializers.ModelSerializer):
class Meta:
model = Permission
fields = ('name', )
class FeatureSerializer(serializers.ModelSerializer):
permissions = PermisionSerializer(many=True)
class Meta:
model = Feature
fields = ('name', 'permissions', )
class RoleSerializer(serializers.ModelSerializer):
features = FeatureSerializer(many=True)
class Meta:
model = Role
fields = ('name', 'features', )
Related
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 am new to Django rest framework.i am trying to get child model records to the parent model as a field so that all the RefreshmentImage models records are available in games_sports list.i have posted sample code.
model.py
class Refreshment(models.Model):
title = models.CharField(max_length=200, unique=True)
type = models.CharField(max_length=200)
charges = models.DecimalField(max_digits=12, decimal_places=2, help_text="Charges per hour")
class RefreshmentImage(models.Model):
refreshment = models.ForeignKey(Refreshment, on_delete=models.CASCADE)
image = models.FileField(upload_to="refreshment_image/", null=True, blank=True)
serializers.py
class EntertainmentSerializer(serializers.ModelSerializer):
class Meta:
model = Refreshment
fields = '__all__'
class RefreshmentImageSerializer(serializers.ModelSerializer):
refreshment = EntertainmentSerializer(read_only=True, many=True)
class Meta:
model = RefreshmentImage
fields = '__all__'
views.py
def all_games_sports(request):
entertainment = Refreshment.objects.all()
serialize = EntertainmentSerializer(instance=entertainment,many=True)
serial = RefreshmentImageSerializer(instance=entertainment,many=True)
main = {'status': True, 'code': CODE_SUCCESSFUL, 'msg': SUCCESS, 'games_sports': serialize.data,'image':serial.data}
return HttpResponse(json.dumps(main), content_type='application/json')
what i got is like:
games_sports": [
{
"id": 1,
"title": "yyy",
"type": 1,
"charges": "500.00",
},
{
"id": 2,
"title": "xxxxx",
"type": "something",
"charges": "501.00",
}
*******
],
"image": [
{
"id": 1,
"image": null,
"date_created": "2019-03-03T08:16:15.538024+05:30"
},
**********
]
i want it to be:
games_sports": [
{
"id": 1,
"title": "yyy",
"type": 1,
"charges": "500.00",
"image": [
{
"id": 1,
"image": image_path,
"date_created": "2019-03-03T08:16:15.538024+05:30"
},
}
***********
],
Try this snippet
#serializers.py
"""I've re-arranged the order of 'RefreshmentImageSerializer' serializer and 'EntertainmentSerializer' serializer"""
class RefreshmentImageSerializer(serializers.ModelSerializer):
class Meta:
model = RefreshmentImage
fields = '__all__'
class EntertainmentSerializer(serializers.ModelSerializer):
image = RefreshmentImageSerializer(many=True, source='refreshmentimage_set')
class Meta:
model = Refreshment
fields = '__all__'
# views.py
"""Added DRF stuffs such as 'api_view' and 'Response'"""
from rest_framework.decorators import api_view
#api_view()
def all_games_sports(request):
entertainment = Refreshment.objects.all()
serialize = EntertainmentSerializer(instance=entertainment, many=True)
main = {'status': True, 'code': "CODE_SUCCESSFUL", 'msg': "SUCCESS", 'games_sports': serialize.data}
return Response(main)
{
"status": true,
"code": "CODE_SUCCESSFUL",
"msg": "SUCCESS",
"games_sports": [
{
"id": 1,
"image": [
{
"id": 1,
"image": null,
"refreshment": 1
},
{
"id": 3,
"image": "refreshment_image/jpg-icon.png",
"refreshment": 1
}
],
"title": "t1",
"type": "tt1",
"charges": "123.00"
},
{
"id": 2,
"image": [
{
"id": 2,
"image": "refreshment_image/asd.jpg",
"refreshment": 2
}
],
"title": "t2",
"type": "tt2",
"charges": "321.00"
},
{
"id": 3,
"image": [
{
"id": 4,
"image": "refreshment_image/Screenshot_from_2018-10-26_16-32-41.png",
"refreshment": 3
},
{
"id": 5,
"image": "refreshment_image/twitter.png",
"refreshment": 3
}
],
"title": "t3",
"type": "tt3",
"charges": "754.00"
}
]
}
What I've done here?
re-arranged the order of serializer to avoid not defined errors
added a new field in EntertainmentSerializer class to show the images associated with the Refreshment object
In views.py I've added DRF pieces of stuff, which is more suitable
References
#api_view() decorator
DRF's Response() class
DRF Nested Serializers
The source keyword argument
Hope this helps!!
I get a problem in Django Rest Framework.
class FeedDetailSerializer(ModelSerializer):
user = UserFeedSerializer(read_only=True)
comment_count = SerializerMethodField(default=0)
comment_list = CommentFeedSerializer(many=True, read_only=True)
class Meta:
model = Feed
fields = [
'id',
'comment_count',
'comment_list',
]
def get_comment_count(self, obj):
comment_count = Comment.objects.filter(feed=obj.id, parent__isnull=True).count()
return comment_count
This is the CommentFeedSerializer I've created:
class CommentFeedSerializer(ModelSerializer):
url = comment_detail_url
class Meta:
model = Comment
fields = [
'url',
'id',
'comment',
'posted_on',
]
With this Serializer I've done, API will render like this:
"comment_count": 2,
"comment_list": [
{
"url": "http://localhost:8000/api/v1/comments/2/",
"id": 2,
"comment": "haha",
"reply_count": 0,
"posted_on": "2017-11-24T10:23:28.353000Z"
},
{
"url": "http://localhost:8000/api/v1/comments/1/",
"id": 1,
"comment": "Good",
"reply_count": 1,
"posted_on": "2017-11-24T09:54:48.680000Z"
}
]
But this is very hard to manage. So I want to put comment_count into comment_list: commentlist like below How can I do that?
"comment_list": [
"comment_count": 2,
{
"url": "http://localhost:8000/api/v1/comments/2/",
"id": 2,
"comment": "haha",
"reply_count": 0,
"posted_on": "2017-11-24T10:23:28.353000Z"
},
{
"url": "http://localhost:8000/api/v1/comments/1/",
"id": 1,
"comment": "Good",
"reply_count": 1,
"posted_on": "2017-11-24T09:54:48.680000Z"
}
]
from django.db import models
# django user
from django.contrib.auth.models import User
class Entity(models.Model):
"""
Entity of EAV
"""
entity = models.CharField(max_length=216,
null=False, default='entity_name',
name='entity', verbose_name='Entity of EAV',
db_index=True,
unique=True
)
class Asset(models.Model):
"""
Asset of EAV
"""
asset = models.CharField(max_length=216, null=False,
default='asset', name='asset',
verbose_name='Asset of EAV'
)
entity = models.ForeignKey(to=Entity)
class Meta:
unique_together = ("asset", "entity")
class Value(models.Model):
"""
Value of EAV
"""
value = models.CharField(max_length=216,
null=False, default='value',
name='value', verbose_name='Value of EAV'
)
asset = models.ForeignKey(to=Asset)
owner = models.ForeignKey(User, verbose_name='EAV Owner', related_name='eav')
class Meta:
unique_together = ('value', 'asset', 'owner')
Serializers
class EntitySerializer(serializers.Serializer):
id = serializers.IntegerField(label='ID', read_only=True)
entity = serializers.CharField(label='Entity of EAV', max_length=216, required=False)
class AssetSerializer(serializers.Serializer):
id = serializers.IntegerField(label='ID', read_only=True)
asset = serializers.CharField(default='asset', label='Asset of EAV', max_length=216)
entity = EntitySerializer(read_only=True)
class ValueSerializer(serializers.Serializer):
id = serializers.IntegerField(label='ID', read_only=True)
value = serializers.CharField(default='value', label='Value of EAV', max_length=216)
asset = AssetSerializer(read_only=True)
owner = UserModelSerializer(read_only=True)
class EntityAssetValueSerializer(serializers.Serializer):
entity = EntitySerializer(many=True)
asset = AssetSerializer(many=True)
value = ValueSerializer(many=True)
Expected Serialization
{
"entities": [
{
"entity": "Hero",
"id": 1,
"owner": {
"name": "BatMan",
"id": "1"
},
"groups": [
{
"id": "1",
"name": "SuperHeroes Group"
}
],
"asset": [
{
"asset": "Name",
"value": "BatMan",
"asset_id": 1,
"value_id": 1
},
{
"asset": "Age",
"value": "30",
"asset_id": 1,
"value_id": 2
}
]
},
{
"entity": "Hero",
"id": 1,
"owner": {
"name": "SuperMan",
"id": "2"
},
"groups": [
{
"id": "1",
"name": "SuperHeroes Group"
}
],
"asset": [
{
"asset": "Name",
"value": "SuperMan",
"asset_id": 1,
"value_id": 3
},
{
"asset": "Age",
"value": "30",
"asset_id": 1,
"value_id": 4
}
]
},
{
"entity": "Villian",
"id": 1,
"owner": {
"name": "Joker",
"id": "3"
},
"groups": [
{
"id": "2",
"name": "SuperVillians Group"
}
],
"asset": [
{
"asset": "Name",
"value": "Joker",
"asset_id": 3,
"value_id": 4
},
{
"asset": "Age",
"value": "30",
"asset_id": 4,
"value_id": 5
}
]
},
{
"entity": "Person",
"id": 1,
"owner": {
"name": "Puny Human",
"id": "3"
},
"groups": [
{
"id": "2",
"name": "Humans Group"
}
],
"asset": [
{
"asset": "Name",
"value": "Human Being",
"asset_id": 5,
"value_id": 6
},
{
"asset": "Age",
"value": "30",
"asset_id": 6,
"value_id": 7
}
]
}
]
}
Achieved Serialization
{
"eav": [
{
"id": 1,
"value": "Human",
"asset": {
"id": 1,
"asset": "Name",
"entity": {
"id": 1,
"entity": "Human"
}
},
"owner": {
"id": 1,
"username": "PunyHuman"
}
},
{
"id": 2,
"value": "26",
"asset": {
"id": 2,
"asset": "Age",
"entity": {
"id": 1,
"entity": "Human"
}
},
"owner": {
"id": 1,
"username": "PunyHuman"
}
},
{
"id": 3,
"value": "26",
"asset": {
"id": 3,
"asset": "Age",
"entity": {
"id": 2,
"entity": "Hero"
}
},
"owner": {
"id": 2,
"username": "BatMan"
}
},
{
"id": 4,
"value": "BatMan",
"asset": {
"id": 3,
"asset": "Name",
"entity": {
"id": 2,
"entity": "Hero"
}
},
"owner": {
"id": 2,
"username": "BatMan"
}
},
{
"id": 5,
"value": "26",
"asset": {
"id": 3,
"asset": "Age",
"entity": {
"id": 2,
"entity": "Hero"
}
},
"owner": {
"id": 3,
"username": "SuperMan"
}
},
{
"id": 6,
"value": "SuperMan",
"asset": {
"id": 4,
"asset": "Name",
"entity": {
"id": 2,
"entity": "Hero"
}
},
"owner": {
"id": 3,
"username": "SuperMan"
}
}
]
}
API View
class EntityAssetValueAPIView(APIView):
queryset = Value.objects.select_related('asset', 'asset__entity', 'owner')
serializer_class = ValueSerializer
# If you want to use object lookups other than pk, set 'lookup_field'.
# For more complex lookup requirements override `get_object()`.
lookup_field = 'pk'
# lookup_url_kwarg = None
# The filter backend classes to use for queryset filtering
# filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
# The style to use for queryset pagination.
# pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
# def allowed_methods(self):
# http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
# return http_method_names
def get(self, request, *args, **kwargs):
eav = self.queryset.all()
serializer = self.serializer_class(eav, many=True)
return Response(serializer.data)
What I want to do is, Get all the ENTITIES Assigned to a USER ( along with the ASSET & VALUES ).
The same data is posted for a NEW ENTITY ASSIGNMENT to USER .
From What I understood from DRF, I would need an API view, API view would call serializer, so, I would have to create a custom Serializer, then to save the data I have to override create method, where in I will have these separate serializers that would validate the data and save it.
I am not able to send the desired RESPONSE or ingest the REQUEST coming in.
What should be a way forward ?
I have faced the similar problem So I'll explain a little scenario here. So you can take reference from that.
Added some related names in models :
class Asset(models.Model):
"""
Asset of EAV
"""
asset = models.CharField(max_length=216, null=False,
default='asset', name='asset',
verbose_name='Asset of EAV'
)
entity = models.ForeignKey(to=Entity, related_name='asset_entity')
class Value(models.Model):
"""
Value of EAV
"""
value = models.CharField(max_length=216,
null=False, default='value',
name='value', verbose_name='Value of EAV'
)
asset = models.ForeignKey(to=Asset, related_name='asset_value')
owner = models.ForeignKey(User, verbose_name='EAV Owner', related_name='eav')
initial queryset looks like this, the idea is to fetch all information that is required initially:
queryset = Entity.objects.filter('**condition comes here**')
.values('id', 'entity', 'asset_entity', 'asset_entity__asset', 'asset_entity__asset_value', 'asset_entity__asset_value__value',
'asset_entity__asset_value__owner_id',)
Pass this queryset when trying to make response :
serializer = serializer(queryset, many=True, context={'request': request})
Serailizers :
class Owner_Serializer(serializers.ModelSerializer)
class Meta:
model = User
exclude = ('**exclude fields you want to exclude**', )
class EntitySerializer(serializers.Serializer):
id = serializers.IntegerField(source='id')
entity = serializers.CharField(source='entity')
owner = serializers.SerializerMethodField()
groups = serializers.SerializerMethodField()
asset = serializers.SerializerMethodField()
def get_owner(self, obj):
return Owner_Serializer(obj.get('asset_entity__asset_value__owner_id'), context=self.context).data
Same process goes for groups and asset fields.
in get_owner() we have entity object and from that object we can get owner_id , as we have already fetched related data initially.
So the main idea here to fetch all data initially and then serilaize that data according to your requirement.
Existing Nested Serailization do not support the response format you required.
Note : Initial querset is vry important , you may need to use prefetch related there because we are fetching data using reverse relationship. Also I didn't test the queryset so have to make sure that correct related_names are used to fetch related data.