How to make a login view for django custom user?

青春壹個敷衍的年華 提交于 2020-01-24 00:50:09

问题


I have made a custom user model using the AbstractUser , removed the username and replaced it with email and extended the model, tried creating superuser and it worked and also created some users by a signup form , logged in the admin interface and it worked however when tried to create a login form for the users it fails

I tried this but it didn't work

def LoginView(request):
    if request.method == 'POST':
        form = AuthenticationForm(data=request.POST)
        if form.is_valid():
            user = form.get_user()
            login(request,user)
            return redirect('accounts:login')
    else:
        form = AuthenticationForm()
    return render(request,'accounts/login.html', {'form':form})

then i tried this

class LoginView(FormView):
   form_class = AuthenticationForm
   template_name = 'login.html'

   def form_valid(self, form):
       email = form.cleaned_data['email']
       password = form.cleaned_data['password']
       user = authenticate(email=email, password=password)

    # Check here if the user is an admin
       if user is not None and user.is_active:
           login(self.request, user)
           return HttpResponseRedirect(self.success_url)
       else:
           return self.form_invalid(form)

Obviously i expect the user to be logged in i think the code in this post is badly formatted. mainly it's my fault as i'm new to this platform


回答1:


I've developed almost the same setup that you're describing (I didn't remove the username field, just stopped using it). If you haven't already seen it, Django's documentation at https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#substituting-a-custom-user-model is quite helpful.

There are a couple of important things that need to be set up correctly for this to work.

  • The USERNAME_FIELD on your model should be set to the name of your email field.
  • The AUTH_USER_MODEL needs to point to your custom user model.
class MyUser(AbstractUser):
    USERNAME_FIELD = 'email'
AUTH_USER_MODEL = 'customauth.MyUser'

Since you've removed the username field altogether you might need to subclass django.contrib.auth.forms.AuthenticationForm and django.contrib.auth.views.LoginView to avoid breaking things, but Django should handle a different authentication field quite well.

If you do wind up needing to subclass the view, https://ccbv.co.uk/projects/Django/2.2/django.contrib.auth.views/LoginView/ is a great place to look over all the methods to see what's going on.

Edit - On Subclassing and it's necessity

What I was saying about possibly needing to subclass certain things was influenced by https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#writing-a-manager-for-a-custom-user-model. I wasn't sure if there were other parts of the authentication system that would need you to customize them because you removed the username field.

I've read through some of the source code for Django's authentication system. Here's the path that's being followed.

  1. When the POST request is made to Django's authentication view the authentication form is validated. https://github.com/django/django/blob/2.2.2/django/contrib/auth/forms.py#L191

  2. The authenticate function is called. This iterates through the backends set up and tries to authenticate on each of them. https://github.com/django/django/blob/2.2.2/django/contrib/auth/__init__.py#L62

  3. Django's built-in authentication backend gets the user if it exists using the natural key. https://github.com/django/django/blob/2.2.2/django/contrib/auth/backends.py#L16

  4. We can see in the base manager that the natural key used is the field named by USERNAME_FIELD. https://github.com/django/django/blob/2.2.2/django/contrib/auth/base_user.py#L43

  5. If the form is valid, meaning that the user is authenticated properly, the user is then logged in. https://github.com/django/django/blob/2.2.2/django/contrib/auth/views.py#L88

My reaction is that it looks like Django should work out of the box for your use case. You shouldn't need to write a backend. Here's the extent of the code my gut says you should have to write.

from django.contrib.auth import views as auth_views
from django.shortcuts import resolve_url

class LoginView(auth_views.LoginView):
    template_name = 'accounts/login.html'

    def get_success_url(self):
        return resolve_url('accounts:login')



回答2:


If you could post the error messages you're getting for the first one that would be helpful. It could be a problem with the form, the view, or the login function...



来源:https://stackoverflow.com/questions/56761409/how-to-make-a-login-view-for-django-custom-user

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!