OrderedDict of OrderedDict and storing data in YAML Issues - python

So basically I have an app I'm making that has user data which I want to backup and load in the database. I'm storing the data in yml files. Now, a user has posts. Each post has a timestamp, text and tags. I want to use an ordereddictionary in order to retain order when I write the data in the YAML files. Currently, I'm doing something like this:
def get_posts(user):
posts_arr = []
for post in user.posts.all():
temparr = OrderedDict()
temparr['timestamp'] = post.created_at.strftime("%Y-%m-%d %H:%M %p")
temparr['text'] = post.text
temparr['tags'] = (',').join(list(post.tags.all().values_list('field',flat=True)))
posts_arr.append(temparr)
return posts_arr
As you can see, I'm using an array of orderectionaries and that I think is the reason my posts for each user are not ordered. How can I resolve this issue.
I am returning this posts_arr object to be stored within another ordereddictionary.
Also, I since the posts text is kind of nested and is a large block of text, I want to make sure that text is also stored in string literal block styles.

Basically, your issue is a misunderstanding on how ordered dictionaries work in python. The python documentation states that an OrderedDict is a:
dict subclass that remembers the order entries were added
https://docs.python.org/3/library/collections.html#module-collections
Personally, I'd recommend a list of dictionaries created from a pre-sorted list of posts. In this case, it would look something like this if we were to keep the majority of your code as-is:
def get_posts(user):
posts_arr = []
sorted_posts = sorted(user.posts.all(), key=(lambda post: post.created_at)) # Sorts the posts based on their created_at date
for post in sorted_posts:
temparr = dict()
temparr['timestamp'] = post.created_at.strftime("%Y-%m-%d %H:%M %p")
temparr['text'] = post.text
temparr['tags'] = (',').join(list(post.tags.all().values_list('field',flat=True)))
posts_arr.append(temparr)
return posts_arr
You could use list comprehensions to build this list from the sorted one like chepner suggested, but I don't want to change too much.

Use an ordinary dict (or OrderedDict if you really need to) for each post, and use a list for the collection of all posts. Once you do that, it's a short jump to using a list comprehension to define the return value directly.
def get_posts(user):
return [{
'timestamp': post.created_at.strftime("%Y-%m-%d %H:%M %p"),
'text': post.text,
'tags': ','.join(list(post.tags.all().values_list('field', flat=True)))
} for post in user.posts.all()]

Related

Read Data in a nested Json

I have this very long json here: https://textup.fr/601885q4 and would like to read a data that is in one of the "payment_token_contract" specifically those with "id":1
My problem is that I don't get how to call the specific dictionary as they all have the same name. Is this even possible, I'm not used to manipulating such complex objects as I'm a beginner.
I would have tried something like:
["orders][x]["id":1]["base_price"]
with x being in a for loop that iterates through each "orders" present.
But I can't manage to put it all together. Thanks for your help !
You can use a for loop to iterate over the orders, you can check the value of the payment contract id and if its 1 then print the base price for that order
import json
jdata = "yourjson"
jdict = json.loads(jdata)
for order in jdict["orders"]:
if order['payment_token_contract']['id'] == 1:
print(order["base_price"])
I have omited the json data as its to long but you can image jdata is the string of your json
OUTPUT
149000000000000000000

Python JSON - Retrieve JSON from constantly changing label?

Let's say my JSON looks like this
In Post, the labels are constantly changing. If they were stable, I can retrieve the JSON value by just doing this and retrieving the title
['payload']['references']['Post']['CONSTANT']['title']
But, the ['CONSTANT'] or ['4c708604012f'] is always changing if there are new Posts so I'm not sure how I can retrieve it the title?
Thanks for any help
What you need to do is return all of the .keys() of the changing dictionaries, and then reference them in a loop.
titles = []
for constant in json['payload']['references']['Post'].keys():
titles.append(json['payload']['references']['Post'][constant]['title'])
Loop through all the elements of Post:
for post in var['payload']['references']['Post'].items():
print(post['title']
You can collect all of them in a list:
titles = [post['title'] for post in var['payload']['references']['Post'].items()]

json change dictionary item to a list with one dictionary

I'm working with a Rest Api for finding address details. I pass it an address and it passes back details for that address: lat/long, suburb etc. I'm using the requests library with the json() method on the response and adding the json response to a list to analyse later.
What I'm finding is that when there is a single match for an address the 'FoundAddress' key in the json response contains a dictionary but when more than one match is found the 'FoundAddress' key contains a list of dictionaries.
The returned json looks something like:
For a single match:
{
'FoundAddress': {AddressDetails...}
}
For multiple matches:
{
'FoundAddress': [{Address1Details...}, {Address2Details...}]
}
I don't want to write code to handle a single match and then multiple matches.
How can I modify the 'FoundAddress' so that when there is a single match it changes it to a list with a single dictionary entry? Such that I get something like this:
{
'FoundAddress': [{AddressDetails...}]
}
If it's the external API sending responses in that format then you can't really change FoundAddress itself, since it will always arrive in that format.
You can change the response if you want to, since you have full control over what you've received:
r = json.parse(response)
fixed = r['FoundAddress'] if (type(r['FoundAddress']) is list) else [r['FoundAddress']]
r['FoundAddress'] = fixed
Alternatively you can do the distinction at address usage time:
def func(foundAddress):
# work with a single dictionary instance here
then:
result = map(func, r['FoundAddress']) if (type(r['FoundAddress']) is list) else [func(r['FoundAddress'])]
But honestly I'd take a clear:
if type(r['FoundAddress']) is list:
result = map(func, r['FoundAddress'])
else:
result = func(r['FoundAddress'])
or the response fix-up over the a if b else c one-liner any day.
If you can, I would just change the API. If you can't there's nothing magical you can do. You just have to handle the special case. You could probably do this in one place in your code with a function like:
def handle_found_addresses(found_addresses):
if not isinstance(found_addresses, list):
found_addresses = [found_addreses]
...
and then proceed from there to do whatever you do with found addresses as if the value is always a list with one or more items.

How to convert Google Charts Data Table into python dictionary?

I'm using the Google Visualization Library for python (gviz) to generate chart objects. This works great for generating JSON that can be read by the Google Charts using the DataTable.ToJSon method. What I'm trying to do now, however, is add multiple Google Chart data tables to one JSON dictionary. In other words, what I'm making now is this:
Chart_Data = JSON_Chart_Data_1
and what I want to make is this:
Chart_Data = {'Chart_1' : JSON_Chart_Data_1,
'Chart_2' : JSON_Chart_Data_2,}
Where Chart_Data is converted into a JSON string in both cases.
I'm pretty sure I can do this by converting the JSON string from gviz back into a python dictionary, compile the strings in a container dictionary as necessary, and then convert that container dictionary back into JSON, but that doesn't seem like a very elegant way to do it. Is there a better way? What I'm picturing is a .ToPythonObject method equivalent to .ToJSon, but there doesn't appear to be one in the library.
Thanks a lot,
Alex
I ended up doing my original, inelegant, solution to the problem with this function:
def CombineJson(JSON_List):
#Jsonlist should be a list of tuples, with the dictionary key and the json file to go with that.
#eg: [('json1', 'some json string'), ('json2', 'some other json string')]
Python_Dict = {}
for tup in JSON_List:
parsed_json = json.loads(tup[1])
Python_Dict[tup[0]] = parsed_json
BigJson = json.dumps(Python_Dict)
return BigJson
Thanks guys,
Alex

How do I put a dictionary in the datastore?

Is there a good way to store a Python dictionary in the datastore? I want to do something like the following:
from google.appengine.ext import db
class Recipe(db.Model):
name = db.StringProperty()
style = db.StringProperty()
yeast = db.StringProperty()
hops = db.ListofDictionariesProperty()
Of course, that last line doesn't actually work. I need hops to be a list of key-value pairs, where the key is always a string and the value can be a string, int, or float, but I can't see anything in that would allow me to do that in the Property classes.
Serializing a dict with repr is a good way to do it. You can then reconstitute it with eval, or if you don't trust the data, a "safe eval".
An advantage of repr over pickling is that the data is readable in the database, even queryable in desperate cases.
You can use json
You could pickle the dictionary and store it as a StringProperty.
I'm pretty sure there's no way to store a Python dictionary. But why not just place what you'd like in hops as a second model?
Also, as mentioned by John you could use pickle, but (and correct me if I'm wrong) store it as a Blob value instead.
Your options are basically to use pickle, to use a db.Expando and make each key in the dict a separate property, or to have a StringListProperty of keys and one of values and zip() them back to a dict when reading.
You can use JsonProperty.
Value is a Python object (such as a list or a dict or a string) that is serializable using Python's json module; Cloud Datastore stores the JSON serialization as a blob. Unindexed by default.
Optional keyword argument: compressed.
from google.appengine.ext import ndb
class Article(ndb.Model):
title = ndb.StringProperty(required=True)
stars = ndb.IntegerProperty()
tags = ndb.StringProperty(repeated=True)
info = ndb.JsonProperty()
I did it like this:
class MyEntity(db.Model):
dictionary_string = db.StringProperty()
payload = {{}...{}}
# Store dict
my_entity = MyEntity(key_name=your_key_here)
my_entity.dictionary_string = str(payload)
my_entity.put()
# Get dict
import ast
my_entity_k = db.Key.from_path('MyEntity', your_key_here)
my_entity = db.get(my_entity_k)
payload = ast.literal_eval(my_entity.dictionary_string)

Categories

Resources