I have several related questions and post under one topic for clarity's sake.

# Django/django_bookmarks/urls.py    
urlpatterns = patterns('',
    (r'^$', main_page),
    (r'^user/(\w+)/$', user_page),
    (r'^login/$', 'django.contrib.auth.views.login'),
)    

# login.html
<html>
  <head>
    <title>Django Bookmarks - User Login</title>
  </head>

  <body>
    <h1>User Login</h1>
    {% if form.errors %}
    <p>Your username and password didn't match.
      Please try again.</p>
    {% endif %}
    <form method="post" action=".">
      {% csrf_token %}
      <p><label for="id_username">Username:</label>
    {{ form.username }}</p>
      <p><label for="id_password">Password:</label>
    {{ form.password }}</p>
      <input type="hidden" name="next" value="/" />
      <input type="submit" value="login" />
    </form>
  </body>
</html>

Based on the book, the login.html uses form.has_errors instead of form.errors. However, the form.has_errors doesn't print any warning message even if I enter a wrong user/password. After some investigation, I change it to form.errors and it works for me.

Question 1> Which one should be used form.errors or form.has_errors?

Question 2> If form.has_errors doesn't work, why django doesn't complain in the first place. The book was written for Django 1.0 and I am using Django 1.3. Is that the reason?

Question 3> How to check which attributes the form has? I have tried the following and it doesn't give the information I needed.

python manage.py shell
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24) 
[GCC 4.
Edit
Report