Как заставить таймер не сбрасываться при перезагрузки страницы или отправки post-запросов сервера, а запомнить время первоначальной загрузки страницы?
настройки жизни сессии SESSION_COOKIE_AGE=120 (2 минуты)
При первом рендере страницы шаблона confirm_email.html загружается форма ввода кода из 6 полей, если не вводить код(бездействовать) и подождать то каждую минуту будет проверяться слаться get запрос из скрипта check_session.js каждую минуту во вьюшку CheckSession и она будет отдавать json ответ обратно и за 30 секунд до окончания жизни сессии сработает скрипт timer.js и после окончания 2 минут скриптом check_session.js пользователь будет перенаправлен на главную страницу- здесь все хорошо!!!!
Теперь сам вопрос: Если при первом рендере страницы шаблона confirm_email.html (например страница загрузилась в 18:00:00) загружается форма ввода кода из 6 полей, и допустим ты через 30 секунд(в 18:00:30) (до этого времени ты бездействовал) ты вводишь неправильный код то отправляется post запрос во вьюшку ConfirmEmail и скрипт check_session.js будет слать запрос во вьюшку CheckSession от этого времени, от post запроса, то есть скрипт отправит запрос в 18:01:30 то есть через минуту от post запроса, но не от того времени как загрузилась страница в 18:00:00
Нужно, чтобы запомнилось время первоначальной загрузки страницы, и get запросы также отправлялись через минуту, но при отправке post запроса на сервер(при вводе в формы неправильного кода) таймер не сбрасывался и не слал get запрос через минуту от этого post-запроса!!!
views.py ConfirmEmail:
class ConfirmEmail(SuccessMessageMixin,View):
template_name = 'mos_sel/confirm_email.html'
success_message='Пользователь %(username)s был успешно создан.\nЗалогиньтесь, чтобы продолжить'
def get(self, request, *args, **kwargs):
form = EmailConfirmationForm()
user_email = request.session.get('email','')
username = request.session.get('username', user_email.split('@')[0])
anonymized_email = request.session.get('anonymized_email', '')
if not user_email: # Если сессия истекла
User = get_user_model()
user = User.objects.get(email=user_email)
user.delete() # Удалить пользователя
# Удаляем email_confirmed из сессии и обновляем сессию
del request.session['email']
request.session.modified = True
return redirect(reverse_lazy('Login')) # Перенаправить на главную страницу
request.session['email_confirmed'] = False
request.session['last_activity'] = tz.now().isoformat()
return render(request, self.template_name, {'form': form, 'user_email': user_email, 'username': username, 'show_modal': True,'session_timeout': settings.SESSION_COOKIE_AGE,})
def post(self, request, *args, **kwargs):
user_email = request.session.get('email', '')
print(f'сессия email_confirmed вначале post {request.session["email_confirmed"]}')
if not user_email: # Если сессия истекла
User = get_user_model()
user = User.objects.get(email=user_email)
user.delete() # Удалить пользователя
return redirect(reverse_lazy('Login')) # Перенаправить на главную страницу
form = EmailConfirmationForm(request.POST)
username = request.session.get('username', user_email.split('@')[0])
anonymized_email = request.session.get('anonymized_email', '')
if form.is_valid():
code = form.cleaned_data['code1'] + form.cleaned_data['code2'] + form.cleaned_data['code3'] + form.cleaned_data['code4'] + form.cleaned_data['code5'] + form.cleaned_data['code6']
User = get_user_model()
user = User.objects.get(email=user_email)
email_confirmation = EmailConfirmation.objects.filter(
code=code,
user=user
).first()
if email_confirmation:
email_confirmation.delete()
user.is_active = True
user.email_confirmed = True # Устанавливаем email_confirmed в True
request.session['email_confirmed'] = True
user.save()
success_message = self.success_message % dict(username=username,)
messages.success(request, success_message)
return redirect(reverse_lazy('SuccessMessage'))
else:
messages.error(request, 'Неправильный код. Попробуйте снова.')
else:
messages.error(request, 'Код введен неверно.')
return render(request, self.template_name, {'form': form, 'user_email': user_email, 'username': username, 'show_modal': True,'session_timeout': settings.SESSION_COOKIE_AGE,})
views.py ConfirmEmail:
class ConfirmEmail(SuccessMessageMixin,View):
template_name = 'mos_sel/confirm_email.html'
success_message='Пользователь %(username)s был успешно создан.\nЗалогиньтесь, чтобы продолжить'
def get(self, request, *args, **kwargs):
form = EmailConfirmationForm()
user_email = request.session.get('email','')
username = request.session.get('username', user_email.split('@')[0])
anonymized_email = request.session.get('anonymized_email', '')
if not user_email: # Если сессия истекла
User = get_user_model()
user = User.objects.get(email=user_email)
user.delete() # Удалить пользователя
# Удаляем email_confirmed из сессии и обновляем сессию
del request.session['email']
request.session.modified = True
return redirect(reverse_lazy('Login')) # Перенаправить на главную страницу
request.session['email_confirmed'] = False
request.session['last_activity'] = tz.now().isoformat()
return render(request, self.template_name, {'form': form, 'user_email': user_email, 'username': username, 'show_modal': True,'session_timeout': settings.SESSION_COOKIE_AGE,})
def post(self, request, *args, **kwargs):
user_email = request.session.get('email', '')
print(f'сессия email_confirmed вначале post {request.session["email_confirmed"]}')
if not user_email: # Если сессия истекла
User = get_user_model()
user = User.objects.get(email=user_email)
user.delete() # Удалить пользователя
return redirect(reverse_lazy('Login')) # Перенаправить на главную страницу
form = EmailConfirmationForm(request.POST)
username = request.session.get('username', user_email.split('@')[0])
anonymized_email = request.session.get('anonymized_email', '')
if form.is_valid():
code = form.cleaned_data['code1'] + form.cleaned_data['code2'] + form.cleaned_data['code3'] + form.cleaned_data['code4'] + form.cleaned_data['code5'] + form.cleaned_data['code6']
User = get_user_model()
user = User.objects.get(email=user_email)
email_confirmation = EmailConfirmation.objects.filter(
code=code,
user=user
).first()
if email_confirmation:
email_confirmation.delete()
user.is_active = True
user.email_confirmed = True # Устанавливаем email_confirmed в True
request.session['email_confirmed'] = True
user.save()
success_message = self.success_message % dict(username=username,)
messages.success(request, success_message)
return redirect(reverse_lazy('SuccessMessage'))
else:
messages.error(request, 'Неправильный код. Попробуйте снова.')
else:
messages.error(request, 'Код введен неверно.')
return render(request, self.template_name, {'form': form, 'user_email': user_email, 'username': username, 'show_modal': True,'session_timeout': settings.SESSION_COOKIE_AGE,})
template confirm_email.html
<body id='custom_background_image' data-session-timeout="{{ session_timeout }}" data-last-activity="{{ request.session.last_activity }}" data-url="{% url 'check_session' %}">
<div class="container">
<!-- Задний фон -->
<div class="overlay"></div>
<!-- Модальное окно -->
<div class="modal fade {% if show_modal %}show d-block{% endif %}" id="confirmEmailModal" tabindex="-1" aria-labelledby="confirmEmailModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered mx-auto my-custom-modal">
<div class="modal-content " id="modal_background_color">
<div class="modal-header">
<h5 class="modal-title text-center" id="confirmEmailModalLabel"><strong>Завершение регистрации </strong></h5>
<button type="button" id="close_registr_modal" data-url="{% url 'Home' %}" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div id="insert_timer"></div>
{% if messages %}
<div class="alert alert-danger">
<strong>Ошибка подтверждения:</strong><br>
{% for message in messages %}
{{ message }}
{% endfor %}
</div>
{% endif %}
<p> <strong> Введите код подтверждения </strong></p>
<p> Приветствуем Вас, <strong> {{ username }}</strong>!</p>
<div class="text mb-4">Мы отправили 6-значный код на <strong>{{ user_email }}</strong>
Подтвердите, что номер принадлежит вам, чтобы обезопасить свою учетную запись
</div>
<form method="post">
{% csrf_token %}
<div class="form-group row justify-content-between">
<div class="col"><input type="text" name="code1" maxlength="1" class="form-control digit-input" id="code1"></div>
<div class="col"><input type="text" name="code2" maxlength="1" class="form-control digit-input" id="code2"></div>
<div class="col"><input type="text" name="code3" maxlength="1" class="form-control digit-input" id="code3"></div>
<div class="col"><input type="text" name="code4" maxlength="1" class="form-control digit-input" id="code4"></div>
<div class="col"><input type="text" name="code5" maxlength="1" class="form-control digit-input" id="code5"></div>
<div class="col"><input type="text" name="code6" maxlength="1" class="form-control digit-input" id="code6"></div>
</div>
<div class="d-flex justify-content-end mt-2 mb-1">
<button type="submit" id="confirm_code" class="btn btn-primary">Подтвердить</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
views.py CheckSession:
class CheckSession(View):
def get(self, request, *args, **kwargs):
# Проверка времени последней активности
last_activity_str = request.session.get('last_activity', None)
if last_activity_str:
last_activity = datetime.fromisoformat(last_activity_str)
else:
last_activity = tz.now()
session_timeout = tz.timedelta(seconds=settings.SESSION_COOKIE_AGE)
email_confirmed = False
if tz.now() - last_activity > session_timeout:
User = get_user_model()
users = User.objects.filter(email=request.session.get('email', ''))
if users.exists():
user = users.first()
user.delete()
# Если прошло более 5 минут, считаем сессию подтвержденной фиктивно
email_confirmed = True
# Обновляем состояние сессии
request.session['email_confirmed'] = email_confirmed
request.session.save()
# Возвращаем JsonResponse без 'last_activity'
return JsonResponse({'email_confirmed': email_confirmed})
@csrf_exempt
def post(self, request, *args, **kwargs):
try:
user = User.objects.get(email=request.session.get('email', ''))
if not user.email_confirmed:
user.delete()
# Удаляем email_confirmed из сессии и обновляем сессию
del request.session['email_confirmed']
request.session.modified = True
return JsonResponse({'email_confirmed': False})
else:
return JsonResponse({'email_confirmed': True})
except User.DoesNotExist:
return JsonResponse({'error': 'User does not exist.'})
check_session.js :
let checkSessionUrl;
var body = document.querySelector('body[data-url]');
let navbar = document.querySelector('nav[data-url]');
if (body) {
checkSessionUrl = body.getAttribute('data-url');
} else if (navbar) {
checkSessionUrl = navbar.getAttribute('data-url');
}
if (checkSessionUrl) {
function checkSession() {
fetch(checkSessionUrl)
.then(response => response.json())
.then(data => {
if (data.email_confirmed === true) {
window.location.href = "/";
}
});
}
// Check the session every 1 minute
setInterval(checkSession, 60000);
}
timer.js :
let session_timeout;
let last_activ;
var body = document.querySelector('body');
if (body) {
session_timeout = body.getAttribute('data-session-timeout');
last_activ = body.getAttribute('data-last-activity');
const sessionExpiryTime = session_timeout * 1000;
console.log(session_timeout);
console.log(sessionExpiryTime);
const warningTime = 30 * 1000;
const lastActivity = new Date(last_activ);
console.log(lastActivity);
const sessionExpiryDate = new Date(lastActivity.getTime() + sessionExpiryTime);
function checkSession() {
const timeLeft = sessionExpiryDate - new Date();
// Найдите div с помощью его id
const warningDiv = document.getElementById('insert_timer');
if (warningDiv) {
// Установите его содержимое только если элемент найден
if (timeLeft <= warningTime) {
warningDiv.textContent = 'Ваша сессия истекает через ' + Math.round(timeLeft / 1000) + ' секунд';
}
}
}
setInterval(checkSession, 1000);
}