I want to serialize data in the format given below.I'm new to django-rest framework.I am working in a varsity project.So, little help will be appreciated.
{
{
"Series_name":"something",
"Home_team":"anything",
"Away_team":"sbh",
"players":[
{
"id":"1",
...
}
{
"id":"2",
...
}
]
},
{
"Series_name":"something2",
"Home_team":"anything",
"Away_team":"sbh",
"players":[
{
"id":"1",
...
}
{
"id":"1",
...
}
]
}
}
I have tried this.But this doesn't give satisfactory result.In fact it returns empty set.
class PlayersSerializer2(serializers.ModelSerializer):
class Meta:
model = Players
fields = ['name', 'country', 'image', 'role', 'credit']
class SeriesListSerializer2(serializers.ModelSerializer):
class Meta:
model = SeriesList
fields = '__all__'
class SeriesSquadsSerializer(serializers.ModelSerializer):
players = PlayersSerializer2(many=True, read_only=True)
series = SeriesListSerializer2(many=True, read_only=True)
class Meta:
model = SeriesSquads
fields = ['series', 'players']
these are the models I'm working with.I've 3 models SeriesList,Series_Squads and Players.Series_sqauds has unique pairs (Series_name,Players).It has two foreign keys pointing objects of SeriesList and Players.
class SeriesList(models.Model):
Series_name = models.CharField(max_length=250,
unique=True,primary_key=True)
No_of_matches = models.IntegerField()
Home_team = models.CharField(max_length=250)
Away_team = models.CharField(max_length=250)
class SeriesSquads(models.Model):
Series_name = models.ForeignKey(SeriesList, on_delete=models.CASCADE)
Squad_player = models.ForeignKey(Players, on_delete=models.CASCADE)
class Players(models.Model):
name = models.CharField(default="", max_length=250)
country = models.CharField(max_length=250)
image = models.CharField(max_length=500)
role = models.CharField(max_length=30)
credit = models.FloatField(default=None)
You can get user of SerializerMethodField to get your ForeignKey related objects into your serializer. Update your serializer so that:
class PlayersSerializer2(serializers.ModelSerializer):
class Meta:
model = Players
fields = ['name', 'country', 'image', 'role', 'credit']
class SeriesSquadsSerializer(serializers.ModelSerializer):
players = PlayersSerializer2(many=True, read_only=True)
Series_name = serializers.SerializerMethodField()
Home_team = serializers.SerializerMethodField()
Away_team = = serializers.SerializerMethodField()
class Meta:
model = SeriesSquads
fields = ['players']
def get_Series_name(self, obj):
return obj.Series_name.Series_name
def get_Home_team(self, obj):
return obj.Series_name.Home_team
def get_Away_team(self, obj):
return obj.Series_name.Away_team
Related
I want to design solution for ordering items. I have endpoint that create orders BUT I need to to have items object in the order. let me show you the code
class ItemModel(models.Model):
name = models.CharField(max_length=50)
price = models.FloatField()
discretion = models.CharField(max_length=500)
available = models.BooleanField(default=True)
class OrderModel(models.Model):
phone = models.CharField(max_length=20)
delevary_time = models.DateTimeField()
class CartModel(models.Model):
order = models.ForeignKey(OrderModel, on_delete=models.CASCADE, related_name='order_m')
item = models.ForeignKey(ItemModel, on_delete=models.CASCADE, related_name='item_m')
I need endpoint that create order to me. her what I did
class CartSerializer(serializers.ModelSerializer):
class Meta:
model = CartModel
exclude = ['order',]
depth = 2
class OrderSerializer(serializers.ModelSerializer):
cart = serializers.SerializerMethodField()
class Meta:
model = OrderModel
fields = ['phone', 'state', 'delevary_time', 'cart']
def get_cart(self, obj):
cart = CartModel.objects.filter(order__id=obj.id)
serializer = CartSerializer(cart, many=True)
return serializer.data
this is the endpoint
router.register('order', OrderViewSet, 'api-order')
{
"phone": 124997988698,
"delevary_time": "2020-07-17T19:34:00",
"cart": [
{
"item": 1
},
{
"item": 2
}
]
}
when I post the json it don't save the cart it only save the oder phone and delevary_time. How I can save the cart at the same time
class CartSerializer(serializers.ModelSerializer):
class Meta:
model = CartModel
exclude = ['order',]
depth = 2
class OrderSerializer(serializers.ModelSerializer):
order_m = CartSerializer(many=True) # adding this
class Meta:
model = OrderModel
fields = ['phone', 'state', 'delevary_time', 'order_m']
def create(self, validated_data):
cart_data = validated_data.pop('order_m')
order = OrderModel.objects.create(**validated_data)
for c in cart_data:
CartModel.objects.create(order=order, **c)
return order
I am new to Django rest-framework. I am writing an API to fetch details in a parent-child hierarchy. Following is my code;
models.py
class ConfigAttributes(models.Model):
attr_set_name = models.CharField(max_length=32)
product_type = models.CharField(max_length=32)
class ProductInfo(models.Model):
config_attr = models.ForeignKey(ConfigAttributes, on_delete=models.CASCADE)
product_name = models.CharField(max_length=32)
class AttributeDetails(models.Model):
product_info = models.ForeignKey(ProductInfo, on_delete=models.CASCADE)
attribute_name = models.CharField(max_length=32)
serializers.py
class ConfigAttributesSerializer(serializers.ModelSerializer):
class Meta:
model = ConfigAttributes
fields = ['id', 'attr_set_name', 'product_type']
class ProductInfoSerializer(serializers.ModelSerializer):
class Meta:
model = ProductInfo
fields = ['id', 'product_name', 'config_attr_id']
class AttributeDetailsSerializer(serializers.ModelSerializer):
class Meta:
model = AttributeDetails
fields = ['id', 'attribute_name', 'product_info_id']
views.py
class ConfigAttributesViewSet(viewsets.ModelViewSet):
queryset = ConfigAttributes.objects.all()
serializer_class = ConfigAttributesSerializer
class ProductInfoViewSet(viewsets.ModelViewSet):
queryset = ProductInfo.objects.all()
serializer_class = ProductInfoSerializer
class AttributeDetailsViewSet(viewsets.ModelViewSet):
queryset = AttributeDetails.objects.all()
serializer_class = AttributeDetailsSerializer
and app/urls.py
router = routers.DefaultRouter()
router.register('config', ConfigAttributesViewSet)
router.register('product', ProductInfoViewSet)
router.register('attr', AttributeDetailsViewSet)
urlpatterns = [
path('', include(router.urls)),
]
When I call the API, my required hierarchy and output is;
[
{
"attr_set_name" : "abc",
"product_type" : "efg",
"product_info" : {
"product_name" : "hij",
"attribute_details" : {
"attribute_name" : "klm"
}
}
}
]
What are the changes need to done in the files to get the above output in hierarchy (I am using Postman to check my APIs). Thank you for the help.
You can nest your serializers. To match your general API hierarchy this is as close as you can get. Unfortunately, the relationship fields will be lists.
class AttributeDetailsSerializer(serializers.ModelSerializer):
class Meta:
model = AttributeDetails
fields = ['id', 'attribute_name', 'product_info_id']
class ProductInfoSerializer(serializers.ModelSerializer):
attribute_details = AttributeDetailsSerializer(many=True)
class Meta:
model = ProductInfo
fields = ['id', 'product_name', 'config_attr_id', 'attribute_details']
class ConfigAttributesSerializer(serializers.ModelSerializer):
product_infos = ProductInfoSerializer(many=True)
class Meta:
model = ConfigAttributes
fields = ['id', 'attr_set_name', 'product_type', 'product_infos']
You can get the specific parent elements if you start with the AttributeDetails instance though:
class ConfigAttributesSerializer(serializers.ModelSerializer):
class Meta:
model = ConfigAttributes
fields = ['id', 'attr_set_name', 'product_type',]
class ProductInfoSerializer(serializers.ModelSerializer):
config_attribute = ConfigAttributesSerializer(many=False)
class Meta:
model = ProductInfo
fields = ['id', 'product_name', 'config_attr_id', 'config_attribute']
class AttributeDetailsSerializer(serializers.ModelSerializer):
product_info = ProductInfoSerializer(many=False)
class Meta:
model = AttributeDetails
fields = ['id', 'attribute_name', 'product_info_id', 'product_info']
I want to serialize "Department name"(dept_name) as well as Department ID(id) in the Employee Model Serializer from department Model
In the Employee Serializer I want to Serialize "Department name" as well as "Dept ID" models. I mentioned Department Model in class Meta of Employee Serializer as well
MODELS
class Department(models.Model):
dept_name = models.CharField(max_length=10)
class Employee(models.Model):
emp_name = models.CharField(max_length=15)
email = models.EmailField(unique=True)
password = models.CharField(max_length=14)
designation = models.CharField(max_length=20)
dept_id = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True, blank=True)
class Meta:
ordering = ('id',)
def __str__(self):
return self.emp_name
SERIALIZER
class DepartmentSerializer(serializers.ModelSerializer):
class Meta:
model = Department
fields = [
'id',
'dept_name',
]
class EmployeeSerializer(serializers.ModelSerializer):
dept_id = serializers.SlugRelatedField(queryset=Department.objects.all(), slug_field='dept_name')
deptname = DepartmentSerializer()
class Meta:
model = Employee,Department
fields = [
'id',
'emp_name',
'email',
'password',
'designation',
'dept_id',
'deptname',
]
Remember to select_related('dept') on your Employee queryset.
class Department(models.Model):
dept_name = models.CharField(max_length=10)
class Employee(models.Model):
emp_name = models.CharField(max_length=15)
email = models.EmailField(unique=True)
password = models.CharField(max_length=14)
designation = models.CharField(max_length=20)
# .._id suffix django will implement automatically
dept = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True, blank=True)
class Meta:
ordering = ('id',)
def __str__(self):
return self.emp_name
class DepartmentSerializer(serializers.ModelSerializer):
class Meta:
model = Department
fields = ('id', 'dept_name')
class EmployeeSerializer(serializers.ModelSerializer):
dept = DepartmentSerializer()
class Meta:
model = Employee
fields = ('id',
'emp_name',
'email',
'password',
'designation',
'dept')
you can use depth in in EmployeeSerializer. It will return all department object's fields.
=================
depth = 1 => returns one level of depth.
depth = 2 => returns two levels of depth.
like this :
class DepartmentSerializer(serializers.ModelSerializer):
class Meta:
model = Department
fields = '__all__'
class EmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = Employee
fields = '__all__'
depth = 1
I have the following models:
class Asset(models.Model):
isin = models.CharField(max_length=100)
asset_type = models.CharField(max_length=50)
last_price = models.FloatField
security_weight = models.FloatField
update_date = models.DateTimeField
def __str__(self):
return self.isin
class Meta:
ordering = ('isin',)
class PortfolioElement(models.Model):
nominal = models.FloatField
weight = models.FloatField
asset = models.OneToOneField(
Asset,
on_delete=models.CASCADE,
primary_key=True,
)
def __str__(self):
return self.asset.isin
class Meta:
ordering = ('asset',)
class Portfolio(models.Model):
number = models.CharField(max_length=100)
update_date = models.DateTimeField
elements = models.ManyToManyField(PortfolioElement)
def __str__(self):
return self.number
class Meta:
ordering = ('number',)
class Client(models.Model):
number = models.CharField(max_length=100)
update_date = models.DateTimeField
portfolios = models.ManyToManyField(Portfolio)
def __str__(self):
return self.number
class Meta:
ordering = ('number',)
and the following serializer:
class ClientSerializer(serializers.ModelSerializer):
class Meta:
model = Client
fields = ('number', 'portfolios')
depth = 1
However, I would like to see the actual data in the portfolios (and portfolio elements). But when I try to make a GET request on an arbitrary Client (by the (Client).number field) I can only see the following:
{
"number": "28101317",
"portfolios": [
{
"id": 14,
"number": "5471-339425",
"elements": [
{
"asset": 326
},
{
"asset": 327
}, ... (and so on)
How can a tweak my code, so that I also can get the actual "asset" information?
/Niclas
You can try this:
class AssetSerializer(serializers.ModelSerializer):
class Meta:
model = Asset
fields = '__all__'
class PortfolioElementSerializer(serializers.ModelSerializer):
asset = AssetSerializer()
class Meta:
model = PortfolioElement
fields = ('nominal', 'weight', 'asset')
class PortfolioSerializer(serializers.ModelSerializer):
elements = PortfolioElementSerializer(many=True)
class Meta:
model = Portfolio
fields = ('number', 'update_date', 'elements')
class ClientSerializer(serializers.ModelSerializer):
portfolios = PortfolioSerializer(many=True)
class Meta:
model = Client
fields = ('number', 'portfolios')
I got events that happen at locations:
class Event(models.Model):
title = models.CharField(max_length=200)
date_published = models.DateTimeField('published date',default=datetime.now, blank=True)
date_start = models.DateTimeField('start date')
date_end = models.DateTimeField('end date')
def __unicode__(self):
return self.title
description = models.TextField()
price = models.IntegerField(null=True, blank=True)
tags = TaggableManager()
location = models.ForeignKey(Location, blank=False)
class Location(models.Model):
location_title = models.CharField(max_length=200)
location_date_published = models.DateTimeField('published date',default=datetime.now, blank=True)
location_latitude = models.CharField(max_length=200)
location_longitude = models.CharField(max_length=200)
location_address = models.CharField(max_length=200)
location_city = models.CharField(max_length=200)
location_zipcode = models.CharField(max_length=200)
location_state = models.CharField(max_length=200)
location_country = models.CharField(max_length=200)
location_description = models.TextField()
def __unicode__(self):
return u'%s' % (self.location_title)
I can get the results of all via:
class EventSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
class Meta:
model = Event
depth = 2
fields = ('url','id','title','date_start','date_end','description', 'price', 'location')
Which outputs:
{
"url": "http://localhost:8000/api/event/3/",
"id": 3,
"title": "Testing",
"date_start": "2013-03-10T20:19:00Z",
"date_end": "2013-03-10T20:19:00Z",
"description": "fgdgdfg",
"price": 10,
"location": {
"id": 2,
"location_title": "Mighty",
"location_date_published": "2013-03-10T20:16:00Z",
"location_latitude": "37.767475",
"location_longitude": "-122.406878",
"location_address": "119 Utah St, San Francisco, CA 94103, USA",
"location_city": "San Francisco",
"location_zipcode": "94103",
"location_state": "California",
"location_country": "United States",
"location_description": "Some place"
}
},
However, I don't want it to grab all fields, as I don't need all of them. How can I define what fields should be retrieved from my nested object? Thanks!
Serializers can be nested, so do something like this...
class LocationSerializer(serializers.ModelSerializer):
class Meta:
model = Location
fields = (...)
class EventSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
location = LocationSerializer()
class Meta:
model = Event
fields = ('url','id','title','date_start','date_end','description', 'price', 'location')
I have been to this and did not get a perfect solution, But I did something you may check for it.
This method will not create nested serializers
**class LocationSerializer(serializers.ModelSerializer):**
class Meta:
model = Location
fields = (...) #does not matter
exclude = (...) #does not matter
class EventSerializer(serializers.ModelSerializer):**
loc_field_1 = serializers.CharField(required=False,*source='location.loc_field_1'*)
loc_field_2 = serializers.CharField(required=False,*source='location.loc_field_2'*)
***#ADD YOUR DESIRE FIELD YOU WANT TO ACCESS FROM OTHER SERIALIZERS***
class Meta:
model = Event
fields =('url','id','title','date_start','date_end','description', 'price', 'location')
I found this question when I was trying to figure out how to exclude certain fields from a serializer only when it was being nested. Looks like Tasawer Nawaz had that question as well. You can do that by overriding get_field_names. Here's an example based on Tom Christie's answer:
class LocationSerializer(serializers.ModelSerializer):
class Meta:
model = Location
fields = (...)
exclude_when_nested = {'location_title', 'location_date_published'} # not an official DRF meta attribute ...
def get_field_names(self, *args, **kwargs):
field_names = super(LinkUserSerializer, self).get_field_names(*args, **kwargs)
if self.parent:
field_names = [i for i in field_names if i not in self.Meta.exclude_when_nested]
return field_names
class EventSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
location = LocationSerializer()
class Meta:
model = Event
fields = ('url','id','title','date_start','date_end','description', 'price', 'location')