Query set is not JSON serializable - django

I am trying to create an endpoint but I keep getting an error: "Object of type model is not JSON serializable".
I tried passing it through list() and json.dumps() but it int work. I tried printing the query and it was like
[<Lead: Test>, <Lead: user2>, <Lead: user3>, <Lead: user4>]
Here is the code I wrote:
def leads(request):
full = []
lead_list = list(Lead.objects.all())
print(lead_list)
for i in lead_list:
full.append(json.dumps(i))
print(full)
return JsonResponse(list(full), safe=False)
Here are a few question I looked at and tried:
Output Django queryset as JSON
I tried serializing it with serializer but the response was like this:
"[{\"model\": \"leads.lead\", \"pk\": 1, \"fields\": {\"first_name\": \"Test\", \"last_name\": \"User\", \"age\": 25, \"city\": \"kolkata\", \"country\": \"India\", \"email\": \"ankr#gmail.com\", \"agent\": 1, \"status\": \"Potential\"}}, {\"model\": \"leads.lead\", \"pk\": 2, \"fields\": {\"first_name\": \"user2\", \"last_name\": \"test2\", \"age\": 44, \"city\": \"Mumbai\", \"country\": \"India\", \"email\": \"test2#gmail.com\", \"agent\": null, \"status\": \"prospect\"}}, {\"model\": \"leads.lead\", \"pk\": 4, \"fields\": {\"first_name\": \"user3\", \"last_name\": \"test3\", \"age\": 19, \"city\": \"Paris\", \"country\": \"France\", \"email\": \"test3#gmail.com\", \"agent\": null, \"status\": \"Prospect\"}}, {\"model\": \"leads.lead\", \"pk\": 8, \"fields\": {\"first_name\": \"user4\", \"last_name\": \"test4\", \"age\": 33, \"city\": \"London\", \"country\": \"UK\", \"email\": \"test4#gmail.com\", \"agent\": null, \"status\": \"Converted\"}}]"

you need to serialize your queryset then use JsonResponse.
class LeadSerializer(serializers.ModelSerializer):
class Meta:
model = Lead
fields = '__all__'
def leads(request):
qs= Lead.objects.all()
serializer = LeadSerializer(qs,many=True)
return JsonResponse(serializer.data, safe=False)
PS: since i don't know the columns in your Lead Model i am using ModelSerializer for serializing, However you can write your own custom serializer using serializers.Serializer also by mentioning your each column like
class LeadSerializer(serializers.Serializer):
name = serializer.CharField(max_length=10)
column_1 = serializer.IntegerField()

Related

Show ISO date values in string form

So I was trying to get what months that an insurer filed a claim. However, the values were in ISO Form. I was trying to show it in string form. Instead of showing 2021-01-01, show January; 2021-01-02, show February
Here's the sample get data
Data in image form
{
"Month": [
"2021-04-01T00:00:00+08:00",
"2021-02-01T00:00:00+08:00",
"2021-03-01T00:00:00+08:00"
],
"Claim(s)": {
"": 18,
"Bank Transfer": 5,
"CAR": 1,
"home": 5,
"Credit": 7,
"Energy": 1,
"health": 38,
"\"health\"": 5
}
}
I'd like to change the ISO date form into string form instead.
Here is my code in Views
class GetClaimsCompare_year(APIView):
def get_claim_count(self, claims_data, claim_type):
claims_count = claims_data.filter(claim_type = claim_type).count()
return claims_count
def get_claims_type(self, claim_per_month):
return claim_per_month.claim_type
def get(self, request):
today = datetime.now()
claims_data = Claims.objects.filter(modified_at__year =today.year)
claim_per_month = claims_data.annotate(month = TruncMonth('modified_at')).values('month').annotate(claim_type=Count('id'))
labels = []
claims_type = list(set(map(self.get_claims_type, claims_data)))
final = {}
for claims in claim_per_month:
labels.append(claims['month'])
for claim_type in claims_type:
final[claim_type] = self.get_claim_count(claims_data, claim_type)
context = {
'Month':labels,
'Claim(s)':final
}
return Response(context)
Simple call strftime on the datetime that you get
...
for claims in claim_per_month:
month_label = claims['month'].strftime('%B')
labels.append(month_label)
...

How to display all dates for multiple model annotations in django

So I'm working on a website, and I want to have some kind of a summary page to display the data that I have. Let's say I have these models:
class IceCream(TimeStampedModel):
name = models.CharField()
color = models.CharField()
class Cupcake(TimeStampedModel):
name = models.CharField()
icing = models.CharField()
So on this page, users will be able to input a date range for the summary. I'm using DRF to serialize the data and to display them on the view actions. After I receive the filter dates, I will filter out the IceCream objects and Cupcake objects using the created field from TimeStampedModel.
#action(detail=False, methods=['get'])
def dessert_summary(self, request, **kwargs):
start_date = self.request.query_params.get('start_date')
end_date = self.request.query_params.get('end_date')
cupcakes = Cupcake.objects.filter(created__date__range=[start_date, end_date])
ice_creams = IceCream.objects.filter(created__date__range=[start_date, end_date])
After filtering, I want to count the total cupcakes and the total ice creams that is created within that period of time. But I also want to group them by the dates, and display the total count for both ice creams and cupcakes based on that date. So I tried to annotate the querysets like this:
cupcakes = cupcakes.annotate(date=TruncDate('created'))
cupcakes = cupcakes.values('date')
cupcakes = cupcakes.annotate(total_cupcakes=Count('id'))
ice_creams = ice_creams.annotate(date=TruncDate('created'))
ice_creams = ice_creams.values('date')
ice_creams = ice_creams.annotate(total_ice_creams=Count('id'))
So I want the result to be something like this:
{
'summary': [{
'date': "2020-09-24",
'total_ice_creams': 10,
'total_cupcakes': 7,
'total_dessert': 17
}, {
'date': "2020-09-25',
'total_ice_creams': 6,
'total_cupcakes': 5,
'total_dessert': 11
}]
}
But right now this is what I am getting:
{
'summary': [{
'cupcakes': [{
'date': "2020-09-24",
'total_cupcakes': 10,
}, {
'date': "2020-09-25",
'total_cupcakes': 5,
}],
'ice_creams': [{
'date': "2020-09-24",
'total_ice_creams': 7,
}, {
'date': "2020-09-27",
'total_ice_creams': 6,
}]
}]
}
What I want to ask is how do I get all the dates of both querysets, sum the ice creams and cupcakes, and return the data like the expected result? Thanks in advance for your help!
So here's what you can do:
gather all icecream/cupcakes count data into a dictionary
icecream_dict = {obj['date']: obj['count'] for obj in ice_creams}
cupcakes_dict = {obj['date']: obj['count'] for obj in cupcakes}
create a sorted list with all the dates
all_dates = sorted(set(list(icecream_dict.keys()) + list(cupcakes_dict.keys())))
create a list with items for each date and their count
result = []
for each_date in all_dates:
total_ice_creams = icecream_dict.get(each_date, 0)
total_cupcakes = cupcakes_dict.get(each_date, 0)
res = {
'date': each_date,
'total_ice_creams': total_ice_creams,
'total_cupcakes': total_cupcakes,
'total_dessert': total_ice_creams + total_cupcakes
}
result.append(res)
# check the result
print(result)
Hint: If you plan to add more desert-like models, consider have a base model Desert that you could query directly instead of querying each desert type model.

how to remove extra squared brackets in a response on djago rest framework

I created a stored function in PostgreSQL returns a table, and called that function in a Django-rest-framework like this:
def getSomeFunc(self):
with connection.cursor() as cursor:
cursor.execute(f'select json_agg(myfunctionpsql) from myfunctionpsql')
table = cursor.fetchall()
return table
this function is called in a views file, like a code below:
class myview(views.APIView):
def get(self, request):
fund = getSomeFunc(self)
return Response({'data': fund}, status=status.HTTP_200_OK)
well the response is like this:
{
"data": [
[ // I want to delete this
[ // I want to delete this
{
"id": 21,
"somedata": "FIX A",
"somedata": "FIX A",
"sometag": 0.95,
"somdata": "005.119.745/0001-98",
"somedatayear": 1.57,
"somedata12": 4.11,
"somedata36": 19.58,
"somedata60": 51.9,
"datarisk": 0
}
]// I want delete this
]// I want to delete this
]
}
and I need response below:
{ "data": [{
"id": 21,
"somedata": "FIX A",
"somedata": "FIX A",
"sometag": 0.95,
"somdata": "005.119.745/0001-98",
"somedatayear": 1.57,
"somedata12": 4.11,
"somedata36": 19.58,
"somedata60": 51.9,
"datarisk": 0
}]
}
I try this:
class myview(views.APIView):
def get(self, request):
fund = getSomeFunc(self)
reps = str(fund)[1:-1]
return Response({'data': resp}, status=status.HTTP_200_OK)
but the response is all converted and return in a string, how to delete extra squared brackets, in a response.
regards.
If your variable fund is:
[
[
[
{
"id": 21,
"somedata": "FIX A",
"somedata": "FIX A",
"sometag": 0.95,
"somdata": "005.119.745/0001-98",
"somedatayear": 1.57,
"somedata12": 4.11,
"somedata36": 19.58,
"somedata60": 51.9,
"datarisk": 0
}
]
]
]
you can write a generator to flatten the items into a simple list, because I'm assuming that there could be multiple objects in your list and using indices to slice the list would be dangerous.
try this recursive generator:
def flatten_list(data):
if isinstance(data, list):
for item in data:
yield from flatten_list(item)
else:
yield data
and call it like this:
list(flatten_list(fund))
example:
data = [[[1, 4], 2], 3]
list(flatten_list(data))
# result: [1, 4, 2, 3]

How to format json response in django?

I am retrieving data from multiple tables in Django.
my current response is :
{
"status": 0,
"message": "Client details retrived successfully...!!!",
"results": [
{
"id": 11,
"client_id": "CL15657917080578748000",
"client_name": "Pruthvi Katkar",
"client_pan_no": "RGBB004A11",
"client_adhar_no": "12312312313",
"legal_entity_name": "ABC",
"credit_period": "6 months",
"client_tin_no": 4564565,
"client_email_id": "abc#gmail.com",
"head_office_name": "ABC",
"office_name": "asd234",
"office_email_id": "zxc#gmail.com",
"office_contact": "022-27547119",
"gst_number": "CGST786876876",
"office_country": "India",
"office_state": "gujrat",
"office_district": "vadodara",
"office_taluka": "kachh",
"office_city": "vadodara",
"office_street": "New rode 21",
"office_pincode": 2344445,
"contact_person_name": "prasad",
"contact_person_designation": "DM",
"contact_person_number": "456754655",
"contact_person_email": "asd#gmail.com",
"contact_person_mobile": "5675545654",
"created_at": "2019-08-14T14:08:28.057Z",
"created_by": "Prathamseh",
"updated_at": "2019-08-14T14:08:28.057Z",
"updated_by": "prasad",
"is_deleted": false
},
{
"id": 11,
"user_id": "CL15657917080578748000",
"bank_details_id": "BL15657917080778611000",
"bank_name": "Pruthvi",
"branch": "vashi",
"ifsc_code": "BOI786988",
"account_number": 56756765765765,
"account_name": "Pruthvi",
"is_deleted": false
},
{
"id": 10,
"document_details_id": "DL15657917080808598000",
"user_id": "CL15657917080578748000",
"document_type": "Pruthvi ID",
"document": "www.sendgrid.com/pan",
"is_deleted": false
}
]
}
Expected Response :
I am getting the queryset form db in models.py and i am sending it to the views.py and i am iterating over the dict but not getting the expected response.
views.py
#csrf_exempt
def get_client_details(request):
try:
# Initialising lists for storing results
result = []
temp_array = []
# Getting data from request body
client_master_dict = json.loads(request.body)
# Response from get client data
records = ClientDetails.get_client_data(client_master_dict)
# Create response object
# Iterating over the records object for getting data
for i in range(len(records)):
# Converting the querysets objects to json array format
record_result_list = list(records[i].values())
# If multiple records are present
if(len(record_result_list) > 1):
for j in range(len(record_result_list)):
user_info = record_result_list[j]
temp_array.append(user_info)
result.append(temp_array)
temp_array=[]
# For single record
else:
result.append(record_result_list[0])
# Success
returnObject = {
"status" : messages.SUCCESS,
"message" : messages.CLIENT_RETRIVE_SUCCESS,
"results" : result
}
return JsonResponse(returnObject,safe=False)
I think the issue might be in my inner for loop, can anyone help me out with this, is there any way to iterate over the nested JSON object.
Models.py
#classmethod
def get_client_data(cls, client_master_dict):
try:
response_list = []
client_id = client_master_dict['client_id']
client_details = cls.objects.filter(client_id = client_id,is_deleted = False)
bank_details = BankDetails.objects.filter(user_id = client_id,is_deleted = False)
document_details = DocumentDetails.objects.filter(user_id = client_id,is_deleted = False)
response_list.append(client_details)
response_list.append(bank_details)
response_list.append(document_details)
return response_list
except(Exception) as error:
print("Error in get_client_data",error)
return False
Here i'm fetching data from 3 tables and adding it into list.
After printing the data on console i am getting :
[{'id': 11, 'client_id': 'CL15657917080578748000', 'client_name': 'Pruthvi Katkar', 'client_pan_no': 'RGBB004A11', 'client_adhar_no': '12312312313', 'legal_entity_name': 'ABC', 'credit_period': '6 months', 'client_tin_no': 4564565, 'client_email_id': 'abc#gmail.com', 'head_office_name': 'ABC', 'office_name': 'asd234', 'office_email_id': 'zxc#gmail.com', 'office_contact': '022-27547119', 'gst_number': 'CGST786876876', 'office_country': 'India', 'office_state': 'gujrat', 'office_district': 'vadodara', 'office_taluka': 'kachh', 'office_city': 'vadodara', 'office_street': 'New rode 21', 'office_pincode': 2344445, 'contact_person_name': 'prasad', 'contact_person_designation': 'DM', 'contact_person_number': '456754655', 'contact_person_email': 'asd#gmail.com', 'contact_person_mobile': '5675545654', 'created_at': datetime.datetime(2019, 8, 14, 14, 8, 28, 57874, tzinfo=<UTC>), 'created_by': 'Prathamseh', 'updated_at': datetime.datetime(2019, 8, 14, 14, 8, 28, 57874, tzinfo=<UTC>), 'updated_by': 'prasad', 'is_deleted': False}]
[{'id': 11, 'user_id': 'CL15657917080578748000', 'bank_details_id': 'BL15657917080778611000', 'bank_name': 'Pruthvi', 'branch': 'vashi', 'ifsc_code': 'BOI786988', 'account_number': 56756765765765, 'account_name': 'Pruthvi', 'is_deleted': False}]
[{'id': 10, 'document_details_id': 'DL15657917080808598000', 'user_id': 'CL15657917080578748000', 'document_type': 'Pruthvi ID', 'document': 'www.sendgrid.com/pan', 'is_deleted': False}]
Did you check the output of record_result_list? You can outright tell their if it's recovering the data in the format you requested. Try the printing to screen method to debug.
As far as I cam see, the expected output and the hierarchy of results for bank details are not matching. I don't know how you are handling the hierarchy. Are you directly taking it from JSON as the hierarchy? Or are you just taking the data and creating hierarchy in the expected output?

Django rest api framework ModelSerializer

I have ModelSerrializer:
class ProbeParamsSerializer(serializers.ModelSerializer):
modems = ModemParamsSerializer(many=True, required=True)
net_adapters = NetworkAdapterParamsSerializer(many=True, required=True)
class Meta:
model = ProbeParams
fields = (
'probe', 'modems', 'net_adapters', 'ram_free', 'sd_free', 'num_measurement_files', 'num_audio_files',
'cpu_t',
'cpu_load', 'latitude', 'longitude', 'navigation_status', 'info_updated')
I perform:
probe_params_serializer = ProbeParamsSerializer(data=item)
Item look as:
{
"info_updated": 56483476,
"config_updated": 325687,
"ram_free": 800,
"sd_free": 2000,
"num_measurement_files": 8,
"num_audio_files": 2,
"cpu_temp": 38.7,
"cpu_load": 58.4,
"latitude": 0,
"longitude": 0,
"modems": [
Note parameter: cpu_temp. The model is called сpu_t and the report comes under the same name cpu_temp. So naturally when performing validation, I get an error -
"this field (сpu_t) is required".
I understand which is why there is an error, but I do not know how to link these two names. It is necessary to make the value of the parameter cpu_temp are stored in a parameter cpu_t.
Help me please.