AbstractUser Login View
<p>I've spent a couple of days on this, read the docs, read some Two Scoops info, and I'm missing something. I'm trying to make a view to log in an AbstractUser. The AbstractUser model is in <code>my_app</code> and the view is in an app called <code>mainsite</code>, that I use to store project-wide views.</p>

<p>After the user logs in, they will have access to class-based views that they will use to add, edit, and delete database records. These users are not staff, so I am not giving them access to the admin.</p>

<p>Every time I try to log in as a user, <code>authenticate(username, password)</code> (in views.py) returns none.</p>

<p>What am I missing?</p>

<p>Here's the setup--I have a custom Person model that extends the AbstractUser model:</p>

<pre><code># my_app.models.py
class Person(AbstractUser):
    date_left = models.DateField(blank=True, null=True)
    phone_number = models.IntegerField(blank=True, null=True)

    def _full_name(self):        
        return self.get_full_name()
    full_name = property(_full_name)

    def __str__(self):
        return self.get_full_name()

    class Meta:
        verbose_name_plural = 'People'    
</code></pre>

<p>I've added Person to settings.py:</p>

<pre><code># settings.py
...
AUTH_USER_MODEL = "my_app.Person"
...
</code></pre>

<p>I have the following URLconf:</p>

<pre><code># project/urls.py
from mainsite.views import login_view
...
url(r'^login/$', login_view, name='login'),
...
</code></pre>

<p>This view logs in the user:</p>

<pre><code># mainsite.views.py
def login_view(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user is not None:
            login(request, user)
            return render(request, 'logged_in.html')
        else:
            return render(request, 'login.html', 
                {'message': 'Bad username or password'}
            )
    else:
        return render(request, 'login.html')
</code></pre>

<p>And finally, here's the template with the login fields:</p>

<pre><code>#templates/login.html
&lt;form action="{% url 'login' %}" method="post"&gt;
    {% csrf_token %}
    &lt;div class="row column"&gt;&lt;h1&gt;Login&lt;/h1&gt;&lt;/div&gt;
    {% if message %}
        &lt;div class="row"&gt;
            &lt;div class="small-12 medium-6 columns"&gt;
                &lt;div class="alert callout"&gt;
                    &lt;p&gt;{{ message }}&lt;/p&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    {% endif %}
    &lt;div class="row"&gt;
        &lt;div class="small-12 medium-6 columns"&gt;
            &lt;label&gt;Username
                &lt;input type="text" id="username" name="username"&gt;
            &lt;/label&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="row"&gt;
        &lt;div class="small-12 medium-6 columns"&gt;
            &lt;label&gt;Password
                &lt;input type="password" id="password" name="password"&gt;
            &lt;/label&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="row"&gt;
        &lt;div class="small-12 medium-6 columns"&gt;
            &lt;input type="submit" value="Log in" class="button"&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;
</code></pre>

<p>I found an answer (with help from reddit) in the docs.</p>

<p><a href="https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#custom-users-and-the-built-in-auth-forms" rel="nofollow">When you use AbstractUser, you need to create your own UserCreationForm and UserChangeForm.</a> If you use AbstractBaseUser, then you will need to create additional forms.</p>

<p>I had not created these forms, and I created my users in the admin using forms automatically generated by Django. These forms did not set the password correctly. The automatically generated form probably used <code>user.password = 'some_password'</code>. The correct way to do it is <code>user.set_password('some_password') </code>.</p>

python django