Question

I have the issue of trying to pull a "random" item out of a database in my Flask app. This function only needs to return a video that wasn't recently watched by the user. I am not worried about multiple users right now. My current way of doing this does not work. This is what I am using:

@app.route('/_new_video')
def new_video():

Here's the important part I'm asking about:

    current_id = request.args.get('current_id')
    video_id = random.choice(models.Video.query.all()) # return list of all video ids
    while True:
        if video_id != current_id:
            new_video = models.Video.query.get(video_id)

and then I return it:

            webm = new_video.get_webm() #returns filepath in a string
            mp4 = new_video.get_mp4() #returns filepath in a string 
            return jsonify(webm=webm,mp4=mp4,video_id=video_id)

The random range starts at 1 because the first asset was deleted from the database, so the number 0 isn't associated with an id. Ideally, the user would not get a video they had recently watched.

Was it helpful?

Solution

I recommend using a collections.deque to store a recently watched list. It saves a list like collection of items, and as you add to it, if it gets to its max length, it automatically drops the oldest items, on a first in, first out basis.

import collections

And here's a generator that you can use to get random vids, that haven't been recently watched. The denom argument will allow you to change the length of the recently watched list because it's used to determine the max length of your recently_watched as a fraction of your list of vids.

def gen_random_vid(vids, denom=2):
    '''return  a random vid id that hasn't been recently watched'''
    recently_watched = collections.deque(maxlen=len(vids)//denom)
    while True:
        selection = random.choice(vids)
        if selection not in recently_watched:
             yield selection
             recently_watched.append(selection)

I'll create a quick list to demo it:

vids = ['vid_' + c for c in 'abcdefghijkl']

And here's the usage:

>>> recently_watched_generator = gen_random_vid(vids)
>>> next(recently_watched_generator)
'vid_e'
>>> next(recently_watched_generator)
'vid_f'
>>> for _ in range(10):
...     print(next(recently_watched_generator))
... 
vid_g
vid_d
vid_c
vid_f
vid_e
vid_g
vid_a
vid_f
vid_e
vid_c
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top