Search code examples
pythonpython-3.xyamlpyyaml

OrderedDict of OrderedDict and storing data in YAML Issues


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.


Solution

  • 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.