How to return nested list from html forms usingf pydantic? - list

Trying to return form data in a nested list. Current code returns the below format:
{
"name":"meal number 4",
"description":"new description",
"ing_qty":"4",
"ing_type":"small",
"ing_name":"Tomato",
"ing_id":"9"
}
Printing raw FormData results in:
FormData([('name', 'meal number 4'), ('description', 'new
description'), ('ing_qty', '4'), ('ing_type', 'small'), ('ing_name',
'Onion'), ('ing_id', '6'), ('ing_qty', '4'), ('ing_type', 'small'),
('ing_name' , 'Red'), ('ing_id', '7'), ('ing_qty', '4'), ('ing_type',
'small'), ('ing_name', 'Tomato'), ('ing_id', '8'), ('ing_qty', '4'),
('ing_type', 'small'), ('ing_name', 'Tomato'), ('ing_id', '9')])
I am trying to get the results into the below format so that i may update my db recrds with the form data.
{
"name":"string",
"description":"string",
"ingredients":[
{
"ing_id":null,
"ing_qty":null,
"ing_type":null,
"ing_name":null
}
]
}
Here are my Pydantic BaseModels
class IngUpdate(BaseModel):
ing_id: Optional[int]
ing_qty: Optional[int]
ing_type: Optional[str]
ing_name: Optional[str]
class RecipeUpdate(BaseModel):
name: Optional[str]
description: Optional[str]
ingredients: List[IngUpdate] = []
Here is my Post Request:
#router.post("/edit/{recipe_id}")
async def edit_select_recipe(request: Request, recipe_id: int,
db: Session = Depends(get_db)):
data = await request.form()
print(data)
return data
Adding Response Model to Post returns the following result:
{
"name":"meal number 4",
"description":"new description",
"ingredients":[
]
}
It appears it's unable to pull the data into a list. How can I get this into a nest model?

Related

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 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?

return data in from django queryset in the a specified format below

I have a database table with a field named groupname.
I have a queryset that counts the number of groupname as follows
count_groups=Eventgroup.objects.values('groupname').annotate(group_count=Count('groupname'))
I want to return this values in the following format:
[{
data : [[0, 4]],
label : "Event 2345"
}, {
data : [[0, 3]],
label : "Event 34567"
}, {
data : [[0, 5]],
label : "Event 4567",
}, {
data : [[0, 3]],
label : "Event 4356"
}];
where label should be the name of the groupname, in data,the 0 is always there but the second value is the count of the groupname.
here is my model:
class Eventgroup(models.Model):
event_id=models.CharField(max_length=500)
OS_CHOICE=(('Win 2003','windows 2003'),
('Win 2008','Windows 2008'),
('Win XP','Windows XP'),
('Win VISTA','Win VISTA'),
('Win 2007','Windows 2007'),
)
windows=models.CharField(max_length=20,choices=OS_CHOICE,default='Win 2003')
groupname=models.CharField(max_length=250)
def __unicode__(self):
return " %s, group name:%s" \
% (int(self.event_id), str(self.groupname.name),str(self.windows.name))
class Meta:
db_table= 'Eventgroups'
verbose_name_plural='eventgroups'
please give insights based on my data. regards
Something like this
def format_results(queryset):
for eventgroup in queryset:
yield {
'data': [[0, eventgroup['group_count']]],
'label': eventgroup['name'],
}
count_groups = Eventgroup.objects.values('groupname').annotate(group_count=Count('groupname'))
results = format_results(count_groups)
Using a generator like this behaves similarly to a queryset in that it is not immediately evaluated or fully loaded into memory as a list object.

ordered data in django chartit

I am using django-chartit to display a site name on x-axis and its response time on y-axis.
How do I sort the graph with the response time in ascending order. I am using order_by in the queryset but still its not ordering correctly.
Below is my code :
siteresppivotdata = PivotDataPool(
series =
[{'options': {
'source': MonthlySiteResponse.objects.all(),
'categories': ['site_name', ],
'legend_by' : ['site_name'],
},
'terms': {
'total_response_time': Avg('response_time')}}
],
pareto_term = 'total_response_time' ## Added this code for sorting
)
#Step 2: Create the PivotChart object
siteresppivcht = PivotChart(
datasource = siteresppivotdata,
series_options =
[{'options':{
'type': 'bar', ## Show response_time on x-axis and site_name on y-axis with the 'bar' i.e (reverse of the column graph)
'stacking': True},
'terms':[
'total_response_time']}],
chart_options =
{'title': {
'text': 'Monthly Site Response Time'},
'xAxis': {
'title': {
'text': 'Website'}},
'yAxis': {
'title': {
'text': 'Response Time'}}}
)
Also is there a way to show the graph vice-versa (i.e site name on y-axis and response-time on x-axis)

django rest framework - get two models

I have multiple models that are associated by Foreign Keys. I can export them all separately using django rest framework on a one to one basis, and I can also export multiple ones nested. However I want to be able to essentially "concatenate" them together into a single json/xml export.
The models in the example below are joined by a one to one foreign key on jobdtl_id. I have some where it's one to many but I'm hoping I can figure that out when I know how to get a view that will link 2 separate models like I want below -
Here's an example of what I want the json to look like by hitting a single URL like
http://localhost/job/4/
{
"job": {
"-id": "9878",
"-name": "This is the job",
"-master": "blahserver",
"-dbversion": "234",
"-xmlversion": "1",
"jobmst": {
"jobmst_id": "9878",
"jobmst_type": "2",
"jobmst_prntid": "234",
"jobmst_active": "Y",
"jobmst_name": "This is the job",
"jobmst_owner": "Owner",
"jobdtl_id": "9878",
"jobmst_lstchgtm": {
"-date": "Y",
"#text": "2013-10-23 09:22:08.0"
},
"jobmst_prntname": "Parent",
"jobmst_alias": "9878"
},
"jobdtl": {
"jobdtl_id": "9878",
"jobdtl_cmd": "blah.exe",
"jobdtl_failalarm": "NULL",
"nodmst_id": "NULL",
"nodlstmst_id": "NULL",
"jobdtl_inhevent": "Y",
"jobdtl_inhoptions": "Y",
"jobdtl_inhagent": "Y",
"jobdtl_inhrepeat": "Y",
"jobdtl_inhtime": "Y",
"jobdtl_timewin": "NULL",
"jobdtl_saveoutput": "Y",
"jobdtl_outputname": "NULL",
"jobdtl_trackmethod": "1",
"jobdtl_trackcmd": "NULL",
"jobdtl_deplogic": "1",
"jobdtl_rerun": "NULL",
"jobdtl_params": "--blah --ok"
},
"jobdep": [
{
"jobdep_id": "79670",
"jobmst_id": "9878",
"jobdep_type": "1",
"jobdep_jobmst": "another job",
"varmst_id": "NULL"
},
{
"-num": "2",
"jobdep_id": "83783",
"jobmst_id": "9878",
"jobdep_type": "1",
"jobdep_jobmst": "and another",
"varmst_id": "NULL"
}
],
"trgjob": [
{
"trgjob_id": "22286",
"trgmst_id": "23455",
"jobmst_id": "9878"
},
{
"-num": "2",
"trgjob_id": "28980",
"trgmst_id": "23521",
"jobmst_id": "9878"
},
{
"-num": "3",
"trgjob_id": "28981",
"trgmst_id": "9237",
"jobmst_id": "9878"
}
]
}
}
The models are basically like this -
class Jobdtl(models.Model):
jobdtl_id = models.IntegerField(primary_key=True)
jobdtl_cmd = models.TextField(blank=True)
....
jobdtl_duration = models.IntegerField(blank=True, null=True)
class Meta:
managed = False
db_table = 'jobdtl'
class Jobmst(models.Model):
jobmst_id = models.IntegerField(primary_key=True)
jobmst_type = models.SmallIntegerField()
....
jobdtl_id = models.ForeignKey('Jobdtl', db_column='jobdtl_id', related_name='mstdtl', blank=True, null=True)
def __unicode__(self):
return self.jobmst_name
class Meta:
managed = False
db_table = 'jobmst'
end caveat I'm converting the json from how the XML looks for the existing legacy app which is like so -
<?xml version="1.0"?>
<job id="9878" name="This is the job" master="blahserver" dbversion="532" xmlversion="1">
<jobmst>
<jobmst_id>9878</jobmst_id>
<jobmst_type>2</jobmst_type>
<jobmst_prntid>234</jobmst_prntid>
<jobmst_active>Y</jobmst_active>
<jobmst_name>This is the job</jobmst_name>
<jobmst_owner>Owner</jobmst_owner>
<jobdtl_id>9878</jobdtl_id>
<jobmst_lstchgtm date="Y">2013-10-23 09:22:08.0</jobmst_lstchgtm>
<jobmst_prntname>Parent</jobmst_prntname>
<jobmst_alias>9878</jobmst_alias>
</jobmst>
<jobdtl>
<jobdtl_id>9878</jobdtl_id>
<jobdtl_cmd>blah.exe</jobdtl_cmd>
<jobdtl_failalarm>NULL</jobdtl_failalarm>
<nodmst_id>NULL</nodmst_id>
<nodlstmst_id>NULL</nodlstmst_id>
<jobdtl_inhevent>Y</jobdtl_inhevent>
<jobdtl_inhoptions>Y</jobdtl_inhoptions>
<jobdtl_inhagent>Y</jobdtl_inhagent>
<jobdtl_inhrepeat>Y</jobdtl_inhrepeat>
<jobdtl_inhtime>Y</jobdtl_inhtime>
<jobdtl_timewin>NULL</jobdtl_timewin>
<jobdtl_saveoutput>Y</jobdtl_saveoutput>
<jobdtl_outputname>NULL</jobdtl_outputname>
<jobdtl_trackmethod>1</jobdtl_trackmethod>
<jobdtl_trackcmd>NULL</jobdtl_trackcmd>
<jobdtl_deplogic>1</jobdtl_deplogic>
<jobdtl_rerun>NULL</jobdtl_rerun>
<jobdtl_params>--blah --ok</jobdtl_params>
</jobdtl>
<jobdep>
<jobdep_id>79670</jobdep_id>
<jobmst_id>9878</jobmst_id>
<jobdep_type>1</jobdep_type>
<jobdep_jobmst>another job</jobdep_jobmst>
<varmst_id>NULL</varmst_id>
</jobdep>
<jobdep num="2">
<jobdep_id>83783</jobdep_id>
<jobmst_id>9878</jobmst_id>
<jobdep_type>1</jobdep_type>
<jobdep_jobmst>and another</jobdep_jobmst>
<varmst_id>NULL</varmst_id>
</jobdep>
<trgjob>
<trgjob_id>22286</trgjob_id>
<trgmst_id>23455</trgmst_id>
<jobmst_id>9878</jobmst_id>
</trgjob>
<trgjob num="2">
<trgjob_id>28980</trgjob_id>
<trgmst_id>23521</trgmst_id>
<jobmst_id>9878</jobmst_id>
</trgjob>
<trgjob num="3">
<trgjob_id>28981</trgjob_id>
<trgmst_id>9237</trgmst_id>
<jobmst_id>9878</jobmst_id>
</trgjob>
</job>
class MSTSerializer(serializers.HyperlinkedModelSerializer):
jobdtl_id = DTLSerializer()
class Meta:
model = Jobmst
fields = ('id', 'url', 'jobdtl_id'...)
class DTLSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Jobdtl
fields = ('id', 'url', ...)
Would result in a more correct data structure of
{
"jobmst_id": 4,
"jobmst_type": 1,
"jobdtl_id": {
"jobdtl_id": 4,
"jobdtl_cmd": null,
"jobdtl_duration": 1379
},
}
I found the solution by doing the following in my views.py
...
#csrf_exempt
def tesxml_test(request, pk):
"""
Retrieve, update or delete a code snippet.
"""
try:
mst = Jobmst.objects.using('database1').get(jobmst_id=pk)
dtl = Jobdtl.objects.using('database1').get(jobdtl_id=pk)
dep = Jobdep.objects.using('database2').filter(jobmst_id=pk).order_by('jobdep_id')
trg = Trgjob.objects.using('database1').filter(jobmst_id=pk).order_by('trgjob_order')
except Jobmst.DoesNotExist:
return HttpResponse(status=404)
if request.method == 'GET':
#Get String Results of 4 queries
jobmststring = JobmstSerializer(mst)
jobdtlstring = JobdtlSerializer(dtl)
jobdepstring = JobdepSerializer(dep)
trgjobstring = TrgjobSerializer(trg)
#Get serialized Results of 4 queries
jobmst_serialized = {'jobmst': jobmststring.data}
jobdtl_serialized = {'jobdtl': jobdtlstring.data}
jobdep_serialized = {'jobdep': jobdepstring.data}
trgjob_serialized = {'trgjob': trgjobstring.data}
jobgroup = jobmst_serialized, jobdtl_serialized, jobdep_serialized, trgjob_serialized,
jobgroupresponse = TESXMLResponse(jobgroup)
return jobgroupresponse
...
It's not perfect but it puts me on the next step of my problem which is customizing the renderer to get the data in the root fields which I have another SO question for :)