mercredi 27 mars 2019

How can I return a new non-repeating item from a list in Django while keeping track of previous items?

I'm working on an app where a user can select a category, which will return a random selection from that category. The main functionality I'm trying to implement is once an item is selected, it can no longer be randomly selected in session.

For example, we have 3 categories of photos: landscape, urban, and portraits, each with 5 photos. A user selects urban, is then redirected to a details page with a random photo from urban category. He can either refresh the page or click a button to get a new photo from that category. When that category is out of new photos, he is redirected home.

I am able to get my random item from the selected category through converting a queryset to a list, but the data isn't persisting. On every refresh the list I have resets, thus a previously selected photo can come up again, ignoring the the fact that I removed the item from the list after it was selected.

Here's the views.py with the function responsible for this:

def randomPhoto(request, pk, **kwargs):

    # queryset to get all photos from selected category
    gallery = list(Photos.objects.filter(id=pk)
    .values_list("partof__category", flat=True))

    # select random photo from list
    last = len(gallery) -1
    randomInt = random.randint(0, last)
    randomPic = gallery[randomInt]

    gallery.remove(randomPic)

    if len(gallery) == 0:
        return render(request, 'gallery/category_select.html')

        photoDetails = {
        'category' : Category.objects.get(id=pk),
        'author' : Author.objects.get(tookin__category=randomPic),
        'uploadedPhoto' : 'http://localhost:8000/media/' + 
    str(Photo.objects.get(category=randomPic).photoUpload),
        'randomPic' : randomPic,
        }

        return render(request, 'gallery/random_photo.html', {'photoDetails': photoDetails})

The functionality I'm looking for is (where each number is an object/item in list):

  • User selects urban category:
    • urban has the following items: [1, 2, 3, 4, 5]
    • random [3] selected from urban
    • urban now has [1, 2, 4, 5]
  • User refreshes:
    • random [4] selected
    • urban now has [1, 2, 5]
  • User refreshes:
    • random [2] selected
    • urban now has [1, 5]
  • User refreshes:
    • random [5] selected
    • urban now has [1]
  • User refreshes:
    • random [1] selected
    • urban now has []
  • User is redirected home

I believe my problem lies in having to configure either sessions or cookies to have the data persist in an anonymous session. Eventually I will be adding a Users module so each user will have their browsing history saved but for now I want it to work just as an anonymous user.

I've tried adding SESSION_SAVE_EVERY_REQUEST = True to settings.py and placing request.session.modified = True in my views.py, though I doubt I'm implementing them properly. I've read some SO questions on sessions and cookies but wasn't able to find something to work with my issue. The Django Sessions Doc seemed interesting but overwhelming. I'm not sure where to begin trying to experiment with wiring the sessions aspect together.

I've been stuck on this issue for a few days now and am wondering if there's an easy/Pythonic way to achieve having my web app give me a non-repeating item from a list until none are left within the session.




Aucun commentaire:

Enregistrer un commentaire