Sqlalchemy - Create a row when i put a model nested with marshmallow - python

I trying to put a nested model and it's works, but i can see a new row in my database created in the same time.
api/program.py:
#app.route("/programs/<id>", methods=["PUT"])
def update_program(id):
program = Program.query.filter_by(id=id).first()
res = program_nested_schema.load(request.json)
program.name = res.data.name
program.steps = res.data.steps
program.updated_at = datetime.utcnow()
db.session.add(program)
db.session.commit()
return program_nested_schema.jsonify(program)
(i think it's a problem with my nested schema)
schemas:
class ProgramNested(ma.ModelSchema):
class Meta:
model = Program
fields = ('name', 'visibility', 'steps')
steps = fields.Nested(ProgramStepsSchema, many=True)
program_nested_schema = ProgramNested()
class ProgramStepsSchema(ma.ModelSchema):
class Meta:
model = Step
exercise = fields.Nested(GetExerciseSchema, many=False, only=('id',))
class GetExerciseSchema(ma.ModelSchema):
class Meta:
model = Exercise
fields = ('id', 'name', 'image', 'visibility')
In addition to the update, a line is created when I send this body:
{
"id": 2,
"name": "Jambes",
"steps": [
{
"exercise": {
"id": 6,
"image": "pompe.jpg",
"name": "Pompes"
},
"id": 6,
"position": 1,
"repetitions": 200,
"rest": 30,
"rest_end": 60,
"series": 3,
"weight": 0
},
{
"exercise": {
"id": 7,
"image": "10763352.jpg",
"name": "Squats"
},
"id": 70,
"position": 2,
"repetitions": 11,
"rest": 45,
"rest_end": 90,
"series": 4,
"weight": 16
}
],
"visibility": "PRIVATE"
}
It's my first post, teel me if you need more information and I'm sorry for my very aproximative english

Related

nested serializer not returning expected values Django Rest Framework

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"]

django Many to Many with three table relationships together

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', )

how to access child entire record in parent model in django rest framework

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!!

Insert count objects fields in Array Django Rest Framework

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"
}
]

Django Rest Framework & Entity–attribute–value model (EAV) Data Model

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.

Categories

Resources