web-dev-qa-db-fra.com

NoReverseMatch avec l'argument de mot clé uidb64 avec Django 2.0

Je ne comprends pas pourquoi mon code ne fonctionne pas. Avant cela fonctionnait, mais maintenant, lorsque j'exécute le serveur et que je teste, le code ne fonctionne pas.

Lorsque l'utilisateur s'inscrit, je lui envoie un e-mail d'activation, comme ceci:

def send_activation_email(serializer, request, user):
    current_site = get_current_site(request)
    message = render_to_string('acc_active_email.html', {
        'user': user,
        'domain': current_site.domain,
        'uid': urlsafe_base64_encode(force_bytes(user.pk)),
        'token': account_activation_token.make_token(user),
    })
    mail_subject = 'Activate your blog account.'
    to_email = serializer.data['email']

    email = EmailMessage(mail_subject, message, to=[to_email])
    email.send()

acc_active_email.html

{% autoescape off %}
Hi {{ user.username }},
Please click on the link to confirm your registration,

http://{{ domain }}{% url 'activate' uidb64=uid token=token %}
{% endautoescape %}

et mon fichier URL

.
.
    url(r'^activate/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
        views.activate_account, name='activate'),
.
.

mais j'ai cette erreur:

Exception Type:     NoReverseMatch
Exception Value:    

Reverse for 'activate' with keyword arguments '{'uidb64': b'NDM', 'token': '4qz-8f770502bd8b02786da9'}' not found. 1 pattern(s) tried: ['activate/(?P<uidb64>[0-9A-Za-z_\\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$']

met en évidence cette ligne http://{{ domain }}{% url 'activate' uidb64=uid token=token %}

17
r2546971

Dans Django 2.0 et 2.1, vous devez appeler decode() après le codage en base64 de l'uid, pour le convertir en chaîne:

message = render_to_string('acc_active_email.html', {
    'user': user,
    'domain': current_site.domain,
    'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
    'token': account_activation_token.make_token(user),
})

Voir la note dans les Notes de version de Django 2. pour plus d'informations.

Dans Django 2.2+, urlsafe_base64_encoderenvoie une chaîne , il n'est donc pas nécessaire de décoder.

message = render_to_string('acc_active_email.html', {
    'user': user,
    'domain': current_site.domain,
    'uid': urlsafe_base64_encode(force_bytes(user.pk)),
    'token': account_activation_token.make_token(user),
})

Il devrait être possible d'écrire du code compatible avec Django <1.11, 2.0-2.1 et 2.2+, en utilisant force_text. Notez que ce qui suit n'est pas testé.

from Django.utils.encoding import force_text

message = render_to_string('acc_active_email.html', {
    'user': user,
    'domain': current_site.domain,
    'uid': force_text(urlsafe_base64_encode(force_bytes(user.pk))),
    'token': account_activation_token.make_token(user),
})

Vous pouvez supprimer le force_text et utilisez le deuxième extrait de code une fois que vous avez supprimé la prise en charge de Django <2.2.

49
Alasdair