Authentication is an important aspect of any application. In our application only registered members can add products or reviews. We are going to use the built in authentication tools for Django. We will take the following steps:
- Create users and groups in Admin
- Add an include for django.auth in the project level urls
- Add a registration folder to templates
- Add a login template to the registration folder
- Create loginmessage and logoutmessage views
- Add templates for the login logout messages
- Register those views in the settings.py file
- Add links for login and logout to the base.html file
- Add the @login_required decorator to our form views
- Add tests for authenticated users
Create Users and Groups in Admin
Run the server and login to the admin site.
I am going to create a new group called "members."
Add and Include for django.auth
These are the permission I gave the group:
auth | user| can add user auth | user| can change user auth | user| can view user techapp | product | can add product techapp | product | can change product techapp | product | can delete product techapp | product | can view product techapp | product type| can add product type techapp | product type | can change product type techapp | product type | can delete product type techapp | product type | can view product type techapp | review | can add review techapp | review | can change review techapp | review | can delete review techapp | review | can view review
Now add a couple of users and add them to the member's group
Add an include in the project level urls.py
We need to add another include to our project level urls.py in order to find the pre-written authorization components.
urlpatterns = [ path('admin/', admin.site.urls), path('techapp/', include('techapp.urls')), path('accounts/', include('django.contrib.auth.urls')), ]
Add a registration folder to templates
Now in VSCode right click on the templates folder and select "New Folder." Name the folder "registration." It must be spelled correctly and all in lower case.
Add login template to registration
In the registration folder we need to add our login template. It needs to be named "login.html."
{% extends 'base.html' %} {% block content%} <h2>Login</h2> <form method="POST"> {% csrf_token %} {{ form.as_p }} <button type="submit">login</button> </form> {% endblock %}
Create loginmessage and logoutmessage views
These views are like our original index view. They contain only a pointer to an html file.
def loginmessage(request): return render(request, 'techapp/loginmessage.html') def logoutmessage(request): return render(request, 'techapp/logoutmessage.html')
We also, of course, have to register them in urls.py
urlpatterns=[ path('', views.index, name='index'), path('gettypes/', views.gettypes, name='types'), path('getproducts/', views.getproducts, name='products'), path('productdetails/<int:id>', views.productdetails, name='productdetails'), path('newProduct/', views.newProduct, name='newproduct'), path('loginmessage/', views.loginmessage, name='loginmessage'), path('logoutmessage/', views.logoutmessage, name='logoutmessage'), ]
Create loginmessage and logout message templates
These templates go in the templates/techapp/ folder.
Here is the login message
{% extends 'base.html' %} {% block content %} <h2>Thank you</h2> <p>Thank you for logging in.</p> {% endblock%} {% endblock %}
Here is the logout message.
{% extends 'base.html' %} {% block content %} <h2>Goodbye/h2> <p>You are now logged out.</p> {% endblock%}
Register view in settings.py
There is one last place we need to register the loginmessage and logoutmessage. We need to add a reference to them at the very bottom of the settings.py file, right after the "STATIC_URL" statement.
LOGIN_REDIRECT_URL='loginmessage' LOGOUT_REDIRECT_URL='logoutmessage'
Add the @login_required decorator
In views.py we need to imports the login_required decorators.
from django.contrib.auth.decorators import login_required'
Now we add the "decorator" to the views that require a login.
@login_required def newProduct(request): form=ProductForm if request.method=='POST': form=ProductForm(request.POST) if form.is_valid(): post=form.save(commit=True) post.save() form=ProductForm() else: form=ProductForm() return render(request, 'techapp/newproduct.html', {'form': form})
This simple addition makes it so that if a user is not logged it, the program will throw them to the login form.
Add links in base,html
Lastly we add login and logout links to the base.html file.
<li><a href="{% url 'login' %}">Login</a></li> <li><a href="{% url 'logout' %}">Logout</a></li>
Run the server to test the new login, logout and decorator. When I click on the menu item to add a product, I am thrown to the login:
After I login I can enter form data:
When I logout I get the logout message.
Add tests for authenticated users
Finally we can add some unit tests to check if the authentication works properly. First we set up a user, a Producttype and a Product. The first tests checks to make sure the program redirects to the login form in no user is logged in. The second test actually contains three tests: We log in a user, then test to make sure the user can access the form. We make sure the status is OK and that it is using the correct template.
class New_Product_authentication_test(TestCase): def setUp(self): self.test_user=User.objects.create_user(username='testuser1', password='P@ssw0rd1') self.type=ProductType.objects.create(typename='laptop') self.prod = Product.objects.create(productname='product1', producttype=self.type, user=self.test_user, productprice=500, productentrydate='2019-04-02',producturl= 'http://www.dell.com', productdescription="a product") def test_redirect_if_not_logged_in(self): response=self.client.get(reverse('newproduct')) self.assertRedirects(response, '/accounts/login/?next=/techapp/newProduct/') def test_Logged_in_uses_correct_template(self): login=self.client.login(username='testuser1', password='P@ssw0rd1') response=self.client.get(reverse('newproduct')) self.assertEqual(str(response.context['user']), 'testuser1') self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'techapp/newproduct.html')
No comments:
Post a Comment