How to access Google Apps API from appengine? - python

What's the actual task?
I'm trying to access google Apps API (Drive API, Sheets API) from my google appengine standard project. So when a form is submitted, it has to create a new google sheet and write the contents of the form to the sheet and then the sheet has to be stored in the google drive associated with the google service account or authorized email account (ie, email account we gave in the authorized email section)
What I actually tried?
I have used google_auth library to get the appengine's default credentials and I have enabled both drive, sheets API on my gae project console.
from googleapiclient import discovery
from google.auth import app_engine
from google.auth.transport.requests import AuthorizedSession
import httplib2
def creat_sample_sheet():
credentials = app_engine.Credentials()
http = AuthorizedSession(credentials)
discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?'
'version=v4')
service = discovery.build('sheets', 'v4', http=http,
discoveryServiceUrl=discoveryUrl)
result = service.spreadsheets().values()
print result
But it's not working.. Here is the tracback I got...
File "/base/data/home/apps/vidyalay/1.397393333574060152/alumni_registration_dateycollege/sheet_handler.py" in creat_sample_sheet
30. discoveryServiceUrl=discoveryUrl)
File "/base/data/home/apps/vidyalay/1.397393333574060152/lib/oauth2client/_helpers.py" in positional_wrapper
133. return wrapped(*args, **kwargs)
File "/base/data/home/apps/vidyalay/1.397393333574060152/lib/googleapiclient/discovery.py" in build
222. cache)
File "/base/data/home/apps/vidyalay/1.397393333574060152/lib/googleapiclient/discovery.py" in _retrieve_discovery_doc
269. resp, content = http.request(actual_url)
Exception Type: TypeError at /alumni_dateycollege/sheet/
Exception Value: request() takes at least 3 arguments (2 given)
Don't know I'm on the right path..
Update
By following this link mentioned by Daniel works for me. But I don't know how to view the created spreadsheet .
Here is my attempt to download the created sheet.
service.spreadsheets().get(spreadsheetId=SHEET_ID, alt='media')
But this creates an get request to https://sheets.googleapis.com/v4/spreadsheets/1awnM7z_aomHx833Z5S_Z-agFusaidmgcCa0FJIFyGE8?alt=json
url. But I actually want to pass media to alt parameter instead of json. I tried the above, but it won't work.

I managed to solve the problem on my own.
I have used my google service account to create spreadsheet on the service account's google drive (sheet API takecare of storing the sheet to google drive). Then I gave writer role permission for that particular file to my own gmail id. Now I can be able to view that particular form sheet in my google drive.
from googleapiclient import discovery
import cloudstorage as gcs
# from oauth2client import client
# from oauth2client.contrib import appengine
# from google.appengine.api import memcache
import httplib2
from google.appengine.api import memcache
from oauth2client.contrib.appengine import AppAssertionCredentials
import logging
import os
import io
from googleapiclient.http import MediaIoBaseDownload
logger = logging.getLogger(__name__)
credentials = AppAssertionCredentials(scope='https://www.googleapis.com/auth/spreadsheets')
drive_credentials = AppAssertionCredentials(scope='https://www.googleapis.com/auth/drive')
http = credentials.authorize(httplib2.Http(memcache))
drive_http = drive_credentials.authorize(httplib2.Http(memcache))
discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?'
'version=v4')
service = discovery.build('sheets', 'v4', http=http,
discoveryServiceUrl=discoveryUrl)
def callback(request_id, response, exception):
if exception:
# Handle error
print exception
else:
print "Permission Id: %s" % response.get('id')
def list_drive_files(drive_service):
results = drive_service.files().list(
pageSize=10).execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print('{0} ({1})'.format(item['name'], item['id']))
def give_file_permission(drive_service, file_id):
batch = drive_service.new_batch_http_request(callback=callback)
user_permission = {
'type': 'user',
'role': 'writer',
'emailAddress': 'foobar#gmail.com' # email address of the user you want to give permission
}
batch.add(drive_service.permissions().create(
fileId=file_id,
body=user_permission,
fields='id',
))
batch.execute()
def creat_sample_sheet():
# data = {'properties': {'title': 'Academic Sheet'}}
# res = sheet_service.spreadsheets().create(body=data).execute()
# SHEET_ID = res['spreadsheetId']
SHEET_ID = '1awnM7z_aomHx833Z5S_Z-agFusaidmgcCa0FJIFyGE8'
sheet = service.spreadsheets().get(spreadsheetId=SHEET_ID, includeGridData=True)
drive_service = discovery.build('drive', 'v3', http=drive_http)
list_drive_files(drive_service)
# Sharing a file
# file_id = '1bgvJdXG0eg2JGaNlIcdtde_XJlg2gAUT_DOzHi75zys'
def write_to_sheet(form):
logger.info('Inside write to sheet')
first_name = form.cleaned_data.get('first_name', '')
sur_name = form.cleaned_data.get('sur_name', '')
email = form.cleaned_data.get('e_mail', '')
phone_no = form.cleaned_data.get('mobile_phone', '')
year_of_passing = form.cleaned_data.get('year_of_passing', '')
present_occupation = form.cleaned_data.get('present_occupation', '')
present_city = form.cleaned_data.get('present_city', '')
courses_attended = ', '.join([str(i) for i in form.cleaned_data.get('courses_attended', '')])
volunteer = form.cleaned_data.get('volunteer', '')
fields = [ 'first_name', 'sur_name', 'e_mail', 'mobile_phone', 'year_of_passing', 'present_occupation', 'present_city', 'courses_attended' , 'volunteer' ]
# data = {'properties': {'title': 'Form Sheet'}}
# # create sheet
# res = service.spreadsheets().create(body=data).execute()
# # sheet_id = res['spreadsheetId']
sheet_id = '1bgvJdXG0eg2JGaNlIcdtde_XJlg2gAUT_DOzHi75zys'
# print sheet_id
# update sheet
data = {'values': [[first_name, sur_name, email, phone_no, year_of_passing, present_occupation,
present_city, courses_attended, volunteer]]}
service.spreadsheets().values().append(spreadsheetId=sheet_id,
range='A1', body=data, valueInputOption='RAW').execute()
# Getting rows
# rows = service.spreadsheets().values().get(spreadsheetId=sheet_id,
# range='Sheet1').execute().get('values', [])
# for row in rows:
# print row

Related

Google Drive API return invalidSharingRequest when trying to share folder using service account

I am trying to share a folder using service account through Google API Drive using the following code:
import apiclient
import httplib2
from googleapiclient import discovery
from googleapiclient.errors import HttpError
from oauth2client.service_account import ServiceAccountCredentials
CREDENTIALS_FILE = 'creds.json'
credentials = ServiceAccountCredentials.from_json_keyfile_name(
CREDENTIALS_FILE,
['https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive']
)
httpAuth = credentials.authorize(httplib2.Http())
DRIVE = discovery.build('drive', 'v3', http=httpAuth)
def share_file(file_id, user_email):
"""Batch permission modification.
Args:
file_id: file Id
user_email: User ID
Prints modified permissions
"""
ids = []
file_id = file_id
def callback(request_id, response, exception):
if exception:
# Handle error
print(exception)
else:
print(f'Request_Id: {request_id}')
print(F'Permission Id: {response.get("id")}')
ids.append(response.get('id'))
batch = DRIVE.new_batch_http_request(callback=callback)
user_permission = {
'type': 'user',
'role': 'commenter',
'emailAddress': user_email,
'supportsAllDrives': True
}
batch.add(DRIVE.permissions().create(fileId=file_id,
body=user_permission,
fields='id'
))
batch.execute()
return ids
And in result i get: Details: "[{'domain': 'global', 'reason': 'invalidSharingRequest', 'message': 'Bad Request. User message: "You cannot share this item because it has been flagged as inappropriate."'}]"
What am i doing wrong?

Google contact API raise TypeError('Got an unexpected keyword argument "%s"' % name)

I try my google API Project
from __future__ import print_function
import httplib2
from oauth2client import tools
from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import OAuth2WebServerFlow
from apiclient import discovery
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# Set up a Flow object to be used if we need to authenticate. This
# sample uses OAuth 2.0, and we set up the OAuth2WebServerFlow with
# the information it needs to authenticate. Note that it is called
# the Web Server Flow, but it can also handle the flow for
# installed applications.
#
# Go to the Google API Console, open your application's
# credentials page, and copy the client ID and client secret.
# Then paste them into the following code.
FLOW = OAuth2WebServerFlow(
client_id='592262365202-h6qu4mrf2b043e2gv2qf5grjg0j53ádfasdfsf2s5.apps.googleusercontent.com',
client_secret='VVxrBm9SEádfsf1ONzyX1oIEwSfB2',
scope='https://www.googleapis.com/auth/contacts',
user_agent='contact_cms/YOUR_APPLICATION_VERSION')
# If the Credentials don't exist or are invalid, run through the
# installed application flow. The Storage object will ensure that,
# if successful, the good Credentials will get written back to a
# file.
def get_credentials(FLOW):
storage = Storage('info.dat')
credentials = storage.get()
if credentials is None or credentials.invalid == True:
credentials = tools.run_flow(FLOW, storage)
return credentials
# Create an httplib2.Http object to handle our HTTP requests and
# authorize it with our good Credentials.
def get_http(credentials):
http = httplib2.Http()
http = credentials.authorize(http)
return http
# Build a service object for interacting with the API. To get an API key for
# your application, visit the Google API Console
# and look at your application's credentials page.
def print_list_google_contact_with_number_of_contacts(creds, numberofcontact):
# Call the People API
service = build('people', 'v1', credentials=creds)
print('Ban dang in ra ', numberofcontact, ' danh ba')
results = service.people().connections().list(
resourceName='people/me',
pageSize=numberofcontact,
personFields='names,emailAddresses,phoneNumbers,emailAddresses,addresses').execute()
connections = results.get('connections', [])
# for person in connections:
# names = person.get('names', [])
# if names:
# name = names[0].get('displayName')
# print(name)
for person in connections:
names = person.get('names', [])
if names:
name = names[0].get('displayName')
else:
name = None
phoneNumbers = person.get('phoneNumbers', [])
if phoneNumbers:
phoneNumber = phoneNumbers[0].get('value')
else:
phoneNumber = None
Cities = person.get('addresses', [])
if Cities:
City = Cities[0].get('city')
else:
City = None
emails = person.get('emailAddresses', [])
if emails:
email = emails[0].get('value')
else:
email = None
print(f'{name}: {phoneNumber}: {City}: {email}')
def creat_a_google_contact(http):
service = discovery.build('people', 'v1', http=http, discoveryServiceUrl='https://people.googleapis.com/$discovery/rest')
service.people().createContact(parent='people/me', body={
"names": [
{
'givenName': "Samkafafsafsafit"
}
],
"phoneNumbers": [
{
'value': "8600086024"
}
],
"emailAddresses": [
{
'value': "samkit5495#gmail.com"
}
]
}).execute()
def main():
creds=get_credentials(FLOW)
http=get_http(creds)
printout=print_list_google_contact_with_number_of_contacts(creds,10)
creat_a_google_contact(http)
return print(printout)
if __name__ == '__main__':
main()
But when i run, have the log
Traceback (most recent call last):
File "/Users/nguyenngoclinh/cms/cmsproject/google_contacts_cms/setup_your_app.py", line 116, in <module>
main()
File "/Users/nguyenngoclinh/cms/cmsproject/google_contacts_cms/setup_your_app.py", line 113, in main
creat_a_google_contact(http)
File "/Users/nguyenngoclinh/cms/cmsproject/google_contacts_cms/setup_your_app.py", line 104, in creat_a_google_contact
'value': "samkit5495#gmail.com"
File "/Users/nguyenngoclinh/.conda/envs/1z_vietnam/lib/python3.7/site-packages/googleapiclient/discovery.py", line 840, in method
raise TypeError('Got an unexpected keyword argument "%s"' % name)
TypeError: Got an unexpected keyword argument "parent"
createContact() does not have a parent param. It has been deprecated:
https://developers.google.com/people/api/rest/v1/people/createContact
parent='people/me' is deprecated. Try without that.

Serialize and de-serialize oauth2client.client.OAuth2Credentials

So I have an object, which is credentials from an OAuth2 authorization for a web service. I want to save the users credentials so I can continue to use them in the future. I'm using Django.
The object is: <oauth2client.client.OAuth2Credentials object at 0x104b47310>
I'm not sure how I can stringify the credentials and then build the credentials object back from a string.
Sample code as requested:
#!/usr/bin/python
import httplib2
from apiclient import errors
from apiclient.discovery import build
from oauth2client.client import OAuth2WebServerFlow
# Copy your credentials from the console
CLIENT_ID = 'YOUR_CLIENT_ID'
CLIENT_SECRET = 'YOUR_CLIENT_SECRET'
# Check https://developers.google.com/webmaster-tools/search-console-api-original/v3/ for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/webmasters.readonly'
# Redirect URI for installed apps
REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'
# Run through the OAuth flow and retrieve credentials
flow = OAuth2WebServerFlow(CLIENT_ID, CLIENT_SECRET, OAUTH_SCOPE, REDIRECT_URI)
authorize_url = flow.step1_get_authorize_url()
print 'Go to the following link in your browser: ' + authorize_url
code = raw_input('Enter verification code: ').strip()
credentials = flow.step2_exchange(code)
# Create an httplib2.Http object and authorize it with our credentials
http = httplib2.Http()
http = credentials.authorize(http)
webmasters_service = build('webmasters', 'v3', http=http)
# Retrieve list of properties in account
site_list = webmasters_service.sites().list().execute()
# Filter for verified websites
verified_sites_urls = [s['siteUrl'] for s in site_list['siteEntry']
if s['permissionLevel'] != 'siteUnverifiedUser'
and s['siteUrl'][:4] == 'http']
# Printing the URLs of all websites you are verified for.
for site_url in verified_sites_urls:
print site_url
# Retrieve list of sitemaps submitted
sitemaps = webmasters_service.sitemaps().list(siteUrl=site_url).execute()
if 'sitemap' in sitemaps:
sitemap_urls = [s['path'] for s in sitemaps['sitemap']]
print " " + "\n ".join(sitemap_urls)
You can use pickle module to serialize and de-serialize python objects. Here is untested code:
import pickle
# Store OAuth2Credentials to a file
with open(FILENAME, 'wb') as credentials_file:
pickle.dump(credentials, credentials_file)
# Read OAuth2Credentials from file
with open(FILENAME, 'rb') as credentials_file:
credentials = pickle.load(credentials_file)

How can I use Python / pyodbc to push data to Google Sheets?

Upfront: I'm extremely new to Python. : )
I have taken Google's Python Quickstart information, and can successfully connect to my Google Sheet with read/write privilege and clear the sheet for any previous information. Also, I was able to follow the pyodbc docs, and can successfully connect to a MSSQL server that we utilize and write out an Excel copy of the MSSQL table.
However, I can't seem to figure out how to get the table MSSQL query results appended to the Google Sheet. Within VSCode, it does provide the most recent call in the traceback, and it does appear to be working correctly with no errors. However, the sheet doesn't get updated.
Note: If I change the value for dfListFormatto a text string, it does append that single value in A1 of the target range.
value_range_body = {
"majorDimension": "ROWS",
"values": [
[dfListFormat]
]
}
Below is the full code I currently have. Any help/advice you all could provide would be greatly appreciated.
from __future__ import print_function
import httplib2
import oauth2client
import os
import googleapiclient
import openpyxl
import pandas
import pyodbc
from apiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
from googleapiclient.discovery import build
from openpyxl import Workbook
from pandas import DataFrame, ExcelWriter
""" This is the code to get raw data from a specific Google Sheet"""
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/sheets.googleapis.com-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/spreadsheets'
CLIENT_SECRET_FILE = 'client_secret_noemail.json'
APPLICATION_NAME = 'Google Sheets API Python'
def get_credentials():
"""Gets valid user credentials from storage.
If nothing has been stored, or if the stored credentials are invalid,
the OAuth2 flow is completed to obtain the new credentials.
Returns:
Credentials, the obtained credential.
"""
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir,
'sheets.googleapis.com-python-quickstart.json')
store = Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatibility with Python 2.6
credentials = tools.run_flow(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
def main():
"""Shows basic usage of the Sheets API.
Creates a Sheets API service object and prints the names and majors of
students in a sample spreadsheet:
https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
"""
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?version=v4')
service = discovery.build(
'sheets', 'v4', http=http, discoveryServiceUrl=discoveryUrl)
# Google Sheet Url Link and Range name. Can use tab names to get full page.
spreadsheetId = '[spreadsheetid]'
rangeName = 'tblActiveEmployees'
# TODO: Add desired entries to the request body if needed
clear_values_request_body = {}
# Building Service to Clear Google Sheet
request = service.spreadsheets().values().clear(spreadsheetId=spreadsheetId,
range=rangeName, body=clear_values_request_body)
response = request.execute()
# Prints response that Google Sheet has been cleared
responseText = '\n'.join(
[str(response), 'The Google Sheet has been cleared!'])
print(responseText)
# SQL Server Connection
server = '[SQLServerIP]'
database = '[SQLServerDB]'
username = '[SQLServerUserID]'
password = '[SQLServerPW]'
cnxn = pyodbc.connect('Driver={ODBC Driver 13 for SQL Server};SERVER=' +
server+';DATABASE='+database+';UID='+username+';PWD='+password)
# Sample SQL Query to get Data
sql = 'select * from tblActiveEmployees'
cursor = cnxn.cursor()
cursor.execute(sql)
list(cursor.fetchall())
# Pandas reading values from SQL query, and building table
sqlData = pandas.read_sql_query(sql, cnxn)
# Pandas building dataframe, and exporting .xlsx copy of table
df = DataFrame(data=sqlData)
df.to_excel('tblActiveEmployees.xlsx',
header=True, index=False)
dfListFormat = df.values.tolist()
# How the input data should be interpreted.
value_input_option = 'USER_ENTERED' # TODO: Update placeholder value.
# How the input data should be inserted.
insert_data_option = 'OVERWRITE' # TODO: Update placeholder value.
value_range_body = {
"majorDimension": "ROWS",
"values": [
[dfListFormat]
]
}
request = service.spreadsheets().values().append(spreadsheetId=spreadsheetId, range=rangeName,
valueInputOption=value_input_option, insertDataOption=insert_data_option, body=value_range_body)
response = request.execute()
if __name__ == '__main__':
main()
Thanks to #tehhowch's input, the following was able to solve my problem. The issue was that my data was already in a list, and using it as "values": [[dfListFormat]] made "values" an array of an array of arrays, rather than just an array of arrays. Simply assigning to "values" without brackets worked perfectly.
Below is the updated code, and big thanks to tehhowch!
from __future__ import print_function
import httplib2
import oauth2client
import os
import googleapiclient
import openpyxl
import pandas
import pyodbc
from googleapiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
from openpyxl import Workbook
from pandas import DataFrame, ExcelWriter
""" This is the code to get raw data from a specific Google Sheet"""
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/sheets.googleapis.com-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/spreadsheets'
CLIENT_SECRET_FILE = 'client_secret_noemail.json'
APPLICATION_NAME = 'Google Sheets API Python'
def get_credentials():
"""Gets valid user credentials from storage.
If nothing has been stored, or if the stored credentials are invalid,
the OAuth2 flow is completed to obtain the new credentials.
Returns:
Credentials, the obtained credential.
"""
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir,
'sheets.googleapis.com-python-quickstart.json')
store = Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatibility with Python 2.6
credentials = tools.run_flow(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
def main():
"""Shows basic usage of the Sheets API.
Creates a Sheets API service object and prints the names and majors of
students in a sample spreadsheet:
https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
"""
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?version=v4')
service = googleapiclient.discovery.build(
'sheets', 'v4', http=http, discoveryServiceUrl=discoveryUrl)
# Google Sheet Url Link and Range name. Can use tab names to get full page.
spreadsheetId = '[spreadsheetID'
rangeName = 'tblActiveEmployees'
# TODO: Add desired entries to the request body if needed
clear_values_request_body = {}
# Building Service to Clear Google Sheet
request = service.spreadsheets().values().clear(spreadsheetId=spreadsheetId,
range=rangeName, body=clear_values_request_body)
response = request.execute()
# Prints response that Google Sheet has been cleared
responseText = '\n'.join(
[str(response), 'The Google Sheet has been cleared!'])
print(responseText)
# SQL Server Connection
server = '[SQLServerIP]'
database = '[SQLServerDB]'
username = '[SQLServerUserID]'
password = '[SQLServerPW]'
cnxn = pyodbc.connect('Driver={ODBC Driver 13 for SQL Server};SERVER=' +
server+';DATABASE='+database+';UID='+username+';PWD='+password)
# Sample SQL Query to get Data
sql = 'select * from tblActiveEmployees'
cursor = cnxn.cursor()
cursor.execute(sql)
list(cursor.fetchall())
# Pandas reading values from SQL query, and building table
sqlData = pandas.read_sql_query(sql, cnxn)
# Pandas building dataframe, and exporting .xlsx copy of table
df = DataFrame(data=sqlData)
df.to_excel('tblActiveEmployees.xlsx',
header=True, index=False)
dfHeaders = df.columns.values.tolist()
dfHeadersArray = [dfHeaders]
dfData = df.values.tolist()
print(dfHeaders)
print(dfData)
# How the input data should be interpreted.
value_input_option = 'USER_ENTERED' # TODO: Update placeholder value.
# How the input data should be inserted.
insert_data_option = 'OVERWRITE' # TODO: Update placeholder value.
value_range_body = {
"majorDimension": "ROWS",
"values": dfHeadersArray + dfData
}
request = service.spreadsheets().values().append(spreadsheetId=spreadsheetId, range=rangeName,
valueInputOption=value_input_option, insertDataOption=insert_data_option, body=value_range_body)
response = request.execute()
if __name__ == '__main__':
main()

Creating a DfpClient with a Service Account in Python

I use the google DFP api to collect some statistics on ads clicked on our website. The
code is written in Python. Currently, I am trying to upgrade the code to use oAuth 2.
Since, the code runs automatically everyday without any user involvement, I created a
service account under my google project and added the account to the DoubleClick for
Publishers network of our company. Based on the sample codes on the web, I wrote this:
import httplib2
from oauth2client.client import SignedJwtAssertionCredentials
from apiclient.discovery import build
from googleads.dfp import DfpClient
GOOGLE_DFP_SCOPE="https://www.googleapis.com/auth/dfp"
API_VERSION="v201411"
KEY_FILE="*******.p12"
ACCT_EMAIL="************************#developer.gserviceaccount.com"
NETWORK_CODE="**********"
with open(KEY_FILE) as config_file:
my_private_key = config_file.read()
credentials = SignedJwtAssertionCredentials(service_account_name=ACCT_EMAIL, private_key=my_private_key,scope=GOOGLE_DFP_SCOPE)
http = httplib2.Http()
http_auth = credentials.authorize(http)
dfp_client = build(serviceName='dfp',version=API_VERSION,http=http_auth)
This code does not seem to be correct, because the network_code has not been passed
anywhere in the code. In addition, it fails with the following message:
apiclient.errors.UnknownApiNameOrVersion: name: dfp version: v201411.
Also, the line below:
dfp_client = DfpClient.LoadFromStorage()
does not work for my case, because, this is based on googleads.yaml which seems
to be formatted only for web-app accounts with client secret, not P12 private key.
Any advice? Thanks.
Apiclient.discovery uses a default route to check the services.
But I did not find a service for DoubleClick for publishers.
I use this code to use API with Oauth2. Using Flask
import json
import requests
import flask
from googleads import dfp
from googleads import oauth2
app = flask.Flask(__name__)
CLIENT_ID = ''
CLIENT_SECRET = '' # Read from a file or environmental variable in a real app
SCOPE = 'https://www.googleapis.com/auth/dfp'
REDIRECT_URI = ''
APPLICATION_NAME = 'DFP API SERVICE'
NETWORK_CODE = ''
#app.route('/')
def index():
if 'credentials' not in flask.session:
return flask.redirect(flask.url_for('oauth2callback'))
credentials = json.loads(flask.session['credentials'])
if credentials['expires_in'] <= 0:
return flask.redirect(flask.url_for('oauth2callback'))
else:
try:
refresh_token = credentials['refresh_token']
oauth2_client = oauth2.GoogleRefreshTokenClient(CLIENT_ID, CLIENT_SECRET, refresh_token)
dfp_client = dfp.DfpClient(oauth2_client, APPLICATION_NAME, NETWORK_CODE)
user_service = dfp_client.GetService('UserService', version='v201508')
user = user_service.getCurrentUser()
return flask.render_template('index.html', name=user['name'])
except:
flask.session.pop('credentials', None)
return flask.redirect(flask.url_for('oauth2callback'))
#app.route('/oauth2callback')
def oauth2callback():
if 'code' not in flask.request.args:
auth_uri = ('https://accounts.google.com/o/oauth2/auth?response_type=code'
'&access_type=offline&client_id={}&redirect_uri={}&scope={}&').format(CLIENT_ID, REDIRECT_URI, SCOPE)
return flask.redirect(auth_uri)
else:
auth_code = flask.request.args.get('code')
data = {'code': auth_code,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'grant_type': 'authorization_code'}
r = requests.post('https://www.googleapis.com/oauth2/v3/token', data=data)
flask.session['credentials'] = r.text
return flask.redirect(flask.url_for('index'))
if __name__ == '__main__':
import uuid
app.secret_key = str(uuid.uuid4())
app.debug = False
app.run()
I hope this help you
You are correct. You have to pass the network code when you create a dfp client. And version is not necessary. Try the following code to create the client in python.
import os
from googleads import oauth2
from googleads import dfp
def get_dfp_client():
application_name = "Your application name" # from google developer console. eg: Web Client
network_code = ********
private_key_password = 'notasecret'
key_file = os.path.join('path/to/p12file')
service_account_email = '****#***.iam.gserviceaccount.com'
# create oath2 client(google login)
oauth2_client = oauth2.GoogleServiceAccountClient(
oauth2.GetAPIScope('dfp'), service_account_email, key_file)
dfp_client = dfp.DfpClient(oauth2_client, application_name, network_code)
return dfp_client
client = get_dfp_client()
Reference
Please comment if you need more clarification.
Update
googleads renamed module dfp to ad_manager, docs here – Gocht

Categories

Resources