How to make it by list comprehension - django-models

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.

Related

Count the no of movies in django rest framework

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.

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 add a snippet of category, used in a different snippet

How do I have a snippet of category be used in another snippet called resource? I want to have a list of Resources filtered by category and category is a snippet of its own. I'm getting this error when I try to create a Resource:
AttributeError at /admin/snippets/home/resource/add/
'ForwardManyToOneDescriptor' object has no attribute 'rel'
Here is my code:
class Resource(models.Model):
"""Snippet for Resources"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
resource_name = models.CharField(max_length=128, blank=False, null=True)
phone_number = models.CharField(max_length=12, blank=True, null=True)
website = models.URLField(blank=True, null=True)
info = RichTextField(blank=True, null=True)
category = models.ForeignKey('ResourceCategory', on_delete=models.CASCADE, null=True, blank=True)
panels = [
MultiFieldPanel(
[
FieldPanel("resource_name"),
FieldPanel("phone_number"),
],
heading="Resource information"
),
MultiFieldPanel(
[
FieldPanel('website')
],
heading="Links"
),
MultiFieldPanel(
[
FieldPanel('info')
],
heading="Info"
),
MultiFieldPanel(
[
InlinePanel("category", label="Category")
]
)
]
def __str__(self):
"""String representation of this class"""
return self.resource_name
class Meta:
verbose_name = "Resource"
verbose_name_plural = "Resources"
register_snippet(Resource)
class ResourceCategory(models.Model):
"""Snippet for Resources"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
category_name = models.CharField(max_length=128, blank=False, null=True)
panels = [
MultiFieldPanel(
[
FieldPanel('category_name')
],
heading="Category"
)
]
def __str__(self):
"""String representation of this class"""
return self.category_name
class Meta:
verbose_name = "Category"
verbose_name_plural = "Categories"
register_snippet(ResourceCategory)
The category field should use FieldPanel('category'), not InlinePanel. InlinePanel is for managing multiple child objects belonging to the snippet, but here a Resource only belongs to a single ResourceCategory.
(If you do intend to allow a resource to belong to multiple categories, you'll need to adjust your models so that Resource has a child model, containing a ParentalKey to Resource and a ForeignKey to ResourceCategory.)

Resources