Allow to post json with array of jsonobjects inside - python

I am a newbie in django world and I'm trying to create a simple rest service with those models:
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
class Album(models.Model):
artist = models.ForeignKey(Musician,on_delete=models.CASCADE)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
And those serializers:
class MusicianSerializer(serializers.ModelSerializer):
class Meta:
model = Musician
fields = ('id','first_name', 'last_name', 'instrument')
class AlbumSerializer(serializers.ModelSerializer):
class Meta:
model = Album
fields = ('id','artist', 'name', 'release_date', 'num_stars')
I want to be able to post a JSON like this one:
{
"first_name": "MusicNom",
"last_name": "MusicCognom",
"instrument": "Flauta",
"albums":
[
{
"name": "Album1",
"release_date": "2015-02-12",
"num_stars": 5
},
{
"id": 2,
"artist": 1,
"name": "AlbumNuevo",
"release_date": "2013-01-08",
"num_stars": 5
}
]
}
This JSON should create the musician and his albums. I've found some examples in the documentation that are useful using "GET" but I would like to do it with "POST".

Related

Different representations of an object in the DRF [duplicate]

This question already has answers here:
DRF: Simple foreign key assignment with nested serializers?
(12 answers)
Closed 6 months ago.
I have a model:
class Schedule(LogSaveDeleteMixin, models.Model):
name = models.CharField(max_length=40)
start_date = models.DateTimeField(null=True, blank=True)
class DeliveryChannel(LogSaveDeleteMixin, models.Model):
name = models.CharField(unique=True, max_length=40)
state = models.CharField(choices=DeliveryChannelState.choices, default='draft', max_length=15)
schedule = models.ForeignKey(Schedule, null=True, on_delete=models.SET_NULL)
And standard ModelSerializer:
class DeliveryChannelsSerializer(serializers.ModelSerializer):
class Meta:
model = DeliveryChannel
fields = '__all__'
class ScheduleSerializer(serializers.ModelSerializer):
class Meta:
model = Schedule
fields = '__all__'
For read requests (GET) I want to receive schedule field as a nested serializer:
{
"id": 0,
"name": "string",
"state": "archived",
"schedule": {
"id": 0,
"name": "string",
"start_date": "2022-08-12T02:41:32.187Z",
}
}
But for writing (POST, PUT) I want to get only schedule id:
{
"id": 0,
"name": "string",
"state": "archived",
"schedule": 0
}
I would like to know the best practices for do this
You can just set some fields in the DeliveryChannelsSerializer.
class DeliveryChannelsSerializer(serializers.ModelSerializer):
schedule = ScheduleSerializer(read_only = True)
schedule_id = serializers.IntegerField(write_only = True)
class Meta:
model = DeliveryChannel
fields = '__all__'
extra_fields = ['schedule_id']
The POST payload should be like the following:
{
"name": "string",
"state": "archived",
"schedule_id": 1
}
You can make two different serializers for DeliveryChannels.
class ScheduleSerializer(serializers.ModelSerializer):
class Meta:
model = Schedule
fields = ['id', 'name', 'start_date']
class DeliveryChannelSerializer(serializers.ModelSerializer):
# Serializer for POST,PUT
class Meta:
model = DeliveryChannel
fields = ['id', 'name', 'state', 'schedule']
class DeliveryChannelDetailSerializer(serializers.ModelSerializer):
# Serializer for GET
schedule = ScheduleSerializer()
class Meta:
model = DeliveryChannel
fields = ['id', 'name', 'state', 'schedule']
if you use ModelViewSet you need to override get_serializer_clas
def get_serializer_class(self):
if self.action == "list":
return DeliveryChannelDetailSerializer
return DeliveryChannelSerializer

how to Serialize multiple objects in Django

I have 2 models for admin and member positions and I would like to get both of the models in one API call to fetch the data on my front end. How can I achieve this?
class ClinetAdminPosition(models.Model):
name = models.CharField(max_length=128, null=True)
company = models.ForeignKey(
to="Company", on_delete=models.CASCADE, related_name="admin_positions", null=True
)
modified_at = models.DateTimeField(verbose_name="Updated", auto_now=True, editable=True)
created_at = models.DateTimeField(verbose_name="Created", auto_now_add=True, editable=False)
def __str__(self):
return f"{self.name}"
class ClinetMangerPosition(models.Model):
name = models.CharField(max_length=128, null=True)
company = models.ForeignKey(
to="Company", on_delete=models.CASCADE, related_name="manger_positions", null=True
)
modified_at = models.DateTimeField(verbose_name="Updated", auto_now=True, editable=True)
created_at = models.DateTimeField(verbose_name="Created", auto_now_add=True, editable=False)
def __str__(self):
return f"{self.name}"
I want to get both models' data from 1 API request
to be like this:
[
{
"admin_positions": [
{
"name": "test",
"company": 1
},
{
"name": "test2",
"company": 1
},
{
"name": "test3",
"company": 1
}
],
"manger_position": [
{
"name": "test",
"company": 1
},
{
"name": "test2",
"company": 1
},
{
"name": "test3",
"company": 1
}
]
}
]
You can do something like this.
**This is your serializers classes **
class ClinetMangerPositionSerializer(ModelSerializer)
clas Meta:
model = ClinetMangerPosition
fields = ['name','company']
class ClinetAdminPositionSerializer(ModelSerializer):
class Meta:
model = ClinetAdminPosition
fields = ['name','company']
This will be your views class to display data.
from rest_framework.views import APIView
from . import serializers
from rest_framework.response import Response
class ViewName(APIView):
def get(self, request):
admin = ClinetAdminPosition.objects.all()
manager = ClinetMangerPosition.objects.all()
res :{
"admin_positions": serializers.ClinetAdminPositionSerializer(admin, many=True).data
"manager_positions":serializers.ClinetMangerPositionSerializer(manager, many-True).data
}
return Response(res)
something like this,
Let me know if you got any doubt
class ClinetMangerPositionSerializer(ModelSerializer)
clas Meta:
model = ClinetMangerPosition
fields = ['name','company']
class ClinetAdminPositionSerializer(ModelSerializer):
class Meta:
model = ClinetAdminPosition
fields = ['name','company']
class CompanySerializer(MOdelSerializer):
manger_position = ClinetAdminPositionSerializer(many=True,source
='clinetmangerposition')
admin_position = ClinetAdminPositionSerializer(many=True,source
='clinetadminposition')
class Meta:
model= Company
fields = ['manger_position','admin_position']

PUT on ModelViewSet with nested object Django Rest Framework

I'm building an API with the django rest framework. I have these models:
class Organism(models.Model):
name = models.CharField(max_length=255)
address = models.ForeignKey(Address, on_delete=models.CASCADE)
type = models.ForeignKey(Type, on_delete=models.CASCADE)
class Address(models.Model):
street = models.CharField(max_length=255, blank=True)
class Type(models.Model):
name = models.CharField(max_length=255, blank=True)
This is the view for my mode Organism :
class OrganismViewSet(viewsets.ModelViewSet):
queryset = Organism.objects.all()
serializer_class = OrganismSerializer
pagination_class = StandardResultsSetPagination
filter_backends = (filters.SearchFilter, DjangoFilterBackend)
filter_class = OrganismFilter
search_fields = ('name')
And my serializer:
class OrganismSerializer(serializers.ModelSerializer):
addresse = AddressSerializer()
type = TypeSerializer()
class Meta:
model = Organism
fields = '__all__'
def update(self, instance, validated_data):
// What I should write to do something "elegant"
Let's imagine when I get my Organism, I have:
{
"address": {
"id": 1
"street": "test"
},
type: {
"id": 1,
"name": "type Organism"
},
"name":"TestTest",
}
So I'm trying to update an Organism (I want to change the name of the street but not create a new object AND change the Type which exists in my database) by sending this:
{
"address": {
"id": 1
"street": "new name"
},
type: {
"id": 2,
"name": "new type"
}
"name":"TestTest",
}
And the fact is I don't have the ID of my object in the parameter "validated_data" of the method update.
If you guys know how to proceed... Thank you in advance.

Django Rest Framework foreign key nesting

I am trying to nest my Users table inside my Relationships table. So instead of this:
[
{
"user": 1,
"related_user": 2,
"relationship": "followed_by"
}
]
I am trying to get this:
[
{
"user": {
"username": "user1",
"name": "User 1",
"email": "bla",
"phone": "bla",
"date_joined": "2017-11-01T21:34:13.101256Z"
},
"related_user": {
"username": "user2",
"name": "User 2",
"email": "bla",
"phone": "bla",
"date_joined": "2017-11-01T21:34:13.101256Z"
},
"relationship": "followed_by"
}
]
I looked up tutorials and I tried adding serializers.RelatedField , UserSerializer(many=true, read-only=true) etc. but nothing worked
Models.py
class User(models.Model):
username = models.CharField(max_length=255)
name = models.CharField(max_length=255)
email = models.CharField(max_length=255)
phone = models.CharField(max_length=255)
date_joined = models.DateTimeField(auto_now_add=True, blank=True)
def __str__(self):
return str(self.pk) + ", " + self.username
RELATIONSHIP_CHOICE = [
("follows", "follows"),
("followed_by", "followed_by"),
("none", "none"),
]
class Relationship(models.Model):
user = models.ForeignKey(User, related_name="primary_user", null=True)
related_user = models.ForeignKey(User, related_name="related_user", null=True)
relationship = models.CharField(max_length=40, choices=RELATIONSHIP_CHOICE, default=RELATIONSHIP_CHOICE[0])
Serializers.py
from rest_framework import serializers
from . import models
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = models.User
fields = (
'username',
'name',
'email',
'phone',
'date_joined',
)
class RelationshipSerializer(serializers.ModelSerializer):
related_user = UserSerializer(many=True)
class Meta:
model = models.Relationship
fields = (
'user',
'related_user',
'relationship',
'related_user'
)
I tried to add related user to my serializer but it didnt work. I am getting an error: 'User' object is not iterable
Any help is appreciated.
class RelationshipSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
related_user = UserSerializer(read_only=True)
class Meta:
model = models.Relationship
fields = (
'user',
'related_user',
'relationship'
)
user = UserSerializer(read_only=True, many=True) is for manytomany field,user = UserSerializer(read_only=True) is for ForeignKey field.

Serializer is returning "Model object" instead of specific field

I have a problem. I'm creating an API with Django REST framework and I created serializer to return recipes and ingredients to cook it.
models.py:
class Recipes(models.Model):
title = models.CharField(max_length=50,null=True, blank=False, verbose_name=('name'))
class Tag(models.Model):
name = models.CharField(max_length=50,null=True, blank=False, verbose_name=('name'))
class ListTag(models.Model):
recipes = models.ForeignKey(Recipes, blank=False, on_delete=models.CASCADE, related_name='recipes')
tag = models.ForeignKey(Tag, blank=False, on_delete=models.CASCADE, related_name='tag')
I have the classes Recipes, Tag (ingredients) and ListTag is the list that contains each ingredient with the id of the receipt.
serializers.py
class RecipesSerializer(serializers.ModelSerializer):
ingredient = serializers.StringRelatedField(many=True, read_only=True, source='recipes')
class Meta:
model = Recipes
fields = ('title', 'ingredient')
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
class ListTagSerializer(serializers.ModelSerializer):
tag = serializers.SlugRelatedField(
read_only=True,
slug_field='name'
)
class Meta:
model = ListeTag
fields = ('recipes','tag')
Results
For RecipesSerializer
{
"title": "Pancakes à la canadienne",
"ingredient": [
"ListTag object",
"ListTag object",
"ListTag object"
]
}
But I want
{
"title": "Pancakes à la canadienne",
"ingredient": [
{
"id": 2,
"name": "milk"
},
{
"id": 3,
"name": "rice"
},
{
"id": 4,
"name": "salade"
},
{
"id": 5,
"name": "tomato"
}
]
}
or
{
"title": "Pancakes à la canadienne",
"ingredient": ["milk","rice","salade","tomato"]
}
You can do this by using Nested relationships like:
class RecipesSerializer(serializers.ModelSerializer):
recipes = ListTagSerializer(many=True,read_only=True)
class Meta:
model = Recipes
fields = ('title', 'recipes')
class ListTagSerializer(serializers.ModelSerializer):
id = serializers.ReadOnlyField(source='tag.id')
tag = serializers.SlugRelatedField(
read_only=True,
slug_field='name'
)
class Meta:
model = ListeTag
fields = ('id','tag')
Learn more about Nested relationships here

Categories