#django #session #random #django-queryset #data-persistence
#django #сессия #Случайный #django-набор запросов #сохранение данных
Вопрос:
Я работаю над приложением, в котором пользователь может выбрать категорию, которая вернет случайный выбор из этой категории. Основная функциональность, которую я пытаюсь реализовать, заключается в том, что после выбора элемента он больше не может быть выбран случайным образом в сеансе.
Например, у нас есть 3 категории фотографий: пейзажные, городские и портретные, в каждой по 5 фотографий. Пользователь выбирает urban, затем перенаправляется на страницу сведений со случайной фотографией из категории urban. Он может либо обновить страницу, либо нажать кнопку, чтобы получить новую фотографию из этой категории. Когда в этой категории заканчиваются новые фотографии, он перенаправляется домой.
Я могу получить свой случайный элемент из выбранной категории путем преобразования набора запросов в список, но данные не сохраняются. При каждом обновлении список, который у меня есть, сбрасывается, таким образом, ранее выбранная фотография может появиться снова, игнорируя тот факт, что я удалил элемент из списка после того, как он был выбран.
Вот views.py с функцией, ответственной за это:
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})
Функциональность, которую я ищу (где каждое число является объектом / элементом в списке):
- Пользователь выбирает городскую категорию:
- urban содержит следующие элементы: [1, 2, 3, 4, 5]
- случайный [3], выбранный из urban
- у urban теперь есть [1, 2, 4, 5]
- Пользователь обновляет:
- выбрано случайным образом [4]
- у urban теперь есть [1, 2, 5]
- Пользователь обновляет:
- выбрано случайным образом [2]
- у urban теперь есть [1, 5]
- Пользователь обновляет:
- выбранный случайным образом [5]
- у urban теперь есть [1]
- Пользователь обновляет:
- выбрано случайным образом [1]
- у urban теперь есть []
- Пользователь перенаправляется домой
Я полагаю, что моя проблема заключается в необходимости настраивать сеансы или файлы cookie, чтобы данные сохранялись в анонимном сеансе. В конечном итоге я добавлю модуль Users, чтобы у каждого пользователя сохранялась история посещенных страниц, но пока я хочу, чтобы он работал просто как анонимный пользователь.
Я пробовал добавлять SESSION_SAVE_EVERY_REQUEST = True
в settings.py
и помещать request.session.modified = True
в свой views.py
, хотя сомневаюсь, что правильно их реализую. Я прочитал несколько вопросов SO о сеансах и файлах cookie, но не смог найти что-либо для решения моей проблемы. Документ о сеансах Django показался интересным, но подавляющим. Я не уверен, с чего начать, пытаясь поэкспериментировать с объединением аспектов сессий.
Мне интересно, есть ли простой / Pythonic способ добиться того, чтобы мое веб-приложение выдавало мне неповторяющийся элемент из списка, пока в сеансе не останется ни одного.
Ответ №1:
Ваша проблема в том, что ваша переменная не переносится из одного запроса в следующий. Лучшим способом сделать это было бы использовать request.session = ...
для установки переменной, а затем проверить ее позже и выполнить действия. Вот пример, который вы можете расширить, чтобы сделать его по своему вкусу:
import random
from django.shortcuts import redirect
class TestView(View):
def get(self, request, *args, **kwargs):
gallery = request.session.get('gallery', None)
if (type(gallery) is list) and (len(gallery) == 0): # When list is empty, clear session amp; then redirect
del request.session['gallery']
request.session.modified = True
return redirect('<your_redirect_url>')
if gallery is None: # If first visit to page, create gallery list
gallery = list(models.Photos.objects.all().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)
request.session['gallery'] = gallery
return render(request, 'test.html', {})
Комментарии:
1. Спасибо за быстрый ответ. Это похоже на то, что я ищу. Я собираюсь реализовать нечто подобное сегодня вечером и обновить вас. Большое спасибо, Hybrid.
2. Я обновил представление, чтобы отразить вышеуказанные изменения. Теперь я продолжаю получать ошибку ‘str’ объект не имеет атрибута ‘session’. Есть ли конкретный способ активировать сеанс или назначить его? Я проверил свой settings.py и промежуточное программное обеспечение, и все остальное по умолчанию установлено в Django 2.1 и работает нормально.