How can I include a Count in my Django Rest Framework Pagination to count the total number of rows? - python-3.x

I have written a code in Python using Django Rest Framework to fetch data from database(MySql) and view it in browser using Pagination(PageNumberPagination).It is working fine but the problem is the "count" is not coming in view. I want to show the total number of rows in count. I am getting response like this:
GET /fetchdata/?page=1&per_page=10
HTTP 200 OK
Allow: GET, OPTIONS, POST
Content-Type: application/json
Vary: Accept
[
{
"id": 53,
"first_name": "Rounak",
},
{
"id": 54,
"first_name": "Rounak",
},
]
But I want the response like this.
HTTP 200 OK
{
"count": 1023
"next": "https://api.example.org/persons/?page=2&per_page=10",
"previous": null,
"results": [
…
]
}
Below is my code, please suggest me something.
view.py
from rest_framework.pagination import PageNumberPagination
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .pagination import StandardResultsSetPagination
#api_view(['GET','POST'])
def index(request):
if request.method=='GET':
all_dataobj=fetchdata.objects.all()
paginator = StandardResultsSetPagination()
result_page = paginator.paginate_queryset(all_dataobj, request)
pserializer=fetchdataSerializers(result_page,many=True)
return Response(pserializer.data,status=status.HTTP_201_CREATED)
elif request.method=='POST':
serializer=fetchdataSerializers(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data,status=status.HTTP_201_CREATED)
return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)
pagination.py
from rest_framework import pagination
class StandardResultsSetPagination(pagination.PageNumberPagination):
page_size = 10
page_query_param = 'page'
page_size_query_param = 'per_page'
max_page_size = 1000
settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS':
'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}

Related

Python: Google Analytics API not retrieving adImpressions and adClicks

I am trying to retrieve some information about my ads in google. I have done the same for campaigns, adgroups and keywords and I haven't got a single issue, however, when it comes to ads and their metrics, I cannot manage to extract something other than adCost.
I have the following code to retrieve the info I need from google ads:
def ad_data(service, view_id, start_date, end_date):
# Initialize request with first page of results
request = {
'reportRequests': [
{
'viewId': view_id,
'dateRanges': [
{
'startDate': start_date,
'endDate': end_date
}
],
'metrics': [
{
'expression': 'ga:adCost'
},
{
'expression': 'ga:adClicks'
},
{
'expression': 'ga:adImpressions'
}
],
'dimensions': [
{
'name': 'ga:date'
},
{
'name': 'ga:campaign'
},
{
'name': 'ga:adContent'
}
],
'pageSize': 1000
}
]
}
all_data = []
while True:
# Make API call and get response
response = service.reports().batchGet(body=request).execute()
report = response.get('reports', [])[0]
rows = report.get('data', {}).get('rows', [])
all_data.extend(rows)
# Check if there are more pages of results
page_token = report.get('nextPageToken', None)
if not page_token:
break
# Update request with next page of results
request['reportRequests'][0]['pageToken'] = page_token
return all_data
The issue that I have is that for some reason I'm not being ale to retrieve metrics other than adCost, hence it shows me the following error:
HttpError: <HttpError 400 when requesting https://analyticsreporting.googleapis.com/v4/reports:batchGet?alt=json returned "Unknown metric(s): ga:adImpressions
For details see https://developers.google.com/analytics/devguides/reporting/core/dimsmets.". Details: "Unknown metric(s): ga:adImpressions
For details see https://developers.google.com/analytics/devguides/reporting/core/dimsmets.">
Could anyone help me out?

Parsing JSON from POST request using Python and FastAPI

I'm trying to parse a JSON that came from a POST request from user to my API made with FastAPI. I have a nested JSON that can receive multiple values and my problem is: How can I parse it and get the values from this nested JSON?
The JSON is like this:
{
"recipe": [
{
"ingredient": "rice",
"quantity": 1.5
},
{
"ingredient": "carrot",
"quantity": 1.8
},
{
"ingredient": "beans",
"quantity": 1.8
}
]
}
I must grab the all values from the list recipe separated, as I have a database with this ingredient and will query all of this and do some calculates with the quantity given from user. But I don't even know how I can parse this JSON from the POST request.
I already have a 2 classes with Pydantic validating this values like:
class Ingredientes(BaseModel):
ingredient: str
quantity: float
class Receita(BaseModel):
receita: List[Ingredientes] = []
Edit 1: I tried to include it in my function that recieve this POST request and didn't work like:
#app.post('/calcul', status_code=200)
def calculate_table(receita: Receita):
receipe = receita["receita"]
for ingredient in receipe:
return f'{ingredient["ingredient"]}: {ingredient["quantity"]}'
Edit 2: Fixed the issue with the code bellow(Thanks MatsLindh):
#app.post('/calcul', status_code=200)
def calculate_table(receita: Receita):
receipe = receita.receita
for ingredient in receipe:
return f'{ingredient.ingrediente}: {ingredient.quantidade}'
To parse a JSON-formatted string (from the POST request, for example) into a dictionary, use the loads function from the json module, like this:
import json
s = """{
"recipe": [
{
"ingredient": "rice",
"quantity": 1.5
},
{
"ingredient": "carrot",
"quantity": 1.8
},
{
"ingredient": "beans",
"quantity": 1.8
}
]
}
"""
recipe = json.loads(s)["recipe"]
for ingredient in recipe:
print(f"{ingredient['ingredient']}: {ingredient['quantity']}")

Flask API - create nested json response group by field single table

I have a basic API setup to do a basic Post and Get from a single table. I want to create a nested array though grouping by force_element_type
model.py
from db import db
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy import text as sa_text
class ForceElementModel(db.Model):
__tablename__ = 'force_element'
__table_args__ = {'schema': 'force_element'}
force_element_id = db.Column(UUID(as_uuid=True), primary_key=True, server_default=sa_text("uuid_generate_v4()"))
name = db.Column(db.String(100), nullable=False)
force_element_type = db.Column(db.String(20), nullable=False)
def __init__(self, name, force_element_type):
self.name = name
self.force_element_type = force_element_type
def json(self):
return {'name': self.name, 'force_element_type': self.force_element_type}
#classmethod
def find_by_name(cls, name):
return cls.query.filter_by(name=name).first() # simple TOP 1 select
def save_to_db(self): # Upserting data
db.session.add(self)
db.session.commit() # Balla
def delete_from_db(self):
db.session.delete(self)
db.session.commit()
resource.py
from flask_restful import Resource, reqparse
#from flask_jwt import jwt_required
from models.force_element import ForceElementModel
class ForceElement(Resource):
parser = reqparse.RequestParser() # only allow price changes, no name changes allowed
parser.add_argument('force_element_type', type=str, required=True, help='This field cannot be left blank')
##jwt_required()
def post(self, name):
if ForceElementModel.find_by_name(name):
return {'message': "An Force Element with name '{}' already exists.".format(name)}, 400
data = ForceElement.parser.parse_args()
force_element = ForceElementModel(name, data['force_element_type'])
try:
force_element.save_to_db()
except:
return {"message": "An error occurred inserting the item."}, 500
return force_element.json(), 201
class ForceElementList(Resource):
##jwt_required()
def get(self):
return {'force_elements': [force_element.json() for force_element in ForceElementModel.query.all()]}
class ForceElementType(Resource):
##jwt_required()
def get(self):
The GET endpoint using ForceElementList returns
{
"force_elements": [
{
"name": "San Antonio",
"force_element_type": "ship"
},
{
"name": "Nimitz",
"force_element_type": "ship"
},
{
"name": "Nimitz- Starboard",
"force_element_type": "Crew"
},
{
"name": "Nimitz- Port",
"force_element_type": "Crew"
}
]
}
I don't know how to group by force_element_type and return
[
"ship": [
{
"name": "San Antonio",
"force_element_id": "xxx1"
},
{
"name": "Nimitz",
"force_element_id": "xxx2"
}],
"crew": [
{
"name": "Nimitz- Starboard",
"force_element_id": "yyy1"
},
{
"name": "Nimitz- Port",
"force_element_id": "yyy2"
}
]
]
How do I create this separate andpoint?
OK I got there, here is how I did it. Is there a better way?
Lesson one use an online parser to check the json format this is what I was actually aiming for and the square braket at then start had me scratching my head for a while
{
"ship": [
{
"name": "San Antonio",
"force_element_id": "xxx1"
},
{
"name": "Nimitz",
"force_element_id": "xxx2"
}],
"crew": [
{
"name": "Nimitz- Starboard",
"force_element_id": "yyy1"
},
{
"name": "Nimitz- Port",
"force_element_id": "yyy2"
}]
}
This code creates the correct format for the output
class ForceElementType(Resource):
##jwt_required()
def get(self):
types = {}
force_elements = ForceElementModel.query.order_by(ForceElementModel.force_element_type.desc()).all()
for force_element in force_elements:
nested = {'name': force_element.name, 'force_element_id': str(force_element.force_element_id)}
print(nested)
if not force_element.force_element_type in types:
types[force_element.force_element_type] = []
types[force_element.force_element_type].append(nested)
response = types

How to delete rows in google spreadsheet using SHEET API v4 by Python?

My code is the following
def write_cells(spreadsheet_id, update_data):
updating = sheet_service.spreadsheets().values().\
batchUpdate(spreadsheetId=spreadsheet_id, body=update_data)
updating.execute()
spreadsheet_data = [
{
"deleteDimension": {
"range": {
"sheetId": sheet_id,
"dimension": "ROWS",
"startIndex": 5,
"endIndex": 100
}
}
}
]
update_spreadsheet_data = {
'valueInputOption': 'USER_ENTERED',
'data': spreadsheet_data
}
update_data = update_spreadsheet_data
write_cells(spreadsheet_id, update_data)
I have the following error message
HttpError Traceback (most recent call last)
<ipython-input-64-0ba8756b8e85> in <module>()
----> 1 write_cells(spreadsheet_id, update_data)
2 frames
/usr/local/lib/python3.6/dist-packages/googleapiclient/http.py in execute(self, http, num_retries)
838 callback(resp)
839 if resp.status >= 300:
--> 840 raise HttpError(resp, content, uri=self.uri)
841 return self.postproc(resp, content)
842
HttpError: <HttpError 400 when requesting https://sheets.googleapis.com/v4/spreadsheets/1lAI8gp29luZDKAS1m3P62sq0kKCn8eaMUvO_M_J8meU/values:batchUpdate?alt=json returned "Invalid JSON payload received. Unknown name "delete_dimension" at 'data[0]': Cannot find field.">
I don't understand this: "Unknown name delete_dimension". I'm unable to resolve it. Any help is appreciated, thanks.
You want to delete rows using Sheets API with Python.
If my understanding is correct, how about this modification?
Modification points:
When delete rows in Spreadsheet, please use spreadsheets().batchUpdate().
I think that spreadsheet_data is correct.
In this case, please modify the request body to {"requests": spreadsheet_data}.
Modified script:
def write_cells(spreadsheet_id, update_data):
# Modified
updating = sheet_service.spreadsheets().batchUpdate(
spreadsheetId=spreadsheet_id, body=update_data)
updating.execute()
spreadsheet_data = [
{
"deleteDimension": {
"range": {
"sheetId": sheet_id,
"dimension": "ROWS",
"startIndex": 5,
"endIndex": 100
}
}
}
]
update_spreadsheet_data = {"requests": spreadsheet_data} # Modified
update_data = update_spreadsheet_data
write_cells(spreadsheet_id, update_data)
Note:
This modified script supposes that you have already been able to use Sheets API.
Reference:
DeleteDimensionRequest
If I misunderstood your question and that was not the result you want, I apologize.

flask-marshmallow custom fields

I use flask-marshmallow and mongoengine.
Also flask-restplus for my API server.
Here is my api.py
class BoardSchema(ma.Schema):
class Meta:
fields = ('no', 'title', 'body', 'tags', 'created_at', 'views')
board_schema = BoardSchema()
boards_schema = BoardSchema(many=True)
class ArticleList(Resource):
def get(self):
articles = Board.objects.all()
return boards_schema.jsonify(articles)
model.py
from datetime import datetime
from mongoengine import *
from config import DB_NAME
connect(DB_NAME)
class Board(Document):
d = datetime.now()
date = "{}-{}-{}".format(d.year, d.month, d.day)
no = SequenceField()
title = StringField(required=True)
body = StringField(required=True)
tags = ListField(StringField())
likes = ListField(StringField())
views = ListField(StringField())
password = StringField(required=True)
created_at = DateTimeField(default=date)
updated_at = DateTimeField(default=date)
When I access to /article, it's result like this ->
{
"body": "123",
"created_at": "2018-08-20T00:00:00+00:00",
"no": 1,
"tags": [
"MySQL",
"C"
],
"title": "\ud14c\uc2a4\ud2b8",
"views": [
"127.0.0.1"
]
}
in "views", ip will be added who read article.
But I want to count of all the list of views and include it to my result.
The result I wanted is here.
{
"body": "123",
"created_at": "2018-08-20T00:00:00+00:00",
"no": 1,
"tags": [
"MySQL",
"C"
],
"title": "\ud14c\uc2a4\ud2b8",
"views": 20
}
I'm new at flask-marshmallow so I'm so confused how can I solve this issue.
Thanks.
Maybe you can try like this:
class BoardSchemaCustom(ma.ModelSchema):
class Meta:
model = Board
views = ma.fields.method(deserialize="_custom_serializer")
def _custom_serializer(self, obj):
return len(obj.views)
Create instance of your custom schema:
custom_board_schema = BoardSchemaCustom()
and dump it:
dump, errors = custom_board_schema.schema.dump(Board.query.first())
>>> dump
i've got the same problem. and my code works after installing marshmallow-sqlalchemy
pip install marshmallow-sqlalchemy
see from offical documentation
https://flask-marshmallow.readthedocs.io/en/latest/
Below snippet would also work:
class BoardSchemaCustom(ma.ModelSchema):
class Meta:
model = Board
views = ma.fields.Function(lambda obj: len(obj.views))

Resources