Count the no of movies in django rest framework - django-models

I want to count the no of movies worked by the actors in api. i have tried this but not working
models.py
class Actor(models.Model):
actors = models.CharField(max_length=100)
class Genre(models.Model):
genre = models.CharField(max_length=100)
class Movie(models.Model):
name = models.CharField(max_length=100)
actors = models.ManyToManyField(Actor, related_name="actor_movies")
genre = models.ManyToManyField(Genre,related_name="genre_movies")
serializers.py
class ActorSerializer(serializers.HyperlinkedModelSerializer):
actor_movies = serializers.RelatedField(source='actor.movies', read_only = True)
class Meta:
model = Actor
fields = ['id','actors','actor_movies']
class GenreSerializer(serializers.HyperlinkedModelSerializer):
genre_movies = serializers.RelatedField(source='genre.names', read_only = True)
class Meta:
model = Genre
fields = ['id','genre','genre_movies']
class MovieSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Movie
fields = ['url','name','actors','genre']
im getting output like this
[
{
"id": 1,
"genre": "Ajith"
},
{
"id": 2,
"genre": "Vijay"
}
]
in actual output i need the total no of movies he worked also.

You can use a SerializerMethodField:
class ActorSerializer(serializers.HyperlinkedModelSerializer):
count_actor_movies= serializers.SerializerMethodField()
def get_count_actor_movies(self, instance):
return instance.actor_movies.count()
class Meta:
model = Actor
fields = ['id','actors','count_actor_movies']
For more details, the official docs are here.

Related

How to make it by list comprehension

I need to get the child list under the parent list as a group.
class ServiceSerializer(serializers.ModelSerializer):
cleaning_type = serializers.CharField(source='cleaning_type.cleaning_type_name')
class Meta:
model = Service
fields = ('id', 'cleaning_type','service_name')
class ServiceTypeViewSet(ModelViewSet):
serializer_class = ServiceSerializer
http_method_names = ["get"]
queryset = Service.objects.all()
def get_queryset(self):
"""
This view should return a list of all the service types.
"""
servicename_list = Service.objects.all()
return servicename_list
It shows:
[
{
"id": 1,
"cleaning_type": "Lite service",
"service_name": "Floors",
},
{
"id": 2,
"cleaning_type": "Lite service",
"service_name": "Bathrooms",
},
{
"id": 3,
"cleaning_type": "Lite service",
"service_name": "Kitchen",
}
]
I want this to be in the following format:
[
{
id: 1,
cleaning_type: 'Lite service',
service_name: ['Floors', 'bathroom', 'kitchen'],
},
{
id: 2,
cleaning_type: 'Moving cleaning',
service_name: ['Kitchen Including All Appliances And Cabinets'],
},
]
That means all child elements will be under a separate parent list. Not separate by separate.
models.py is here:
Cleaning Type Model:
class CleaningType(models.Model):
cleaning_type_name = models.CharField(
_("Select Cleaning Type"), blank=True, null=True, max_length=255)
price = models.DecimalField(default=0,max_digits=6, decimal_places=2)
def __str__(self):
return self.cleaning_type_name
Service Model:
class Service(models.Model):
cleaning_type = models.ForeignKey(
CleaningType, on_delete=models.CASCADE)
service_name = models.CharField(
_("Service Name"), blank=True, null=True, max_length=255)
#string type added
def __str__(self):
return str(self.service_name)
I want sub categories under parent caterories. Here cleaning_type is the parent category and service is the child category of cleaning_type. i.e : cleaning_type >> service_type
First you need to move the cleaningtype field into the ServiceType model.
And I think it's better to set the related_name from the view of the target model.
class ServiceType(models.Model):
cleaningtype = models.ForeignKey(
CleaningType, related_name='service_types', on_delete=models.CASCADE)
...
class Service(models.Model):
servicetype = models.ForeignKey(
ServiceType, related_name='services', on_delete=models.CASCADE)
service_name = models.CharField(
_("Service Name"), blank=True, null=True, max_length=255)
#string type added
def __str__(self):
return str(self.service_name)
And in CleaningTypeSerializer
class CleaningTypeSerializer(serializers.ModelSerializer):
service_objects = ServiceTypeSerializer(many = True, read_only = True)
service_types = serializers.SerializerMethodField()
class Meta:
Model = CleaningType
fields = ('id', 'cleaning_type', 'service_types',)
def get_service_types(self, obj):
return list(obj.service_types.values_list('service_type').distinct())
Finally in views.py,
class CleaningTypesViewSet(ModelViewSet):
serializer_class = CleaningTypeSerializer
queryset = CleaningType.objects.all()
You can get the list of CleaningType data from this CleaningTypesViewSet.

how to get foreignkey fields in serializer

In serializer, class I am trying to get the category details such as "name" but the following code gives me the foreignkey id
models.py
class Category(MP_Node, Timestamps):
name = models.CharField(_('Name'), max_length=255, db_index=True)
class VideoCategory(Category):
image = models.ImageField(upload_to='video_categories', blank=True, null=True, max_length=255)
class VideoCategoryVideo(BaseModel, Timestamps, SoftDelete):
video = models.ForeignKey(Video, on_delete=models.CASCADE)
category = models.ForeignKey(VideoCategory, on_delete=models.CASCADE, null=True)
serializers.py
class VideoCategoryVideoSerializer(serializers.ModelSerializer):
class Meta:
model = VideoCategoryVideo
fields = ('category', )
class VideosDetailsListSerializer(serializers.ModelSerializer):
category = serializers.SerializerMethodField()
class Meta:
model = Video
fields = ('id', 'create_date', 'category')
def get_category(self, data):
cate = VideoCategoryVideo.objects.filter(video=data.id)
category = VideoCategoryVideoSerializer(cate, many=True)
return category.data
result is:
"category": [
{
"category": 1
}]
but the expected result is
"category": [
{
"name": "cate_name"
}]
You can add a CharField to VideoCategoryVideoSerializer and specify the source of the value like this:
class VideoCategoryVideoSerializer(serializers.ModelSerializer):
name = serializers.CharField(source='category.name', read_only=True)
class Meta:
model = VideoCategoryVideo
fields = ('category', 'name')
This will tell the serializer to get the value for name from the related category.

Filtering the fields listed by the CreateModelMixin based on ForeignKey in Django Rest Framework

Hello, I am starting to learn Django Rest Framework, i have come across a problem, that i couldn't solve, that is described below:
I have defined three models in models.py:
Endpoint Model
class Endpoint(models.Model):
name = models.CharField(max_length=128)
created_by = models.CharField(max_length=128)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
def __str__(self) -> str:
return self.name
MLAlgorithm model:
class MLAlgorithm(models.Model):
name = models.CharField(max_length=128)
created_by = models.CharField(max_length=128)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
parent_endpoint = models.ForeignKey('Endpoint', on_delete=models.CASCADE, related_name="mlalgorithms")
def __str__(self) -> str:
return self.name
ABTest model:
class ABTest(models.Model):
title = models.CharField(max_length=1000)
created_by = models.CharField(max_length=128)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
parent_endpoint = models.ForeignKey('Endpoint', on_delete=models.CASCADE, related_name="abtests")
parent_mlalgorithm_1 = models.ForeignKey('MLAlgorithm', on_delete=models.CASCADE, related_name="parent_mlalgorithm_1")
parent_mlalgorithm_2 = models.ForeignKey('MLAlgorithm', on_delete=models.CASCADE, related_name="parent_mlalgorithm_2")
def __str__(self) -> str:
return self.title
and defined their serializers:
Endpoint Serializer:
class EndpointSerializer(serializers.ModelSerializer):
class Meta:
model = Endpoint
read_only_fields = ("id", "name", "created_by", "created_at")
fields = read_only_fields
MLAlgorithm Serializer:
class MLAlgorithmSerializer(serializers.ModelSerializer):
class Meta:
model = MLAlgorithm
read_only_fields = (
"id", "name", "created_by", "created_at", "parent_endpoint")
fields = read_only_fields
ABTest Serializer:
class ABTestSerializer(serializers.ModelSerializer):
class Meta:
model = ABTest
read_only_fields = ("id", "created_at")
fields = (
"id", "title", "created_by", "created_at", "parent_endpoint", "parent_mlalgorithm_1", "parent_mlalgorithm_2")
Then i created a viewset for the ABTest:
class ABTestViewSet(viewsets.GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.RetrieveModelMixin):
serializer_class = ABTestSerializer
queryset = ABTest.objects.all()
My problem is in the ABTestView:
for example, i have created two endpoints, and each endpoint has two algorithms:
endpoint_1:
algorithm_1
algorithm_2
endpoint_2:
algorithm_3
algorithm_4
but when i select a specific endpoint in the view, i want only the specific algorithms to be shown not all the algorithms available in the database
enter image description here
i don't know how to force algorithm filtering in the view, should i filter the algorithms by their endpoints in the view or before serialization, unfortunately i am struggling to implement it.
Thank you in advance.

serialize multiple related models

I am just learning django and rest-framework.
I have three models User, UserHospital and Timeslots. User is having time schedule for hospitals. I am requesting for users all details with related hospitals which displays hospital details along with timeslots. Want to represent user details in below format.
Whats wrong in my code?
Using viewsets and serializers it can be possible or i have to try another way?
{
"first_name": "abc",
"last_name": "xyz",
"mobile_number":1111111111,
"related_hospitals": [{
"id": 1,
"name": "bbbb"
"timeslot": [
{
"day": "TUE",
"start_time": "09:00:00",
"end_time": "15:00:00"
},
{
"day": "WED",
"start_time": "10:00:00",
"end_time": "20:00:00"
}
]
},
{
"id": 2,
"name": "ccc"
"timeslot": []
}]
}
created Models as below :
class Users(models.Model):
mobile_number = models.BigIntegerField()
first_name = models.CharField(max_length=255, null=True)
last_name = models.CharField(max_length=255, null=True)
class TimeSlots(BaseAbstract):
DAYS = (
('SUN', 'sunday'),
('MON', 'Monday'),
('TUE', 'tuesday'),
('WED', 'wednesday'),
('THU', 'thursday'),
('FRI', 'friday'),
('SAT', 'saturday'),
)
STATUS = (
(1, 'HOLIDAY'),
(2, 'ON_LEAVE'),
(3, 'AVAILABLE'),
(4, 'NOT_AVAILABLE')
)
DEFAULT_STATUS = 3
DEFAULT_DAY = "SUN"
day = models.CharField(default=DEFAULT_DAY, choices=DAYS, max_length=20)
start_time = models.TimeField()
end_time = models.TimeField()
status = models.SmallIntegerField(default=DEFAULT_STATUS, choices=STATUS)
class UserHospital(BaseAbstract):
user = models.ForeignKey('users.Users', on_delete=models.SET_NULL, null=True)
name = models.(Hospital,CharField(max_length=255, null=True)
timeslots = models.ManyToManyField(TimeSlots)
I have tried:
class TimeslotSerializer(serializers.ModelSerializer):
class Meta:
model = TimeSlots
fields = ('day', 'start_time', 'end_time')
read_only_fields = ('id',)
class RelatedHospitalSerializer(serializers.ModelSerializer):
timeslot = TimeslotSerializer(many=True)
class Meta:
model = UserHospital
fields = ('name', 'timeslot')
read_only_fields = ('id',)
class UserDetailsSerializer(serializers.ModelSerializer):
related_hospitals = serializers.SerializerMethodField()
def get_related_hospitals(self, obj):
hospitalData = []
if UserHospital.objects.all().filter(user=obj).exists():
hospitalData = UserHospital.objects.all().filter(user=obj)
return RelatedHospitalSerializer(hospitalData).data
class Meta:
model = Users
fields = ('first_name', 'last_name','mobile_number','related_hospitals')
read_only_fields = ('id', 'related_hospitals')
class UserDetailsViewset(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet):
queryset = Users.objects.all()
serializer_class = UserDetailsSerializer
def get_queryset(self):
userid = self.request.query_params.get('userid')
if userid is not None:
userData = Users.objects.filter(user=userid)
return userData
else:
return Users.objects.all()
whats wrong with my code ?
I would recommend using related_name parameter of models.ForeignKey, ..ManytoMany field etc
For example,
def Hospital(models.Model):
user = models.ForeignKey(....., related_name="hospitals")
...
def HospitalSerializer(models.Model):
...
def UserSerializer(Hyperlinkedmodelserializer ...(or other):
hospitals = HospitalSerializer(many=True)
class Meta:
....
Note: The use of "hospitals" ....
This will automatically allow one to get the result of a
UserSerializer(userModel, context={'request':request}).data ...
in your desired format

How to count deep relationship fields with Django?

How could I count the relationship of the models below?
class Client(models.Model):
name = models.CharField(max_length=150)
class Pet(models.Model):
client = models.ForeignKey(Client, related_name='pet')
name = models.CharField(max_length=150)
class Photo(models.Model):
pet = models.ForeignKey(Pet, related_name='photo')
photo = models.ImageField(storage=DIR)
I would like to return the total pet and total photos taken of all pets dr to a single customer client, with the following answer:
[
{
"name": "john",
"totalPet": 3, // imagine 10 photos were taken of each pet
"totalPhoto": 30,
},
{
"name": "Mary",
"totalPet": 2, // imagine that 10 photos were taken of one and 5
// of another pet
"totalPhoto": 15,
},
]
My serializer is as follows:
class ClientSerializer(ModelSerializer):
totalPet = serializers.SerializerMethodField()
def get_totalPet(self, obj):
return obj.pet.count()
class Meta:
model = Client
fields = ('name', 'totalPet')
As can be observed, I can total the amount of pets for each customer, but I can't find a way to total the photos of all pets of a customer.
What would be the best way to do this photo count?
You can perform a filter on Photo model with your client.pet queryset, using the __in lookup.
At first, I would define a custom QuerySet for our Photo model:
from django.db import models
class PhotoQuerySet(models.QuerySet):
def for_client(self, client):
# Get all related pets to the current client
client_pets = client.pet.all()
# Filter Photos that are linked with these pets
return self.filter(pet__in=client_pets)
And then inside the model:
class Photo(models.Model):
...
objects = PhotoQuerySet.as_manager()
This will allow you to do the following: Photo.objects.for_client(client=...)
After that, you can use this method in the serializer:
class ClientSerializer(ModelSerializer):
total_pets = serializers.SerializerMethodField()
total_photos = serializers.SerializerMethodField()
def get_total_pets(self, obj):
return obj.pet.count()
def get_total_photos(self, obj):
# Calling our newly created method and aggregating count
return Photo.objects.for_client(client=obj).count()
class Meta:
model = Client
fields = ('name', 'total_pets', 'total_photos')

Resources