Classed-Base-Views (CBV) Register, Login and Logout
Tags: django
Published: 2023-09-03 13:28:58

Let's see how simple the registration, login and logout can be with Classed-Base-Views. For styling I use mostly bootstrap and one custom style sheet. 

I assume you know how to create a Django project and an application. Otherwise check out the official [Django documentation](https://docs.djangoproject.com/en/4.2/intro/tutorial01/#creating-a-project).


I have created a Django project with the apps named: "accounts" and "ui".
In the application "accounts" I have all code for the user, registration, login and logout. 
The "ui" application contains the `base_layout.html` template with the navigation bar and all static files like styles.css, just in case I need additional styling. 

```python
# project tree

.
├── accounts
│   ├── admin.py
│   ├── apps.py
│   ├── forms.py
│   ├── __init__.py
│   ├── migrations
│   ├── models.py
│   ├── templates
│   │   ├── login_page.html
│   │   └── register.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── db.sqlite3
├── project
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── manage.py
└── ui
    ├── admin.py
    ├── apps.py
    ├── __init__.py
    ├── media
    │   └── images
    ├── migrations
    ├── models.py
    ├── static
    │   └── css
    │       └── styles.css
    ├── templates
    │   ├── base_layout.html
    ├── tests.py
    ├── urls.py
    └── views.py
```

Add the applications in the `project/settings.py` file:

```python
 # project/settings.py

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    # custom applications
    "accounts",
    "ui",
]
```

In the same file, we will define the location for the static files. In my case the static folder/directory is located in the application "ui" (check out the tree in the beginning). So, we have to set the location of the static directory like:

```python 
# project/settings.py

STATICFILES_DIRS = [os.path.join(BASE_DIR, "ui/static")]
STATIC_URL = "static/"
```

<hr>

For Login and Logout, I used just the urls.py file in my app "accounts" to create the views:

```python
# app/urls.py

from django.urls import path
from django.contrib.auth.views import LoginView, LogoutView

from .views import RegisterView

app_name = "accounts"

urlpatterns = [
    path("", LoginView.as_view(template_name="login_page.html"), name="login"),
    path("logout/", LogoutView.as_view(), name="logout"),
    # add custom RegisterView to path
    path("register/", RegisterView.as_view(), name="register"),

]
```

_from django.contrib.auth.views import LoginView, LogoutView_: we import the LoginView and LogoutView from Django. If you want to see what this view is doing check out the [GitHub of Django](https://github.com/django/django/tree/main/django). (You can follow the path provided in the import statement: `django/contrib/auth/views`. You have to click on the contrib folder, after auth folder, then views and you will find the code of the views.)

_template_name="login_page.html"_: This template_name points to the file in app `accounts/template/login_page.html`

_name="login"_: this name is important, we name the view, so we can reference it later in our project.  


Do not forget to include the urls of the application "accounts" in your `project/urls.py` file:

```python
# project/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('accounts.urls', namespace='accounts')),
]

```

That is not all. We have to set some variables into the `project/settings.py` file:

```python 
# project/settings.py

LOGIN_URL = "accounts:login"
LOGIN_REDIRECT_URL = "<app_name>:<view_name>"
LOGOUT_REDIRECT_URL = LOGIN_URL
```

_LOGIN_URL_: points to the application and view name to call.
_LOGIN_REDIRECT_URL_: this variable tells which view to call after the login is successful. 
_LOGOUT_REDIRECT_URL_: here you tell where the user will be redirected to after successful logout.

With this lines of code the Login and Logout is done. Now the RegisterView is missing.

```python 
# accounts/views.py

from django.views.generic.edit import CreateView

from .forms import RegisterForm

class RegisterView(CreateView):
    form_class = RegisterForm
    template_name = "register.html"
    success_url = reverse_lazy("<app_name>:<view_name>")

    def form_valid(self, form):
        user = form.save()

        if user:
            login(self.request, user)

        return super().form_valid(form)
```
I used a CreateView to register a new user in my database. 
_form_class_: here you tell which form the view is displaying and using for the validation.
_success_url_: if form is validated this url will be called. 

In form_valid I save the form and store it in a variable named user. The user will be logged in and the success_url will be called. 


```python
# accounts/forms.py

from django import forms
from django.contrib.auth.forms import UserCreationForm

from .models import User


class RegisterForm(UserCreationForm):
    """Form to register User"""

    class Meta:
        model = User
        fields = ["username", "password1", "password2"]
```

This form will display a username and twice the password. The form is inherited from UserCreationForm. 

And that's it.