How to loop inside Stripe - python

I have a problem I would like to loop inside Stripe to create dynamic multiple objects in checkout. I can not do that after stripe.checkout.Session.create() because I get an error. Also I can not create JSON object in for loop out of stripe.checkout.Session.create(). Any ideas? How can I use for loop and create multiple line_items?
def create_checkout_session(request):
if request.method == "GET":
try:
cart = Cart.objects.get(order_user=request.user)
checkout_session = stripe.checkout.Session.create(
payment_method_types=['card', 'p24'],
line_items=[{
'price_data': {
'currency': 'eur',
'product_data': {
'name': 'total'
},
'unit_amount': cart.total,
},
'quantity': 1,
}],

You should be able to iterate to prepare line_items according to your needs then pass the prepared array:
count = 5
lineItems = []
for i in range(count):
lineItems.append({...})
checkout_session = stripe.checkout.Session.create(
line_items=**lineItems**,
...
)

Related

Match between dictionaries in list

I have a question to how match between dictionaries
I send 3 request to youtube api
first to search
second to video
third to channel
What I try to create is dic that have
Title of the video
Thumbnails of the video
and the profile of the channel that make the video.
here you can see the code and the requests I send:
def get(self,request):
search_url = "https://www.googleapis.com/youtube/v3/search"
video_url = "https://www.googleapis.com/youtube/v3/videos"
channel_url = "https://www.googleapis.com/youtube/v3/channels?part=snippet&id='+commaSeperatedList+'&fields=items(id%2Csnippet%2Fthumbnails)&key={}".format(settings.YOUTUBE_DATA_API_KEY)
para_search = {
'part': 'snippet',
'q': 'Learn Python' ,
'key': settings.YOUTUBE_DATA_API_KEY,
'maxResults': 3,
'type': 'video'
}
search_response = requests.get(search_url,params=para_search)
print(search_response.text)
results = search_response.json()['items']
ids =[]
for result in results:
ids.append(result['id']['videoId'])
para_videos = {
'part': 'snippet',
'key': settings.YOUTUBE_DATA_API_KEY,
'id':','.join(ids),
}
video_response = requests.get(video_url, params=para_videos)
print(video_response.text)
results = video_response.json()['items']
dict_youtube = {}
list_youtube = []
channelIdList = []
for result in results:
dict_youtube = {
'title': result['snippet']['title'],
'thumbnails': result['snippet']['thumbnails']['high']['url'],
'channelId': result['snippet']["channelId"],
}
channelIdList.append(result['snippet']["channelId"])
list_youtube.append(dict_youtube)
param_channel = {
'part':'snippet,contentDetails,statistics',
'key':settings.YOUTUBE_DATA_API_KEY,
'id':','.join(channelIdList)
}
channel_response = requests.get(channel_url,params=param_channel)
print(channel_response.text)
results = channel_response.json()['items']
profile = []
profile_dic = {}
for result in results:
profile_dic = {
'channelId': result['id'],
'profile': result['snippet']['thumbnails']['default']['url'],
}
profile.append(profile_dic)
print(profile)
print(list_youtube)
Input:
profile = [{'channelId': 'UC8butISFwT-*******', 'profile': 'https://yt3.ggpht.com/ytc/A*******ifQn-nYNfkgLvVPkw=s88-********-no-rj'}, {'channelId': 'UCWv7*******mDpPBA', 'profile': 'https://yt3.ggpht.com/tBEPr-zTNXEeae7VZK******2PXSwzMBKVR7W0MI7gyND8=s88-c-k-c0x00ffffff-no-rj'}]
list_youtube = [{'title': 'Learn Python - Full Course for Beginners [Tutorial]', 'thumbnails': 'https://i.ytimg.com/vi/rf****bw/hqdefault.jpg', 'channelId': 'UC******wT-Wl7EV0hUK0BQ'}, {'title': 'Python for Beginners - Learn Python in 1 Hour', 'thumbnails': 'https://i.ytimg.com/vi/kqt*****8/hqd****t.jpg', 'channelId': 'UCWv7*********pPBA'}, {'title': 'Python Tutorial - Python Full Course for Beginners', 'thumbnails': 'https://i.ytimg.com/vi/_uQrJ0TkZlc/hqdefault.jpg', 'channelId': 'U********PBA'}]
As you can see, I've created two lists, each with dictionaries.
And every dictionary has a common key I created and it is channelId
What I want to do is union between dictionaries having the same value in the channelId key, the first list has fewer dictionaries than the second list.
How do I combine the two lists and dictionaries so that everything is compatible
That eventually I will have a list with dictionaries that has the key
'title':
'thumbnails':
'channelId':
'profile':
something like that for example:
[{'title':.... , 'thumbnails':... , 'channelId':... , 'profile':... ,} , { ... }, ...]
That sounds like the classical join operation. You can use a filter to identify the elements that match by id and then update the dictionary with its values like so.
This assumes you have at most 1 video per profile. You might need to flip the variables/add logic depending on their relation
for dic in profile:
vids = filter(lambda yt: yt["channelId"] == dic["channelId"], list_youtube)
for vid in vids:
dic.update(vid)
return dic

Place Primary key inside JSON response

The JSON response i'm getting is as below.
In my code i'am trying to fetch the list from the db, as per above img. In the result primary key is coming outside of the fields for each record. How can i place it inside the fields for every record like.
"results":[
"fields":{
"pk": "F09087687633",
"company_name": "Tata",
}
]
Below is my code:
views.py (In below code for loop is to remove app name from the results, same i use to remove primary key, it is working but how can i place it inside for each fields.)
#csrf_exempt
def fleet_owner_list(request):
page_number = json.loads(request.body)
records,total_pages = FleetOwner.get_all_owners(page_number)
for data in range(len(records)):
del records[data]['model']
returnObject = {
"page" : page_number,
"total_results":len(records),
"total_pages":total_pages,
"status" : messages.RETRIVAL_SUCCESS,
"message" : messages.FLEETOWNER_DATA_RETRIEVE_SUCCESS,
"results" : records
}
models.py
#classmethod
def get_all_owners(cls,page_number):
data = cls.objects.filter(is_deleted = False)
page_numbers = page_number
pegination_result, total_page_count = list_paginate(data, page_numbers)
data = serializers.serialize("json", pegination_result)
data = json.loads(data)
return data, total_page_count
paginator.py (This is a common function i'm using for all the list functions to perform django pagination.)
def list_paginate(data,page_numbers):
paginator = Paginator(data,10)
page = page_numbers
try :
records = paginator.page(page)
except PageNotAnInteger:
records = paginator.page(1)
except EmptyPage:
records = paginator.page(paginator.num_pages)
return records, paginator.num_pages
pegination_result, total_page_count = list_paginate(data, page_numbers)
data = serializers.serialize("json", pegination_result)
data = json.loads(data)
return data, total_page_count
By default this is how Django serialize a queryset into JSON Objects. The Django documentation also state the same. The whole collection is just represented as an array and the objects are represented by JSON objects with three properties: “pk”, “model” and “fields”. “fields” is again an object containing each field’s name and value as property and property-value respectively. i.e.,
[
{
"pk": "4b678b301dfd8a4e0dad910de3ae245b",
"model": "sessions.session",
"fields": {
"expire_date": "2013-01-16T08:16:59.844Z",
...
}
}
]
If you look at the Serializer class implementation you can find a get_dump_object method which is responsible for the final JSON output for an object. i.e.,
def get_dump_object(self, obj):
data = {'model': str(obj._meta)}
if not self.use_natural_primary_keys or not hasattr(obj, 'natural_key'):
data["pk"] = self._value_from_field(obj, obj._meta.pk)
data['fields'] = self._current
return data
In other teams this is the method responsible for the below format,
{
"pk": "pk",
"model": "model",
"fields": {
"field1": "2013-01-16T08:16:59.844Z",
...
}
}
Since you want the pk field inside the fields you should create your own JSON serializer class and override the get_dump_object method like the below one,
>>> import json
>>> from pprint import pprint
>>> from django.core.serializers.json import Serializer as JSONSerializer
>>>
>>> class MyCustomSerializer(JSONSerializer):
... def get_dump_object(self, obj):
... data = {'model': str(obj._meta)}
... data['fields'] = self._current
... if not self.use_natural_primary_keys or not hasattr(obj, 'natural_key'):
... data['fields'].update({'pk': self._value_from_field(obj, obj._meta.pk)})
... return data
...
>>> pprint(json.loads(MyCustomSerializer().serialize(User.objects.all())))
[{'fields': {'date_joined': '2019-07-13T05:52:37.885Z',
'email': 'user1#gmail.com',
'first_name': 'User',
'groups': [],
'is_active': True,
'is_staff': False,
'is_superuser': False,
'last_login': None,
'last_name': '1',
'password': '',
'pk': 1,
'user_permissions': [],
'username': ''},
'model': 'auth.user'}]
# You can see that `pk` is now inside the 'fields' key.
>>> json.loads(MyCustomSerializer().serialize(User.objects.all()))[0]['fields']['pk']
1

Python places escape symbols in the Swagger web services response

I have an store procedure Oracle that returns a variable type CLOB with information in JSON format. That variable caught her in a Python
and I return it for a Web Service. The store procedure output is of this style:
{"role":"Proof_Rol","identification":"31056235002761","class":"Proof_Clase","country":"ARGENTINA","stateOrProvince":"Santa Fe","city":"Rosario","locality":"Rosario","streetName":"Brown","streetNr":"2761","x":"5438468,710153","y":"6356634,962204"}
But at the Python service exit it is shown as follows:
{"Atributos": "{\"role\":\"Proof_Rol\",\"identification\":\"31056235002761\",\"class\":\"Proof_Clase\",\"country\":\"ARGENTINA\",\"stateOrProvince\":\"Santa Fe\",\"city\":\"Rosario\",\"locality\":\"Rosario\",\"streetName\":\"Brown\",\"streetNr\":\"2761\",\"x\":\"5438468,710153\",\"y\":\"6356634,962204\"}"}
Does anyone know how to prevent the escape characters from entering that string at the exit of the service?
Part of my Python Code is:
api = Api(APP, version='1.0', title='attributes API',
description='Attibute Microservice\n'
'Conection DB:' + db_str + '\n'
'Max try:' + limite)
ns = api.namespace('attributes', description='Show descriptions of an object')
md_respuesta = api.model('attributes', {
'Attribute': fields.String(required=True, description='Attribute List')
})
class listAtriClass:
Attribute = None
#ns.route('/<string:elementId>')
#ns.response(200, 'Success')
#ns.response(404, 'Not found')
#ns.response(429, 'Too many request')
#ns.param('elementId', 'Id Element (ej:31056235002761)')
class attibuteClass(Resource):
#ns.doc('attributes')
#ns.marshal_with(md_respuesta)
def post(self, elementId):
try:
cur = database.db.cursor()
listOutput = cur.var(cx_Oracle.CLOB)
e, l = cur.callproc('attributes.get_attributes', (elementId, listOutput))
except Exception as e:
database.init()
if database.db is not None:
log.err('Reconection OK')
cur = database.db.cursor()
listOutput = cur.var(cx_Oracle.CLOB)
e, l = cur.callproc('attributes.get_attributes', (elementId, listOutput))
print(listOutput)
else:
log.err('Conection Fails')
listOutput = None
result = listAtriClass()
result.Attribute =listOutput.getvalue()
print(result.Attribute)
return result, 200
Attribute is defined to render as a fields.String but actually it should be defined to render as fields.Nested.
attribute_fields = {
"role": fields.String,
"identification": fields.String,
"class": fields.String,
# ...you get the idea.
}
md_respuesta = api.model('attributes', {
'Attribute': fields.Nested(attribute_fields)
})
Update for flask-restplus
In flask-restplus, a nested field must also register a model.
attribute_fields = api.model('fields', {
"role": fields.String,
"identification": fields.String,
"class": fields.String,
# ...you get the idea.
})
Another way is to inline attribute_fields instead of registering a separate model for it.
md_respuesta = api.model('attributes', {
'Attribute': {
'role': fields.String,
'identification': fields.String,
'class': fields.String,
# ...you get the idea.
}
})

mediaItems.search not working with albumId

When I run the following code I get this error.
{'error': {'code': 400, 'message': 'Invalid JSON payload received. Unknown name "album_id": Proto field is not repeating, cannot start list.', 'status': 'INVALID_ARGUMENT', 'details': [{'#type': 'type.googleapis.com/google.rpc.BadRequest', 'fieldViolations': [{'description': 'Invalid JSON payload received. Unknown name "album_id": Proto field is not repeating, cannot start list.'}]}]}}
If I remove the "albumId": ["albumid code"] it works fine and returns
10 new items, total 10
def _actually_list_media_items(session):
ret = []
params = {
'fields': 'mediaItems(id,baseUrl,filename,mimeType,productUrl),nextPageToken',
}
search_json = {
"pageSize": 10,
"albumId": ["<albumid code>"],
"filters": {
"includeArchivedMedia": False,
"contentFilter": {
"excludedContentCategories": [
"DOCUMENTS",
"RECEIPTS",
"SCREENSHOTS",
"UTILITY",
"WHITEBOARDS",
]
},
"mediaTypeFilter": {
"mediaTypes": [
"PHOTO",
],
},
},
}
tmp = 0
while tmp < 1:
rsp = session.post(
'https://photoslibrary.googleapis.com/v1/mediaItems:search',
params=params,
json=search_json,
).json()
if 'error' in rsp:
print(rsp)
cur = [m for m in rsp.get('mediaItems', [])]
ret += cur
print(f'{len(cur)} new items, total {len(ret)}')
pageToken = rsp.get('nextPageToken')
if pageToken is None:
break
params['pageToken'] = pageToken
tmp = tmp + 1
return ret
The comment about albumId and filters being exclusive is correct, so you need to pick one or the other. However, assuming you want to use the albumId by itself, you need to remove the square brackets around your albumid code, here's a clip from my code:
searchbody = {
"albumId": album_id,
"pageSize": 10
}
print(searchbody)
mediaresults = gAPIservice.mediaItems().search(body=searchbody).execute()
mediaitems = mediaresults.get('mediaItems', [])
for item in mediaitems:
print(u'{0} ({1})'.format(item['filename'], item['id']))
Edit:
Apparently you can't use albumId and filters together: source
filters: object(Filters)
Filters to apply to the request. Can't be set in conjunction with an albumId.
Aside from that, albumId is a supposed to be a string not an array: source
"albumId": "<albumid code>",

Adding to session dictionary

I'm trying to create a view function which updates the users cart (session) on add and removal.
def shoppingCartAdd(request):
data = json.loads(request.POST['post_data'])
if 'shopping_cart' not in request.session: #<-- create the session dict
request.session['shopping_cart'] = {}
if data["action"] == "add":
with open(MEDIA_ROOT + '/json/products.js', 'r') as json_file:
products = json.loads(json_file.read()) #<-- json file that contains product information
json_file.close()
item = products["products"][data["id"]] #<-- get the item info from json
#If the item is not in the session add it. Otherwise do something.
if data["id"] not in request.session['shopping_cart']:
request.session['shopping_cart'][data["id"]] = item
else:
print('Exists')
#Do something else.
#Remove the item from the dict.
if data["action"] == "remove":
request.session['shopping_cart'].pop([data["id"]], None)
context = {'shoppingCart' : request.session['shopping_cart']}
return JsonResponse(context)
My problem is that I cannot add more than two items to my dictinary. I'm not sure what I'm doing wrong here. If I click on the first item it'll create the session and add it properly, and if I try to add it again it'll print out "exists". But if I add a second and try to add it again, it will not print out "exists" on the 2nd item.
Here's a print of my session with two items. using print(request.session['shopping_cart'])
{
'38': {'name': 'hergh', 'price': 23, 'active': 'active', 'pk': 38, 'imageURL': '/media/gg_faUCQOg.jpg', 'type': 'sokker', 'amount': 13},
'39': {'name': 'dea', 'price': 1, 'active': 'active', 'pk': 39, 'imageURL': '/media/gg_6ECtbKE.jpg', 'type': 'sokker', 'amount': 1}
}
According to the documentation - https://docs.djangoproject.com/en/dev/topics/http/sessions/#when-sessions-are-saved
By default, Django only saves to the session database when the session has been modified – that is if any of its dictionary values have been assigned or deleted.
You can set the SESSION_SAVE_EVERY_REQUEST setting to True, this will force save the session on every request.

Categories