django如何验证用户,直到验证电子邮件

时间:2017-11-07 03:51:19

标签: django

如何验证用户,直到他验证电子邮件? 在我的注册过程中,我创建了用户,这意味着即使没有验证电子邮件他也可以登录。是否有内置方法在用户上设置未经验证的状态?

1 个答案:

答案 0 :(得分:2)

models.py

email_active = models.BooleanField(default=False,
                                       verbose_name=u'Email active ')

views.py

username = request.POST.get("username")
password = request.POST.get("password")
user = authenticate(username=username, password=password)
if user is not None:
    if user.email_active:
        login(self.request, user)
        return HttpResponse("login success")
    else:
        return HttpResponse("user email is not active")
else:
    return HttpResponse("username or password error")

您可以通过发送带有verify_code的电子邮件来激活电子邮件,用户可以使用verify_code来激活他们的电子邮件。 演示:

models.py:

class EmailVerify(models.Model):
    owner = models.ForeignKey(User,
                              on_delete=models.CASCADE,
                              verbose_name='owner')
    verify_code = models.CharField(max_length=254,
                                   null=True,
                                   verbose_name='verify_code ')

    def update(self):
        self.verify_code = self.generate_key()
        self.save()
        return self.verify_code

    def get_active_email_url(self, request):
        from django.urls import reverse
        url = '{}?active_code={}'.format(request.build_absolute_uri(reverse('user_login', args=())), self.verify_code)
        return url

    @staticmethod
    def generate_key():
        return binascii.hexlify(os.urandom(20)).decode()

    class Meta:
        verbose_name = 'EmailVerify'

utils.py:

def send_active_email(request, user):
    current_site = get_current_site(request)
    site_name = current_site.name

    if EmailVerify.objects.filter(owner=user, category=0).exists():
        verify = EmailVerify.objects.filter(owner=user).first()
    else:
        verify = EmailVerify.objects.create(owner=user)
    verify.update()
    title = u"{} active email".format(site_name)
    message = "".join([
        u"click this link can active your email:\n\n",
        "{}\n\n".format(verify.get_active_email_url(request=request)),
    ])

    try:
        send_mail(title, message, settings.DEFAULT_FROM_EMAIL, [user.email])
        message = "success"
    except ConnectionRefusedError as e:
        message = e.strerror
    except Exception as e:
        message = str(e)
    return message

views.py

class LoginView(BaseContextMixin, FormView):
    template_name = 'user/login.html'
    form_class = LoginForm
    success_url = reverse_lazy('index')

    def get_context_data(self, **kwargs):
        if 'form' not in kwargs:
            kwargs['form'] = self.get_form()

        if 'active_email' in self.request.GET:
            active_email = self.request.GET.get('active_email')
            try:
                user = User.objects.get(email=active_email, email_active=False)
                kwargs['message'] = send_active_email(self.request, user)
            except (ObjectDoesNotExist, MultipleObjectsReturned):
                kwargs['message'] = 'email not exist or actived'

        if 'active_code' in self.request.GET:
            active_code = self.request.GET.get('active_code')
            try:
                email_verify = EmailVerify.objects.get(verify_code=active_code)
                email_verify.owner.email_active = True
                email_verify.owner.save()
                email_verify.delete()
                kwargs['message'] = 'email {} actived'.format(email_verify.owner.email)
            except ObjectDoesNotExist:
                kwargs['message'] = 'unless link'
            except MultipleObjectsReturned:
                EmailVerify.objects.filter(verify_code=active_code).delete()
                kwargs['message'] = 'error!'
        return super(LoginView, self).get_context_data(**kwargs)

    def get_form(self, form_class=None):
        if form_class is None:
            form_class = self.get_form_class()
        return form_class(request=self.request, **self.get_form_kwargs())

forms.py:

class LoginForm(forms.Form):
    active_email = None
    username = forms.CharField(label='username')
    password = forms.CharField(widget=forms.PasswordInput, label='password')

    def __init__(self, request, *args, **kwargs):
        super(LoginForm, self).__init__(*args, **kwargs)
        self.request = request
        self.fields['username'].widget.attrs.update({'class': 'form-control',
                                                     "placeholder": self.fields['username'].label})
        self.fields['password'].widget.attrs.update({'class': 'form-control',
                                                     "placeholder": self.fields['password'].label})

    def clean(self):
        username = self.cleaned_data["username"]
        password = self.cleaned_data["password"]
        user = authenticate(username=username, password=password)
        if user is not None:
            if user.email_active:
                login(self.request, user)
            else:
                self.active_email = user.email
                self.add_error("username", "not active")
        else:
            self.add_error("username", "username or password error")

的login.html:

{% extends "user/user_base.html" %}

{% block content %}
    <div class="login-box">
        <div class="login-logo">
            <a href="{% url 'index' %}">{{ website_title|default_if_none:'' }}</a>
        </div>

        <div class="login-box-body">
            <form method="post" action="{% url 'user_login' %}" class="form">
                {% csrf_token %}
                {% for field in form %}
                    <div class="form-group no-margin {% if field.errors %} has-error {% endif %}">

                        <label class="control-label" for="{{ field.id_for_label }}">
                            <b>{{ field.label }}</b>
                            {% if message %}
                                {% ifequal field.name 'username' %}{{ message }}{% endifequal %}
                            {% endif %}
                            {% if field.errors %}
                                {{ field.errors.as_text }}
                                {% ifequal field.errors.as_text '* not active' %}
                                    <a href="{% url 'user_login' %}?active_email={{ form.active_email }}">
                                        send active emial
                                    </a>
                                {% endifequal %}
                            {% endif %}
                        </label>
                        {{ field }}
                    </div>
                {% endfor %}

                <div class="row">
                    <div class="col-md-6">
                        <button id="btn_login" type="submit" style="width: 100%"
                                class="btn btn-raised btn-primary">Login
                        </button>
                    </div>

                </div>
            </form>
        </div>
    </div>
{% endblock %}