Django Rest framework- getting total number of rows - django

I would like to output a field that counts the number of Candidat in Candidat Model. I am currently using the following serializer:
class CountCSerializer(serializers.ModelSerializer):
user_count = serializers.SerializerMethodField()
class Meta:
model = Candidat
fields = ( 'user_count',)
def get_user_count(self, obj):
return Candidat.objects.count()
and the following api:
class CountCViewSet(ModelViewSet):
queryset = Candidat.objects.all()
serializer_class = CountCSerializer
urls.py:
router.register(r'CountC', CountCViewSet, base_name='users-count')
models.py:
class Candidat(models.Model):
name = models.CharField(max_length=50)
lastName = models.CharField(max_length=50)
email = models.CharField(max_length=50)
tel = models.CharField(max_length=50, default=0)
password = models.CharField(max_length=50)
civility = models.CharField(max_length=50)
birthDate = models.DateField(auto_now=False, auto_now_add=False)
gouvernorate = models.CharField(max_length=50)
def __str__(self):
return "Candidat: {}".format(self.name)
But im getting nothing!
Any help in the matter would be much appreciated.

I was looking for the same and noticed that ModelViewSet generates a count by default. You can see it by navigating to the endpoint in a browser or checking the response body in Postman.
Example:
{
"count": 10,
"next": null,
"previous": null,
"results": [
{
"id": 62,
"entity_name": "The company name",
"entity_website_url": "thecompany.com",
"entity_city": "Los Angeles",
"entity_state": "CA"
}
...
]
}

Related

Writable nested serializer method getting an Error while posting a request

models.py
class Client(models.Model):
client_id = models.AutoField(unique=True, primary_key=True)
org = models.ForeignKey(Organisation, on_delete=models.CASCADE, related_name='org',null=True)
product = models.ManyToManyField(Product,related_name='product')
client_name = models.CharField(max_length=100)
client_code = models.CharField(max_length=20)
client_logo = models.ImageField(upload_to=upload_to,storage=DownloadableS3Boto3Storage, null=True, blank=True)
currency = MoneyField(max_digits=10, decimal_places=2, default_currency='INR', null=True)
billing_method = models.CharField(max_length=40)
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
email_id = models.EmailField(max_length=100)
contact_no = models.CharField(max_length=20)
mobile_no = models.CharField(max_length=20)
description = models.TextField(max_length=500)
street_address = models.CharField(max_length=250)
city = models.CharField(max_length=50)
state = models.CharField(max_length=50)
country = models.CharField(max_length=50)
pincode = models.CharField(max_length=10)
industry = models.CharField(max_length=100)
company_size = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_active = models.IntegerField(default=0, choices=STATUS_CHOICES)
class Meta:
db_table = "client_master"
def __str__(self):
return self.client_name
serializers.py
class Client_Serializers(serializers.ModelSerializer):
#product_name = Product_Serializers(many=True)
product = Product_Serializers(many=True)
class Meta:
model = Client
fields = ('client_id','currency','billing_method','first_name','last_name','description','street_address','city','state','country','pincode','industry','company_size','client_name', 'contact_no','mobile_no', 'email_id','client_logo','client_code','product',)
def create(self, validated_data):
products_data = validated_data.pop('product')
product = Product.objects.create(**validated_data)
for product_data in products_data:
Product.objects.create(product=product, **product_data)
return product
Data receiving on GET method
{
"client_id": 3,
"currency": "0.05",
"billing_method": "credit card",
"first_name": "career",
"last_name": "lab",
"description": "NA",
"street_address": "tiliconveli",
"city": "tirunelveli",
"state": "tamilnadu",
"country": "India",
"pincode": "600200",
"industry": "software",
"company_size": 100,
"client_name": "techfetch",
"contact_no": "1234567890",
"mobile_no": "1234567890",
"email_id": "icanio#gamil.com",
"client_logo": "https://icanio-project-management.s3.amazonaws.com/client_logo/sup_bat_fDauRxK.jpg",
"client_code": "TFH",
"product": [
{
"product_id": 5,
"product_name": "time"
}
]
}
But while posting it in the same format it is not getting posted, showing like
{
"status": "error",
"code": 400,
"data": {
"product": [
"This field is required."
]
},
"message": "success"
}
Views.py for reference
class Client_Viewset(DestroyWithPayloadMixin,viewsets.ModelViewSet):
renderer_classes = (CustomRenderer, )
queryset=models.Client.objects.all()
serializer_class=serializers.Client_Serializers
parser_classes = [MultiPartParser, FormParser]
filter_fields = (
'client_id',
'client_name',
'client_code',
'org_id',
)
How can I post the same data which I get in the GET request of Product field. Please help me resolve this as I was stuck in there for two days. I tried so many ways and end up not getting posted.
Product model
class Product(models.Model):
product_id = models.AutoField(unique=True, primary_key=True)
product_name = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = "product_master"
def __str__(self):
return self.product_name
product serializer
class Product_Serializers(serializers.ModelSerializer):
class Meta:
model = Product
fields = ('product_id','product_name',)
From your code, the Client_Serializers is for Client model but the create method is not creating any Client object.
Client_Serializers should be something on these lines -
class Client_Serializers(serializers.ModelSerializer):
product = Product_Serializers(many=True)
class Meta:
model = Client
fields = ('client_id','currency','billing_method','first_name','last_name','description','street_address','city','state','country','pincode','industry','company_size','client_name', 'contact_no','mobile_no', 'email_id','client_logo','client_code','product',)
def create(self, validated_data):
products_data = validated_data.pop('product')
client = Client.objects.create(**validated_data) # Create a client object
for product_data in products_data:
Product.objects.create(client=client, **product_data)
return client

Model with foreign keys taking ~90 seconds per query (foreign key model / serializer problem I think)

I'm having trouble with both my serializer and models for a table using foreign keys. I have a view for my Cost table ( see below ) that when I query, I get the following output in about 300-400 ms :
[
{
"id": 12,
"hours1": 10,
"hours2": 0,
"hours3": 0,
"hours4": 0,
"date": "2021-07-12",
"employee": 14,
"job1": 417,
"job2": 671,
"job3": 671,
"job4": 671
},
{
"id": 13,
"hours1": 8,
"hours2": 0,
"hours3": 0,
"hours4": 0,
"date": "2021-07-12",
"employee": 10,
"job1": 411,
"job2": 671,
"job3": 671,
"job4": 671
}
]
The employee, job1, job2, job3, job4 fields are foreign key IDs that I wish to see their main/primary value for (in this case, names!). I've played around with a serializer to achieve this, however, the problem is that it takes about 90 seconds per query and keeps getting longer!
[
{
"id": 12,
"employee": {
"employee_name": "Person 1"
},
"job1": {
"No": "30201"
},
"job2": {
"No": "N/A"
},
"job3": {
"No": "N/A"
},
"job4": {
"No": "N/A"
},
"hours1": 10,
"hours2": 0,
"hours3": 0,
"hours4": 0,
"date": "2021-07-12"
},
{
"id": 13,
"employee": {
"employee_name": "Person 2"
},
"job1": {
"No": "30101"
},
"job2": {
"No": "N/A"
},
"job3": {
"No": "N/A"
},
"job4": {
"No": "N/A"
},
"hours1": 8,
"hours2": 0,
"hours3": 0,
"hours4": 0,
"date": "2021-07-12"
}
]
My schema and serializers:
class Employee(models.Model):
employee_name = models.CharField(max_length=200, unique=True)
employee_email = models.CharField(max_length=200)
employee_navID = models.CharField(max_length=200)
employee_department = models.CharField(max_length=200)
joining_date = models.DateField()
leaving_date = models.DateField()
weekly_salary = models.IntegerField(default=0)
car_allowance = models.IntegerField()
national_insurance = models.IntegerField()
pension = models.IntegerField()
created_at = models.DateField(auto_now_add=True)
#property
def status(self):
if(self.leaving_date >= date.today()):
return "active"
else:
return "inactive"
#property
def employee_cost(self):
return self.weekly_salary + self.car_allowance + self.national_insurance + self.pension
class Meta:
verbose_name_plural = "Employees"
def __str__(self):
return self.employee_name
class ExcelJobsList(models.Model):
No = models.CharField(max_length=200)
Description = models.CharField(max_length=200)
Custom_No = models.CharField(max_length=200)
Sell_to_Name = models.CharField(max_length=200)
Status = models.CharField(max_length=200)
Person_Responsible = models.CharField(max_length=200)
Region_Code = models.CharField(max_length=200)
Market_Code = models.CharField(max_length=200)
Agreement_Form_Code = models.CharField(max_length=200)
Technology_Code = models.CharField(max_length=200)
secondappr_Code = models.CharField(max_length=200)
Search_Description = models.CharField(max_length=200)
Work_in_Progress_Status = models.CharField(max_length=200)
Job_Category = models.CharField(max_length=200)
Project_Manager = models.CharField(max_length=200)
Sales_Person = models.CharField(max_length=200)
Payment_Terms_Code = models.CharField(max_length=200)
First_Agreement_No = models.CharField(max_length=200)
No_of_Service_Agreements = models.CharField(max_length=200)
CRM_Reference = models.CharField(max_length=200)
class Meta:
verbose_name_plural = "Jobs"
def __str__(self):
return self.No
These are populated with a unique list of employees and jobs respectively. I then use to this to create a basic timesheet form where users can assign hours to a job (up to 4). This is posted to the below model, which has foreign keys to the employee and job table.
class Cost(models.Model):
employee = models.ForeignKey(
Employee, default=1, on_delete=SET_DEFAULT)
job1 = models.ForeignKey(ExcelJobsList, default=0, on_delete=SET_DEFAULT)
hours1 = models.IntegerField()
job2 = models.ForeignKey(
ExcelJobsList, default=0, on_delete=SET_DEFAULT, related_name="job2")
hours2 = models.IntegerField()
job3 = models.ForeignKey(
ExcelJobsList, default=0, on_delete=SET_DEFAULT, related_name="job3")
hours3 = models.IntegerField()
job4 = models.ForeignKey(
ExcelJobsList, default=0, on_delete=SET_DEFAULT, related_name="job4")
hours4 = models.IntegerField()
date = models.DateField()
This produces the follow output after I've selected the fields I wanted from a serializer:
class JobModelSerializer(serializers.ModelSerializer):
class Meta:
model = ExcelJobsList
fields = ['No']
class EmployeeModelSerializer(serializers.ModelSerializer):
class Meta:
model = Employee
fields = ['employee_name']
class CostModelSerializer(serializers.ModelSerializer):
employee = EmployeeModelSerializer()
job1 = JobModelSerializer()
job2 = JobModelSerializer()
job3 = JobModelSerializer()
job4 = JobModelSerializer()
class Meta:
model = Cost
fields = ('__all__')
class CostListFilter(filters.FilterSet):
class Meta:
model = Cost
fields = {
'employee': ['exact'],
}
class JoinedFilterCostList(generics.ListAPIView):
queryset = Cost.objects.filter()
serializer_class = CostModelSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = CostListFilter
I've tried using to_field= 'xyz', however, this ends up returning null so either I'm missing something in my model or the serializer isn't set up correctly for it... or both!
Any help would be much really appreciated.
The slowness is caused by having to hit the database 4 times per Cost instance to get all the related ExcelJobsList.
To avoid this and make it more efficient, you can use select_related to the related ExcelJobsList like this:
class JoinedFilterCostList(generics.ListAPIView):
...
queryset = Cost.objects.select_related('job1', 'job2', 'job3', 'job4')
...
These should in turn end up with just one query, with inner joins on the related ExcelJobsList.

Django rest framework: omit dict where field is empty

I'm building a rest API for a media library.
Here are some of my python code, I have simplify them a bit, so only the necessary code is included, to have a better overview about the current problem.
models.py:
class MediaSeries(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(blank=True)
class MediaSeriesEntries(models.Model):
serie = models.ForeignKey(MediaSeries, related_name='series',
db_column='seriesID', null=True,
on_delete=models.SET_NULL)
file = models.ForeignKey(MediaFiles, related_name='serie_set',
db_column='fileID', null=True,
on_delete=models.SET_NULL)
class MediaFiles(models.Model):
youtube = models.CharField(max_length=300, blank=True)
name = models.CharField(max_length=300)
screeningPause = models.BooleanField(default=0)
duration = models.BigIntegerField(default=0)
creatingDate = models.DateTimeField(default=now)
class Library(models.Model):
media = models.ForeignKey(MediaFiles, related_name='library_set',
db_column='fileID', null=True,
on_delete=models.SET_NULL)
visits = models.IntegerField(default=0)
likes = models.IntegerField(default=0)
views.py:
class LibraryMediaFilter(filters.FilterSet):
class Meta:
model = Library
fields = ['media__name', 'media__duration',
'media__youtube', 'media__creatingDate']
class LibraryMediaViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows the library to be viewed.
Example ordering:
http://127.0.0.1:8000/api/library-media/?ordering=media__creatingDate
"""
queryset = Library.objects.all() \
.exclude(media__youtube="").exclude(media__screeningPause=True)
serializer_class = LibraryMediaSerializer
pagination_class = LibraryResultsSetPagination
filter_backends = (filters.DjangoFilterBackend, OrderingFilter)
filterset_class = LibraryMediaFilter
ordering_fields = ['media__serie_set__serie__name', 'media__name',
'media__creatingDate', 'visits', 'likes']
serializers.py:
class LibraryMediaSerializer(serializers.ModelSerializer):
name = serializers.CharField(source='media.name', read_only=True)
duration = serializers.IntegerField(source='media.duration',
read_only=True)
youtube = serializers.CharField(source='media.youtube', read_only=True)
creatingDate = serializers.DateTimeField(source='media.creatingDate',
read_only=True)
serie_set = SeriesEntriesSerializer(source='media.serie_set',
read_only=True, many=True)
class Meta:
model = Library
fields = ('visits', 'likes', 'name', 'duration', 'youtube',
'creatingDate', 'serie_set')
When I call now the api with http://example.org/api/library-media/ I get this result:
{
"visits": 0,
"likes": 0,
"name": "example movie",
"duration": 9505000,
"youtube": "https://youtu.be/34345",
"creatingDate": "2013-01-01T01:00:00+01:00",
"serie_set": []
},
{
"visits": 0,
"likes": 0,
"name": "example serie",
"duration": 3436000,
"youtube": "https://youtu.be/z0c4rLCcyVE",
"creatingDate": "2013-01-01T01:00:00+01:00",
"serie_set": [
{
"name": "Das große Ganze",
"description": ""
}
]
},
Now I would like to filter against empty and not empty serie_set, with something like:
http://example.org/api/library-media/media__serie_set__isempty=true
or:
http://example.org/api/library-media/media__serie_set__isempty=false

django rest-framework serializer reverse relation

I am programming django based web site using django rest-framework.
I want to use rest-framework to get model's data.
this is my model.py
class TimeTable(models.Model):
subject_name = models.CharField(max_length=50)
subject_code = models.CharField(max_length=10, unique=True)
classification = models.CharField(max_length=50)
professor = models.CharField(max_length=50)
department = models.CharField(max_length=50)
credit = models.CharField(max_length=1)
year = models.CharField(max_length=4, default='2018')
semester = models.CharField(max_length=1, default='1')
def __str__(self):
return self.subject_code + '-' + self.subject_name
class Class(models.Model):
owner = models.ForeignKey(Profile, null=True)
timetable = models.ForeignKey(TimeTable, null=True)
grade = models.FloatField()
this is serializer.py
class TimeTableSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = TimeTable
fields = ('url', 'subject_name', 'subject_code', 'classification', 'professor', 'department', 'credit', 'year', 'semester')
class ClassSerializer(serializers.HyperlinkedModelSerializer):
timetables = TimeTableSerializer(read_only=True)
class Meta:
model = Class
fields = ('url','owner', 'timetable', 'grade', 'timetables')
I want to get JSON response Like this
(http://localhost:8000/api/classes/)
[
{
"url": "http://localhost:8000/api/classes/8/",
"owner": "http://localhost:8000/api/profiles/19/",
"timetable": "http://localhost:8000/api/timetables/3/",
"grade": 4.5
"timetables": {
"url": "http://localhost:8000/api/timetables/3/",
"subject_name": "Artificial Inteligence",
"subject_code": "3413513413",
"classification": "major",
"professor": "John Lee",
"department": "software",
"credit": "3",
"year": "2018",
"semester": "1"
}
}
]
but i got this
[
{
"url": "http://localhost:8000/api/classes/8/",
"owner": "http://localhost:8000/api/profiles/19/",
"timetable": "http://localhost:8000/api/timetables/3/",
"grade": 4.5
}
]
How Can I get TimeTable's JSON data in Class JSON??
class ClassSerializer(serializers.HyperlinkedModelSerializer):
timetable = TimeTableSerializer(read_only=True)
class Meta:
model = Class
fields = ('url','owner', 'timetable', 'grade')

Django REST Framework: define fields in nested object?

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')