How to get all related_name fields in django with serializers? - 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)
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

Related

REST API Django does not show all tables in different endpoints

I am learning REST API Django and would appreciate your patience and help in understaing the below case.
in myproject/abcapp/forms.py
from django import forms
from .models import *
class ProfileForm(forms.ModelForm):
class Meta:
model=Profile
fields = "__all__"
class Zoo_data_2020Form(forms.ModelForm):
class Meta:
model=Zoo_data_2020
fields = "__all__"
in myproject/abcapp/models.py
from django.conf import settings
from django.db import models
class ProfileQuerySet(models.QuerySet):
pass
class ProfileManager(models.Manager):
def get_queryset(self):
return ProfileQuerySet(self.model,using=self._db)
class Profile(models.Model):
name=models.CharField(settings.AUTH_USER_MODEL,max_length=200)
subtype=models.CharField(max_length=500)
type=models.CharField(max_length=500)
gender=models.CharField(max_length=500)
objects = ProfileManager()
class Meta:
verbose_name = 'Profile'
verbose_name_plural = 'Profiles'
managed = False
db_table ='profiles'
def __str__(self):
return '{}'.format(self.name)
class Zoo_data_2020QuerySet(models.QuerySet):
pass
class Zoo_data_2020Manager(models.Manager):
def get_queryset(self):
return Zoo_data_2020QuerySet(self.model,using=self._db)
class Zoo_data_2020(models.Model):
name=models.CharField(max_length=200)
size=models.DecimalField(decimal_places=3,max_digits=100000000)
weight=models.DecimalField(decimal_places=3,max_digits=100000000)
age=models.DecimalField(decimal_places=3,max_digits=100000000)
objects = Zoo_data_2020Manager()
class Meta:
verbose_name = 'zoo_data_2020'
verbose_name_plural = 'zoo_data_2020s'
managed = False
db_table ='zoo_data_2020'
def __str__(self):
return '{}'.format(self.name)
in myproject/abcapp/api/views.py:
from rest_framework import generics, mixins, permissions
from rest_framework.views import APIView
from rest_framework.response import Response
import json
from django.shortcuts import get_object_or_404
from abcapp.models import *
from .serializers import *
def is_json(json_data):
try:
real_json = json.loads(json_data)
is_valid = True
except ValueError:
is_valid = False
return is_valid
class ProfileDetailAPIView(generics.RetrieveAPIView):
permission_classes = []
authentication_classes = []
queryset= Profile.objects.all()
serializer_class = ProfileSerializer
lookup_field = 'id'
class ProfileAPIView(generics.ListAPIView):
permission_classes = []
authentication_classes= []
serializer_class = ProfileSerializer
passed_id = None
search_fields = ('id','name','animal')
queryset = Profile.objects.all()
def get_queryset(self):
qs = Profile.objects.all()
query = self.request.GET.get('q')
if query is not None:
qs=qs.filter(name__icontains=query)
return qs
class Zoo_data_2020DetailAPIView(generics.RetrieveAPIView):
permission_classes = []
authentication_classes = []
queryset= Zoo_data_2020.objects.all()
serializer_class = Zoo_data_2020Serializer
lookup_field = ('id','name')
class Zoo_data_2020APIView(generics.ListAPIView):
permission_classes =[]
authentication_classes= []
serializer_class = Zoo_data_2020Serializer
passed_id = None
search_fields = ('id','name')
queryset = Zoo_data_2020.objects.all()
def get_queryset(self):
qs = Zoo_data_2020.objects.all()
query = self.request.GET.get('q')
if query is not None:
qs=qs.filter(name__icontains=query)
return qs
in myproject/abcapp/api/serializers.py:
from rest_framework import serializers
from abcapp.models import *
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model=Profile
fields = "__all__"
read_only_fields = ['name']
class Zoo_data_2020Serializer(serializers.ModelSerializer):
class Meta:
model = Zoo_data_2020
fields = "__all__"
read_only_fields = ['name']
in myproject/abcapp/api/urls.py:
from django.urls import path
from .views import *
urlpatterns = [
path('', ProfileAPIView.as_view()),
path('<id>/', ProfileDetailAPIView.as_view()),
path('', Zoo_data_2020APIView.as_view()),
path('<id>/', Zoo_data_2020DetailAPIView.as_view()),]
in myproject/urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/profile/', include('abcapp.api.urls')),
path('api/zoodata2020/', include('abcapp.api.urls')),
]
So when i do call http://127.0.0.1:8000/api/profile/ i get data from tables Profile, but when i do call http://127.0.0.1:8000/api/zoodata2020/ i get data again from table Profile not Zoo_data_2020. But when i remove from myproject/abcapp/api/urls.py:
path('', ProfileAPIView.as_view()),
path('<id>/', ProfileDetailAPIView.as_view()),
then it shows me data from table Zoo_data_2020 but then i can't get data from table Profile
how to fix it ? I am sure that i am doing smth wrong in urls.py in both app and the project. So what i need to do to make endpoints seperate ? and also how to show them both?
I want to call http://127.0.0.1:8000/api/profile/?search=TIGER and as result to give me information from both tables profiles and zoo_data_2020 as they contain different data but about the same 'name' which is TIGER. But currently when for example i call http://127.0.0.1:8000/api/profile/?search=TIGER it just shows me data from tabel Profile not from Zoo_data_2020
Please help to understand it and how to fix it. Thanks in advance.
In the project urls.py, you don't have to refer the same app multiple times, you can do that in the app's urls.py
Give this a try
myproject/urls.py:
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('cfs.api.urls')),
]
myproject/abcapp/api/urls.py:
urlpatterns = [
path('profile', ProfileAPIView.as_view()),
path('profile/<id>/', ProfileDetailAPIView.as_view()),
path('zoo_data', Zoo_data_2020APIView.as_view()),
path('zoo_data/<id>/', Zoo_data_2020DetailAPIView.as_view()),
]

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

django rest framework error while post through json data

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 CatalogSerializerPost(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField(required=False, allow_blank=True, max_length=100)
no_of_pcs = serializers.IntegerField()
per_piece_price = serializers.IntegerField()
def create(self, validated_data):
return Catalog.objects.create(**validated_data)
class CatalogSerializer(serializers.ModelSerializer):
total_pieces = serializers.SerializerMethodField()
total_price = serializers.SerializerMethodField()
class Meta:
model = Catalog
fields = ('name','no_of_pcs','per_piece_price','company_name','total_pieces','total_price')
depth = 1
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"]
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, generics
from rest_framework.decorators import api_view
#api_view(['GET', 'POST'])
def CatalogView(request):
if request.method == 'GET':
catalogs = Catalog.objects.select_related('company_name')
serializer = CatalogSerializer(catalogs, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = CatalogSerializerPost(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Here is my urls.py
from django.conf.urls import url, include
from django.contrib import admin
from api.views import CatalogView
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,'catalog')
router.register('companies',views.CompanyView)
router.register('users',views.UserView)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'', include(router.urls)),
url(r'catalog/', CatalogView),
]
Here i am not able to post data THRIUGH JSON DATA..
Please refer the screenshot for the error..
Thanks..
here is the screen shot for error
please check this issue.
Here i am not able to post data THROUGH JSON DATA..
showing id field is required.
there are few problems with your Serializer and View both, and also the data that you are passing, Change your serializer to this
class CatalogSerializerPost(serializers.Serializer):
name = serializers.CharField(required=False, allow_blank=True, max_length=100)
no_of_pcs = serializers.IntegerField()
per_piece_price = serializers.IntegerField()
company_name_id = serializers.IntegerField() # add this field as you have a company field in the Catalog Model. and you are passing company id in the JSON.
def create(self, validated_data):
return Catalog.objects.create(**validated_data)
and pass
"company_name_id" :3 in your json
You need to mark id field as read only:
class CatalogSerializerPost(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
Also it could be more simple to use ModelSerializer.

How to get aggregation in django rest framework inside same api

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

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