urlsafe_base64_decode возвращает None
В своем проекте я реализовал подтверждение адреса электронной почты.
Пользователь вводит в форму все необходимые для регистрации данные, после чего мы берем из атрибута cleaned_data адрес электронки и отправляем сообщение следующим способом:
@staticmethod
def send_verification_message_with_uid_and_token(request, consumer, token_generator,
use_https, template, subject):
current_site = get_current_site(request)
content = {
'domain': current_site.domain,
'uid': urlsafe_base64_encode(
force_bytes(consumer.pk)
),
'token': token_generator.make_token(consumer),
'protocol': 'https' if use_https else 'http'
}
body = render_to_string(template, content)
message = EmailMessage(subject, body, to=[consumer.email])
return message.send()
def save(self, **sending_data):
consumer = super().save(commit=False)
consumer.set_password(self.cleaned_data['password'])
self.send_verification_message_with_uid_and_token(consumer=consumer, **sending_data)
consumer.save()
return consumer
Вьюха отправки
class Registration(UnauthorizedRequiredMixin, FormView):
form_class = ConsumerCreationForm
template_name = 'consumers/registration.html'
email_subject = 'Confirm your account.'
email_template = 'mail/verification.html'
token_generator = default_token_generator
success_url = reverse_lazy('message_sent')
def form_valid(self, form):
sending_data = {
'use_https': self.request.is_secure(),
'template': self.email_template,
'subject': self.email_subject,
'token_generator': self.token_generator,
'request': self.request
}
form.save(**sending_data)
return super().form_valid(form)
Вьюха активации
class AccountActivation(TemplateView):
template_name = 'consumers/activation.html'
token_generator = default_token_generator
success_url = reverse_lazy('login')
@staticmethod
def get_consumer(uidb64):
uid = urlsafe_base64_decode(uidb64).decode() # здесь возвращается None
return Consumer.objects.get(pk=uid) # Здесь происходит ошибка Field 'id' expected a number but got b'None'. Обработки нет специально, чтобы разобраться.
def dispatch(self, request, *args, **kwargs):
consumer = self.get_consumer(kwargs['uidb64'])
valid_token = self.token_generator.check_token(consumer, kwargs['token'])
if consumer is not None and valid_token:
consumer.is_active = True
consumer.save()
return self.get(request, *args, **kwargs)
В force_text конструкцию urlsafe_base64_decode я также обволакивал. Всё тот же None.
Помогите, пожалуйста, уже долгое время разобраться пытаюсь где же я накосячил.
Вот если что еще темплейт сообщения:
{% autoescape off %}
Hello, your email address has been selected for registration!
To confirm, follow the link.
{{ protocol }}://{{ domain }}{% url 'activate' uidb64=uid token=token %}
In case you didn't do it, just ignore this message.
{% endautoescape %}
Ответы (2 шт):
Мой ответ: Функция urlsafe_base64_decode не должна возвращать None, ни при каких обстоятельствах.
Либо она где-то у вас в проекте перегружена, либо это ошибка самого питона(что вряд-ли), либо ошибка используемой версии джанги, либо вы сами пошли по неверному пути.
Где вы увидели None? И почему вы решили, что None вернула именно эта функция. Предоставьте пример кода, который мы можем запустить, и который вернёт None. Тогда можно будет рассуждать.
Проблема заключалась в том, что в методе save формы регистрации, которая в том числе и вызывала метод подготовки данных и отправки сообщения, я вызвал его раньше сохранения самого инстанса модели в базе. Если проверить, то до отправки сообщения consumer.pk равен None, а уже после, когда сработал метод save у него появляется численное значение. Спасибо человеку под ником Мистер Фикс, что дал понять то, что никогда возвращаться None не будет, если ты сам None туда не отправил.
Подытоживая все сказанное: нужно было просто поменять местами две операции.