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.
Related
If I'll send get request like thisenter image description here, i need to have multiple pagination (LimitOffset and PageNumber).
models.py:
from django.db import models
class Products(models.Model):
title = models.CharField(max_length=255)
description = models.TextField(blank=True)
photo = models.ImageField(upload_to="photos/%Y/%m/%d/", null=True)
hashtag = models.CharField(max_length=255)
is_hit = models.BooleanField(default=False)
category = models.ForeignKey('Category', on_delete=models.PROTECT, null=True)
def __str__(self):
return self.title
class Category(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
views.py:
from rest_framework import generics
from rest_framework.pagination import PageNumberPagination
from .models import *
from .serializers import ProductsSerializer
class PaginationProducts(PageNumberPagination):
page_size = 2
page_size_query_param = 'page_size'
max_page_size = 2
class ProductsAPIList(generics.ListCreateAPIView):
queryset = Products.objects.all()
serializer_class = ProductsSerializer
pagination_class = PaginationProducts
serializers.py
from rest_framework import serializers
from .models import *
class ProductsSerializer(serializers.ModelSerializer):
class Meta:
model = Products
fields = "__all__"
def get_photo_url(self, obj):
request = self.context.get('request')
photo_url = obj.fingerprint.url
return request.build_absolute_uri(photo_url)
I need something that can help API client choose number of page and quantity of posts on that page. Think that in this case i need NumberPagePagination and LimitOffsetPagination.
I think you don't need to create the custom pagination class.
from rest_framework.pagination import LimitOffsetPagination
class ProductsAPIList(generics.ListCreateAPIView):
queryset = Products.objects.all()
serializer_class = ProductsSerializer
pagination_class = LimitOffsetPagination
The offset value corresponds to the page * size in the original pagination and the limit value corresponds to the size.
I am a beginner in Django. Right now, I am working with the APIs. I am facing a problem. I can't view one of the fields, called label, at http://127.0.0.1:8000/gameapi/. Here is the screenshot:
Here are my codes of serializers.py located inside gamreview folder.
from rest_framework import serializers
from .models import Game, Tags
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tags
fields = ['label']
class GameSerializer(serializers.ModelSerializer):
# label_tag = TagSerializer(many=True)
class Meta:
model = Game
fields = ['id', 'title', 'developer', 'platform']
fields = ['id', 'title', 'developer', 'platform','label_tag']
def create(self, validated_data):
label_tag_data = validated_data.pop('label_tag')
game = Game.objects.create(**validated_data)
for tags_data in label_tag_data:
Tags.objects.create(game=game, **tags_data)
return Game.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.developer = validated_data.get('developer', instance.developer)
instance.platform = validated_data.get('platform', instance.platform)
instance.tag = TagSerializer(read_only=True, many=True)
instance.save()
return instance
Here are my codes of models.py under gamreview folder:
from django.db import models
from django.template.defaultfilters import slugify
# Create your models here.
class Tags(models.Model):
label = models.CharField(max_length=20)
def __str__(self):
return self.label
class Game(models.Model):
title = models.CharField(max_length=100)
developer = models.CharField(max_length=100)
platform = models.CharField(max_length=50, default='null')
label_tag = models.ManyToManyField(Tags)
slug = models.SlugField(max_length=150, default='null')
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save(*args, **kwargs)
class Review(models.Model):
game = models.ForeignKey(Game, on_delete=models.CASCADE)
review = models.CharField(max_length=1000)
date = models.DateField(auto_now=True)
slug = models.SlugField(max_length=150, default='null')
def __str__(self):
return self.game
Here are my codes of views.py under gamreview folder:
from django.views import generic
from .models import Game
from rest_framework import generics
from .serializers import GameSerializer
# Create your views here.
class GameListView(generic.ListView):
template_name = 'gamereview/gamelist.html'
context_object_name = 'all_games'
def get_queryset(self):
return Game.objects.all()
class ReviewView(generic.DetailView):
model = Game
template_name = 'gamereview/review.html'
# class GameApiView(generics.ListAPIView):
class GameApiView(generics.ListCreateAPIView):
queryset = Game.objects.all()
serializer_class = GameSerializer
class GameDetailApiView(generics.RetrieveUpdateDestroyAPIView):
queryset = Game.objects.all()
serializer_class = GameSerializer
Here are my codes of urls.py under gamreview folder:
from . import views
from django.urls import path
app_name = 'gamereview'
urlpatterns = [
path('gamereview/', views.GameListView.as_view(), name='gamelist'),
path('gamereview/<slug:slug>/', views.ReviewView.as_view(), name='review'),
path('gameapi/', views.GameApiView.as_view(), name='gamelistapi'),
path('gameapi/<int:pk>/', views.GameDetailApiView.as_view()),
]
I don't get any error while running the server. However, the label field is not showing up.
How can I fix the issue?
You have declared fields twice in GameSerializer- Meta class. Delete the first one.
class GameSerializer(serializers.ModelSerializer):
# label_tag = TagSerializer(many=True)
class Meta:
model = Game
fields = ['id', 'title', 'developer', 'platform'] --> delete this
fields = ['id', 'title', 'developer', 'platform','label_tag']
Django rest framework relies on related_name attribute to the resolve foreign key fields.
I think just changing your Game model so would do it
label_tag = models.ManyToManyField(Tags, related_name="label")
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')
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"]
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