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?
Related
I am trying to create a chat api, i have structured the messages model to look like this
class ChatMessage(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name="user")
sender = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name="sender")
reciever = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name="reciever")
message = models.CharField(max_length=10000000000)
is_read = models.BooleanField(default=False)
date = models.DateTimeField(auto_now_add=True)
Now i am trying to write the API view to get all messages that belongs only to me and the person that i am chatting with.
Let me elaborate: Let's say Destiny is texting Sammy, there would definitely be alot of messages that have been sent between me (Destiny) and the user (Sammy), so i want to get all that text.
This is the view that i have written to do this
class GetMessages(generics.ListAPIView):
serializer_class = MessageSerializer
def get_queryset(self):
sender_id = self.kwargs['sender_id']
reciever_id = self.kwargs['reciever_id']
messages = ChatMessage.objects.filter(sender=sender_id, reciever=reciever_id)
return messages
urls
path("api/get-messages/<sender_id>/<reciever_id>/", views.GetMessages.as_view()),
This is what this view returns
## url - http://127.0.0.1:8000/api/get-messages/2/1/
[
{
"id": 2,
"sender": 2,
"reciever": 1,
"message": "Hey Destiny",
"is_read": false
}
]
if i swap the sender_id and reciever_id, this is the response i get
# url - http://127.0.0.1:8000/api/get-messages/1/2/
[
{
"id": 1,
"sender": 1,
"reciever": 2,
"message": "Hello Sammy",
"is_read": false
},
{
"id": 3,
"sender": 1,
"reciever": 2,
"message": "This is another message for you sammy",
"is_read": false
}
]
what i want is this, when i pass in the id of the sender (1) and id of the reciever (2) in the url, i want to get a response like this, which is all the conversaion that this two folks have had.
[
{
"id": 1,
"sender": 1,
"reciever": 2,
"message": "Hello Sammy",
"is_read": false
},
{
"id": 2,
"sender": 2,
"reciever": 1,
"message": "Hey Destiny",
"is_read": false
},
{
"id": 3,
"sender": 1,
"reciever": 2,
"message": "This is another message for you sammy",
"is_read": false
}
]
Some images
You can use a Q object here:
from django.db.models import Q
then
messages = ChatMessage.objects.filter(
Q(sender=sender_id, reciever=reciever_id) |
Q(sender=reciever_id, reciever=sender_id)
)
As a side note, it's spelled receiver.
You can also use this method,
messages = ChatMessage.objects.filter(
sender__in=[sender_id, reciever_id], reciever__in=[reciever_id, sender_id]
)
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()
I have an already created serializer object, I am trying to add a new object to the serializer but I keep getting the error
list indices must be integers or slices, not str
I am not able to trace where I am going wrong with the creation of the new object. Here is my code below and more explanations.
class ClusterFunctionView(generics.ListAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = FunctionListSerializer
def get_queryset(self):
//returns serializer
def list(self, request, *args, **kwargs):
response = super().list(request, *args, **kwargs)
user = self.request.user
cluster = Cluster.objects.filter(user_id=user.id, id=self.kwargs["cluster_id"]).first()
schedule = Schedule.objects.filter(clusters__in=[cluster]).values().first() # I am getting the new object here
print('schedule', type(schedule)) # I checked the type, it is a dict
response.data['schedule'] = schedule # doesn't seem to be appending to the existing serializer.
return response
The following is an example of the output of the schedule object, I printed using print('schedule', schedule):
schedule {'id': 7, 'user_id': 3, 'creation_time': datetime.datetime(2020, 5, 25, 15, 44, 39, 875485), 'name': 'mandard_1', 'is_active': True, 'comment': 'extract mardard premier batch', 'cron_expression': '#once'}
A sample of the existing serializer on which I should add the above object is:
[
{
"id": 1,
"function": "connections",
"max_concurrency": 1,
"mandatory_params": {},
"public_params": {
"cluster": {
"account": true,
"max_pages": {
"max": 100,
"default": 100
},
"profiles_per_page": {
"max": 25,
"default": 25
}
}
},
"params": {
"max_pages": 100,
"account_function": "user_account",
"alchemy_directory": "connections",
"unique_result_obj_attribute": "connection_id"
}
}
]
I am expecting a serializer with a schedules object, a result like :
[
{
"id": 1,
"function": "connections",
"max_concurrency": 1,
"mandatory_params": {},
"public_params": {
"cluster": {
"account": true,
"max_pages": {
"max": 100,
"default": 100
},
"profiles_per_page": {
"max": 25,
"default": 25
}
}
},
"params": {
"max_pages": 100,
"account_function": "user_account",
"alchemy_directory": "connections",
"unique_result_obj_attribute": "connection_id"
}
},
"schedule": {} # this should be added as a result
]
What could the problem be, and what solution could I undertake? Thanks
I was able to solve the question, realizing it was a small mistake that I did.
In the def list function,
This line was the one causing the error :
response.data['schedule'] = schedule
I realised that the serializer produced was of a list result, and I was initially trying to append the schedule : {}, directly into a list, hence the error. It should be appended into the first object. Hence I needed to access the object in the list using index, so changing it to below solved the problem:
response.data[0]['schedule'] = schedule
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]
I have a bit of code that is trying to transform a dictionary from one nesting format to another using a series of for loops so that I can easily export the dictionary to a CSV file. However, as my script loops through the input dict, it overwrites the output dict rather than appending the additional values, and I can't figure out why.
Here's the format of the input dictionary:
{'data': [{'title': 'Lifetime Likes by Country',
'values': [{'end_time': '2013-11-10T08:00:00+0000',
'value': {'IN': 343818, 'PK': 212632, 'US': 886367}},
{'end_time': '2013-11-11T08:00:00+0000',
'value': {'IN': 344025, 'US': 886485}}]},
{'title': 'Daily Country: People Talking About This',
'values': [{'end_time': '2013-11-10T08:00:00+0000',
'value': {'IN': 289, 'US': 829}},
{'end_time': '2013-11-11T08:00:00+0000',
'value': {'IN': 262, 'US': 836}}]}]}
Here's my code:
input_dict = function_to_get_input_dict()
filtered_dict = {}
for metric in input_dict['data']:
for day in metric['values']:
parsed_date = parser.parse(day['end_time'])
date_key = parsed_date.strftime('%m/%d/%Y')
filtered_dict[date_key] = {}
filtered_dict[date_key]['Total %s' % metric['title']] = 0
for k, v in day['value'].iteritems():
filtered_dict[date_key]['%s : %s' % (metric['title'], k)] = v
filtered_dict[date_key]['Total %s' % metric['title']] += v
pprint(filtered_dict) #debug
Expected output dictionary format:
{date1:{metric_1_each_country_code:value, metric_1_all_country_total:value, metric_2_each_country_code:value, metric_2_all_country_total:value}, date2:{etc}}
However, instead I'm getting an output dictionary that only has one metric per date:
{date1:{metric_2_each_country_code:value, metric_2_all_country_total:value}, date2:{etc}}
It appears to be overwriting the metric key:value pair each time, which I don't understand because the key's should be unique to each metric using the ['%s : %s' % (metric['title'], k)] formula, so they shouldn't get overwritten.
What am I missing?
If you notice in your code, in the second for loop you have filtered_dict[date_key] = {}. This resets the value of filtered_dict[date_key] instead of allowing you to add to it.
input_dict = function_to_get_input_dict()
filtered_dict = {}
for metric in input_dict['data']:
for day in metric['values']:
parsed_date = parser.parse(day['end_time'])
date_key = parsed_date.strftime('%m/%d/%Y')
filtered_dict[date_key] = {}
filtered_dict[date_key]['Total %s' % metric['title']] = 0
for k, v in day['value'].iteritems():
filtered_dict[date_key]['%s : %s' % (metric['title'], k)] = v
filtered_dict[date_key]['Total %s' % metric['title']] += v
pprint(filtered_dict) #debug
I think one problem is that your data has syntax errors in it and it is nearly impossible to see the structure. I have corrected it and pretty printed the whole thing to help you better see its structure. Not a complete answer, but it goes a long way towards helping solve the problem:
import pprint; pprint.pprint({"data": [{ "values": [{ "value": { "US": 886367, "IN": 343818, "PK": 212632}, "end_time": "2013-11-10T08:00:00+0000"},{"value": { "US": 886485, "IN": 344025}, "end_time": "2013-11-11T08:00:00+0000"}], "title": "Lifetime Likes by Country"}, {"values": [{"value": { "US": 829, "IN": 289}, "end_time": "2013-11-10T08:00:00+0000"},{"value": {"US": 836,"IN": 262}, "end_time": "2013-11-11T08:00:00+0000"}], "title": "Daily Country: People Talking About This"}]})
{'data': [{'title': 'Lifetime Likes by Country',
'values': [{'end_time': '2013-11-10T08:00:00+0000',
'value': {'IN': 343818, 'PK': 212632, 'US': 886367}},
{'end_time': '2013-11-11T08:00:00+0000',
'value': {'IN': 344025, 'US': 886485}}]},
{'title': 'Daily Country: People Talking About This',
'values': [{'end_time': '2013-11-10T08:00:00+0000',
'value': {'IN': 289, 'US': 829}},
{'end_time': '2013-11-11T08:00:00+0000',
'value': {'IN': 262, 'US': 836}}]}]}
Now that I can see the nature of your data, perhaps this type of data structure would better suit your needs:
import pprint; pprint.pprint({'Daily Country: People Talking About This': {'2013-11-11T08:00:00+0000': {'US': 836, 'IN': 262}, '2013-11-10T08:00:00+0000': {'US': 829, 'IN': 289}}, 'Lifetime Likes by Country': {'2013-11-11T08:00:00+0000': {'US': 886485, 'IN': 344025}, '2013-11-10T08:00:00+0000': {'PK': 212632, 'US': 886367, 'IN': 343818}}})
Which gives you:
{'Daily Country: People Talking About This': {'2013-11-10T08:00:00+0000': {'IN': 289,
'US': 829},
'2013-11-11T08:00:00+0000': {'IN': 262,
'US': 836}},
'Lifetime Likes by Country': {'2013-11-10T08:00:00+0000': {'IN': 343818,
'PK': 212632,
'US': 886367},
'2013-11-11T08:00:00+0000': {'IN': 344025,
'US': 886485}}}