How to get aggregation in django rest framework inside same api - python

Here is my models.py
from __future__ import unicode_literals
from django.db import models
class User(models.Model):
name = models.CharField(max_length=200)
company_name = models.ForeignKey('Company',on_delete=models.CASCADE,related_name='user')
def __str__(self):
return self.name
class Company(models.Model):
name = models.CharField(max_length=200)
phone_number = models.IntegerField(null=True,blank=True)
def __str__(self):
return self.name
class Catalog(models.Model):
name = models.CharField(max_length=200)
no_of_pcs = models.IntegerField(null=True,blank=True)
per_piece_price = models.DecimalField(null=True,blank=True,max_digits=10,decimal_places=2)
company_name = models.ForeignKey(Company,on_delete=models.CASCADE,related_name='catalog')
def __str__(self):
return self.name
here is my serializers.py
from rest_framework import serializers
from .models import *
from django.db.models import Sum,Avg,Max,Min,Count,F,Q
class CatalogSerializer(serializers.HyperlinkedModelSerializer):
dynamic_data = serializers.SerializerMethodField()
class Meta:
model = Catalog
fields = '__all__'
def get_dynamic_data(self, obj):
totalpieces = Catalog.objects.all().aggregate(total_pieces=Count('no_of_pcs'))
totalprice = Catalog.objects.all().aggregate(total_price=Sum('per_piece_price'))
print(totalpieces["total_pieces"],totalprice["total_price"])
return totalpieces["total_pieces"],totalprice["total_price"]
class UserSerializer(serializers.ModelSerializer):
# name = serializers.StringRelatedField()
company_name = serializers.CharField()
class Meta:
model = User
fields = '__all__'
class CatalogData(serializers.ModelSerializer):
class Meta:
model = Catalog
fields = ('name', 'no_of_pcs', 'per_piece_price')
class CompanySerializer(serializers.ModelSerializer):
# catalog_details = serializers.SerializerMethodField()
# name = serializers.StringRelatedField()
catalog = CatalogData(many=True)
user = UserSerializer(many=True)
class Meta:
model = Company
fields = ('name', 'phone_number', 'catalog','user')
here is my views.py
from __future__ import unicode_literals
from django.http import HttpResponse
from .models import *
import json
from django.http import JsonResponse, HttpResponse
from .serializers import *
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework import viewsets
class CatalogView(viewsets.ModelViewSet):
queryset = Catalog.objects.select_related('company_name')
serializer_class = CatalogSerializer
class CompanyView(viewsets.ModelViewSet):
queryset = Company.objects.all()
serializer_class = CompanySerializer
class UserView(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
I am getting api like this..
[
{
"url": "http://127.0.0.1:8000/catalogs/1/",
"dynamic_data": [
3,
471118.0
],
"name": "sarees",
"no_of_pcs": 23,
"per_piece_price": "33333.00",
"company_name": "http://127.0.0.1:8000/companies/1/"
}
]
here in dynamic data 3 is total no of pieces means aggregate Count
and in dynamic data 471118.0 is total price means aggregate Sum
But i am expecting api in different format
like this:
[
{
"url": "http://127.0.0.1:8000/catalogs/1/",
"total_pieces":3,
"total_price": 471118.0
"name": "sarees",
"no_of_pcs": 23,
"per_piece_price": "33333.00",
"company_name": "http://127.0.0.1:8000/companies/1/"
}
]
I wants to achive total_pieces and total_price inside same api.
thanks,,

in one function you are returning both values, so django wont make it separate and will pass it as a list, if you want different key value pair use this
class CatalogSerializer(serializers.HyperlinkedModelSerializer):
total_pieces = serializers.SerializerMethodField()
total_price = serializers.SerializerMethodField()
class Meta:
model = Catalog
fields = '__all__'
def get_total_pieces(self, obj):
totalpieces = Catalog.objects.all().aggregate(total_pieces=Count('no_of_pcs'))
return totalpieces["total_pieces"]
def get_total_price(self, obj):
totalprice = Catalog.objects.all().aggregate(total_price=Sum('per_piece_price'))
return totalprice["total_price"]

Related

Django Rest Framework - Create object with foregin key relation

I created simple REST API which i want to create product objects. My problem is that API view is not showing me multiple choice field to choose from existing categories.
models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
class Meta:
ordering = ('name',)
class Product(models.Model):
name = models.CharField(max_length=200, unique=True)
price = models.PositiveSmallIntegerField(default="")
category = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True, default=None)
def __str__(self):
return self.name
class Meta:
ordering = ('name',)
serializers.py
from rest_framework import serializers
from .models import Product, Category
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
views.py
from django.shortcuts import render
from django.http import HttpResponse
from rest_framework import viewsets
from .models import Product, Category
from .serilaizers import ProductSerializer, CategorySerializer
from rest_framework.response import Response
from rest_framework.views import APIView
class ProductView(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
class CategoryView(viewsets.ModelViewSet):
queryset = Category.objects.all()
serializer_class = CategorySerializer
That is what i get after running server, only two positions:
__all__ does not work with ForeignKey and other relationship fields. You need to specify the field names explicitly. Add a list or tuple with field names to your ProductSerializer.
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ("name", "price", "category")

How to POST ManyToMany Data with Json?

How to POST ManyToMany Data with Json? I have a data like this:
model.py
from django.db import models
class Diet(models.Model):
date = models.CharField(max_length=20)
building = models.CharField(max_length=40)
location = models.CharField(max_length=40)
restaurants = models.ManyToManyField('Restaurant')
def __str__(self):
return self.building
class Restaurant(models.Model):
name = models.CharField(max_length=40)
menus = models.ManyToManyField('DietMenu')
def __str__(self):
return self.name
class DietMenu(models.Model):
name = models.CharField(max_length=256)
price = models.CharField(max_length=20)
def __str__(self):
return self.name
api.py
from .models import Diet
from .models import Restaurant
from .models import DietMenu
from rest_framework import serializers, viewsets
class DietMenuSerializer(serializers.ModelSerializer):
class Meta:
model = DietMenu
fields = ('name', 'price')
class DietMenuViewSet(viewsets.ModelViewSet):
queryset = DietMenu.objects.all()
serializer_class = DietMenuSerializer
class RestaurantSerializer(serializers.ModelSerializer):
menus = DietMenuSerializer(many=True, read_only=True)
class Meta:
model = Restaurant
fields = ('name', 'menus')
class RestaurantViewSet(viewsets.ModelViewSet):
queryset = Restaurant.objects.all()
serializer_class = RestaurantSerializer
class DietSerializer(serializers.ModelSerializer):
restaurants = RestaurantSerializer(many=True, read_only=True)
class Meta:
model = Diet
fields = ('date', 'building', 'location', 'restaurants')
class DietViewSet(viewsets.ModelViewSet):
queryset = Diet.objects.all()
serializer_class = DietSerializer
And I get a json of the data like this.
import requests
class DjangoJson(object):
def __init__(self):
self.url = "url"
def set_diet_date(self):
self.url = "http://localhost:8000/api/v1/diet/?format=json"
def get(self):
self.set_diet_date()
request = requests.get(self.url)
document = request.json()
return document
def post(self, param):
requests.post(self.url, json=param)
if __name__ == "__main__":
json = DjangoJson()
doc = json.get()[0]
json.post(doc)
Then I POST this json by using the requests library. But the restaurant field is empty.
Is there any way to POST ManyToMany data with Json?
Thanks.

How to get foreignkey field name instead of id in django rest framework

Here is my models.py
from __future__ import unicode_literals
from django.db import models
class User(models.Model):
name = models.CharField(max_length=200)
company_name = models.ForeignKey('Company',on_delete=models.CASCADE,related_name='user')
def __str__(self):
return self.name
class Company(models.Model):
name = models.CharField(max_length=200)
phone_number = models.IntegerField(null=True,blank=True)
def __str__(self):
return self.name
class Catalog(models.Model):
name = models.CharField(max_length=200)
no_of_pcs = models.IntegerField(null=True,blank=True)
per_piece_price = models.DecimalField(null=True,blank=True,max_digits=10,decimal_places=2)
company_name = models.ForeignKey(Company,on_delete=models.CASCADE,related_name='catalog')
def __str__(self):
return self.name
here is my serializers.py
from rest_framework import serializers
from .models import *
from django.db.models import Sum,Count
class UserSerializer(serializers.ModelSerializer):
# name = serializers.StringRelatedField()
# company_name = serializers.CharField()
class Meta:
model = User
fields = '__all__'
here is my views.py
from __future__ import unicode_literals
from django.http import HttpResponse
from .models import *
import json
from django.http import JsonResponse, HttpResponse
from .serializers import *
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework import viewsets
class UserView(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
I am getting api like this..
Here i am getting id instead of company_name.
[
{
"id": 1,
"name": "soubhagya",
"company_name": 1
},
{
"id": 2,
"name": "nihar",
"company_name": 2
}
]
But i am expecting output--
like this:
[
{
"id": 1,
"name": "soubhagya",
"company_name": "google"
},
{
"id": 2,
"name": "nihar",
"company_name": "facebook"
}
]
I am expecting my api like this. with company_name.
And i wants to post the data from same api in rest framework
thanks,,
Since you'd defined the __str__() method in your Company model, you can use the StringRelatedField() as
class UserSerializer(serializers.ModelSerializer):
company_name = serializers.StringRelatedField()
class Meta:
model = User
fields = '__all__'
UPDATE
override the to_representation method
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
def to_representation(self, instance):
rep = super(UserSerializer, self).to_representation(instance)
rep['company_name'] = instance.company_name.name
return rep
simple solution is use source
class UserSerializer(serializers.ModelSerializer):
company_name = serializers.CharField(source='company_name.name')
Use depth.
class PhoneSerializer(serializers.ModelSerializer):
class Meta:
model = Phone
depth = 1
fields = '__all__'
class UserSerializer(serializers.ModelSerializer):
company_name = serializers.SerializerMethodField(source='get_company_name')
class Meta:
model = User
fields = '__all__'
def get_company_name(self, obj):
return obj.company_name.name
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
def to_representation(self, instance):
rep = super(UserSerializer, self).to_representation(instance)
rep['company_name'] = instance.company_name.name
return rep
Here is the documentation:
This worked for me:
company_name = serializers.SlugRelatedField(read_only=True, slug_field='name')

How to get all related_name fields in django with serializers?

here is my models.py
from __future__ import unicode_literals
from django.db import models
class User(models.Model):
name = models.CharField(max_length=200)
company_name = models.ForeignKey('Company',on_delete=models.CASCADE)
def __str__(self):
return self.name
class Company(models.Model):
name = models.CharField(max_length=200)
phone_number = models.IntegerField(null=True,blank=True)
def __str__(self):
return self.name
class Catalog(models.Model):
name = models.CharField(max_length=200)
no_of_pcs = models.IntegerField(null=True,blank=True)
per_piece_price = models.DecimalField(null=True,blank=True,max_digits=10,decimal_places=2)
company_name = models.ForeignKey(Company,on_delete=models.CASCADE)
def __str__(self):
return self.name
here is my seralizers.py
from rest_framework import serializers
from .models import *
from django.db.models import Sum,Avg,Max,Min,Count,F,Q
class CatalogSerializer(serializers.HyperlinkedModelSerializer):
dynamic_data = serializers.SerializerMethodField()
class Meta:
model = Catalog
fields = '__all__'
def get_dynamic_data(self, obj):
totalpieces = Catalog.objects.all().aggregate(total_pieces=Count('no_of_pcs'))
totalprice = Catalog.objects.all().aggregate(total_price=Sum('per_piece_price'))
return totalprice,totalpieces
class CompanySerializer(serializers.ModelSerializer):
class Meta:
model = Company
fields = ('name', 'phone_number', 'catalog','user')
class UserSerializer(serializers.ModelSerializer):
name = serializers.StringRelatedField()
company_name = serializers.StringRelatedField()
class Meta:
model = User
fields = '__all__'
here is my view.py
from __future__ import unicode_literals
from django.http import HttpResponse
from .models import *
import json
from django.http import JsonResponse, HttpResponse
from .serializers import *
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework import viewsets
class CatalogView(viewsets.ModelViewSet):
queryset = Catalog.objects.select_related('company_name')
serializer_class = CatalogSerializer
class CompanyView(viewsets.ModelViewSet):
queryset = Company.objects.all()
serializer_class = CompanySerializer
class UserView(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
here is my urls.py
from django.conf.urls import url, include
from django.contrib import admin
from api import views
from rest_framework.urlpatterns import format_suffix_patterns
from rest_framework import routers
router = routers.DefaultRouter()
router.register('catalogs',views.CatalogView)
router.register('companies',views.CompanyView)
router.register('users',views.UserView)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include(router.urls)),
]
when i will go
http://127.0.0.1:8000/companies/
m getting
[
{
"name": "google",
"phone_number": 12,
"catalog": [
5
]
}
]
m expecting this..
[
{
"url": "google",
"name": "google",
"phone_number": 123214214,
"catalog_details":[
"name": "sobhagya",
"no_of_pcs": 22,
"per_piece_price": "3567.00",
]
}
]
here I am able to get only id of related_name which i have set as foreignkKey but I expect all the fields like this above..
please check the json api formats
thanks,
class CompanySerializer(serializers.ModelSerializer):
catalog = CatalogSerializer(many=True) # if you want many catalog objects connected to the company else many=False
class Meta:
model = Company
fields = ('name', 'phone_number', 'catalog','user')
you need to call the catalog serializer inside of the company serializer to get the related objects

How to get all fields in django rest framework which is defined as related name in a diffent model with foreign key?

Here is my models.py
from __future__ import unicode_literals
from django.db import models
class User(models.Model):
name = models.CharField(max_length=200)
company_name = models.ForeignKey('Company',on_delete=models.CASCADE,related_name='user')
def __str__(self):
return self.name
class Company(models.Model):
name = models.CharField(max_length=200)
phone_number = models.IntegerField(null=True,blank=True)
def __str__(self):
return self.name
class Catalog(models.Model):
name = models.CharField(max_length=200)
no_of_pcs = models.IntegerField(null=True,blank=True)
per_piece_price = models.DecimalField(null=True,blank=True,max_digits=10,decimal_places=2)
company_name = models.ForeignKey(Company,on_delete=models.CASCADE,related_name='catalog')
def __str__(self):
return self.name
here is my serializers.py
from rest_framework import serializers
from .models import *
from django.db.models import Sum,Count
class CatalogSerializer(serializers.ModelSerializer):
total_pieces = serializers.SerializerMethodField()
total_price = serializers.SerializerMethodField()
company_name = serializers.CharField()
class Meta:
model = Catalog
fields = ('name','no_of_pcs','per_piece_price','company_name','total_pieces','total_price')
def get_total_pieces(self, obj):
totalpieces = Catalog.objects.aggregate(total_pieces=Count('no_of_pcs'))
return totalpieces["total_pieces"]
def get_total_price(self, obj):
totalprice = Catalog.objects.aggregate(total_price=Sum('per_piece_price'))
return totalprice["total_price"]
class UserSerializer(serializers.ModelSerializer):
company_name = serializers.CharField()
class Meta:
model = User
fields = '__all__'
class CatalogData(serializers.ModelSerializer):
class Meta:
model = Catalog
fields = ('name', 'no_of_pcs', 'per_piece_price')
class CompanySerializer(serializers.ModelSerializer):
catalog = CatalogData(many=True)
user = UserSerializer(many=True)
class Meta:
model = Company
fields = ('name', 'phone_number', 'catalog','user')
here is my views.py
from __future__ import unicode_literals
from django.http import HttpResponse
from .models import *
import json
from django.http import JsonResponse, HttpResponse
from .serializers import *
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework import viewsets
class CatalogView(viewsets.ModelViewSet):
queryset = Catalog.objects.select_related('company_name')
serializer_class = CatalogSerializer
class CompanyView(viewsets.ModelViewSet):
queryset = Company.objects.all()
serializer_class = CompanySerializer
class UserView(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
I am getting api like this..
[
{
"name": "sarees",
"no_of_pcs": 23,
"per_piece_price": "33333.00",
"company_name": "google",
"total_pieces": 3,
"total_price": 471118.0
}
]
Here i am getting only company name for Company Model.
but i am expecting all the fields name of the same company.
But i am expecting output--
like this:
[
{
"name": "sarees",
"no_of_pcs": 23,
"per_piece_price": "33333.00",
"company": [
{
"name": "google",
"phone_number": 323232
}
],
"total_pieces": 3,
"total_price": 471118.0
}
]
I wants to achive all the company fields. with sub list inside same api
thanks,
You can use nested serializer for this. Change your serializer to this:
class CompanySerializer(serializers.ModelSerializer):
catalog = CatalogData(many=True)
user = UserSerializer(many=True)
class Meta:
model = Company
fields = ('name', 'phone_number', 'catalog','user')
class CatalogSerializer(serializers.ModelSerializer):
total_pieces = serializers.SerializerMethodField()
total_price = serializers.SerializerMethodField()
company = CompanySerializer(source='company_name')
class Meta:
model = Catalog
fields = ('name','no_of_pcs','per_piece_price','company','total_pieces','total_price')
depth = 1

Categories