├── .gitignore ├── Dockerfile ├── README.md ├── compose.yaml ├── manage.py ├── profiles ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py ├── tokens.py ├── urls.py ├── utils.py └── views.py ├── readme_images ├── dashboard.PNG ├── home.PNG ├── signin.PNG └── signup.PNG ├── requirements.txt ├── static ├── css │ ├── addons │ │ ├── datatables.css │ │ └── datatables.min.css │ ├── bootstrap.css │ ├── bootstrap.min.css │ ├── mdb.css │ ├── mdb.min.css │ ├── style.css │ └── style.min.css ├── font │ └── roboto │ │ ├── Roboto-Bold.eot │ │ ├── Roboto-Bold.ttf │ │ ├── Roboto-Bold.woff │ │ ├── Roboto-Bold.woff2 │ │ ├── Roboto-Light.eot │ │ ├── Roboto-Light.ttf │ │ ├── Roboto-Light.woff │ │ ├── Roboto-Light.woff2 │ │ ├── Roboto-Medium.eot │ │ ├── Roboto-Medium.ttf │ │ ├── Roboto-Medium.woff │ │ ├── Roboto-Medium.woff2 │ │ ├── Roboto-Regular.eot │ │ ├── Roboto-Regular.ttf │ │ ├── Roboto-Regular.woff │ │ ├── Roboto-Regular.woff2 │ │ ├── Roboto-Thin.eot │ │ ├── Roboto-Thin.ttf │ │ ├── Roboto-Thin.woff │ │ └── Roboto-Thin.woff2 ├── img │ ├── lightbox │ │ ├── default-skin.png │ │ ├── default-skin.svg │ │ └── preloader.gif │ ├── overlays │ │ ├── 01.png │ │ ├── 02.png │ │ ├── 03.png │ │ ├── 04.png │ │ ├── 05.png │ │ ├── 06.png │ │ ├── 07.png │ │ ├── 08.png │ │ └── 09.png │ └── svg │ │ ├── arrow_left.svg │ │ └── arrow_right.svg ├── index.html └── js │ ├── addons │ ├── datatables.js │ └── datatables.min.js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── jquery-3.3.1.min.js │ ├── mdb.js │ ├── mdb.min.js │ └── popper.min.js ├── templates ├── app │ ├── dashboard.html │ ├── home.html │ ├── profile_edit.html │ └── signup.html ├── base.html ├── navbar.html └── registration │ ├── account_activation_email.html │ ├── account_activation_invalid.html │ ├── account_activation_sent.html │ ├── login.html │ └── logout.html ├── users ├── __init__.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py ├── urls.py └── views.py └── website ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # migrations folder 107 | profiles/migrations 108 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1.4 2 | FROM python:3.11 3 | EXPOSE 8000 4 | 5 | ENV PROJECT_KEY=$PROJECT_KEY 6 | 7 | # set working directory 8 | WORKDIR /Django-Signup 9 | COPY requirements.txt /Django-Signup 10 | 11 | # install app dependencies 12 | RUN pip3 install -r requirements.txt --no-cache-dir 13 | COPY . /Django-Signup 14 | ENTRYPOINT ["python3"] 15 | 16 | RUN python manage.py makemigrations 17 | RUN python manage.py migrate 18 | CMD ["manage.py", "runserver", "0.0.0.0:8000"] 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Django-Signup 2 | Creating a simple sign up view and then moving onto more advanced sign up view with profile model and confirmation mail 3 | 4 | **I have also added a location field in custom profile model and stored the 5 | actual location (city, country code) of user using API, a little javascript and 6 | python without letting user know about it. For a tutorial on using that API checkout my [repo](https://github.com/Alexmhack/django_weather_app)** 7 | 8 | In this tutorial we will 9 | 10 | 1. Create basic sign up view 11 | 2. Create sign up form with extra fields 12 | 3. Create profile model for users 13 | 4. Create sign up view with confirmation email 14 | 15 | # Finished View 16 | After completing the project and adding some styling from [mdbootstrap](http://mdbootstrap.com/) my project looks like 17 | 18 | Home Page is simply showing a navbar with working links 19 | 20 |  21 | 22 | Login page looks like 23 | 24 |  25 | 26 | Sign Up page 27 | 28 |  29 | 30 | And finally dashboard page with the user name displayed... 31 | 32 |  33 | 34 | **You can reuse the code from my repo and include it in your django project. Put a star if you liked my work.** 35 | 36 | # Django Project Setup 37 | 38 | ``` 39 | pip install -r requirements.txt 40 | ``` 41 | 42 | 1. ```django-admin startproject website .``` 43 | 2. ```python manage.py migrate``` 44 | 3. ```python manage.py createsuperuser``` 45 | 4. ```python manage.py runserver``` 46 | 5. In project ```settings.py``` file import [decouple](https://pypi.org/project/python-decouple/) 47 | 48 | ``` 49 | from decouple import config 50 | SECRET_KEY = config("PROJECT_KEY") 51 | ``` 52 | 53 | And create ```.env``` file like so 54 | 55 | ``` 56 | PROJECT_KEY=93%@nka8)+fv-*ai-st1d*h)w2j2-y^)(jfiv9bogcy0u241u7 57 | ``` 58 | 59 | We will start with the basic sign up features that django provides by default 60 | 61 | # Basic Sign Up 62 | Simplest way to implement a **Sign Up** view is using ```UserCreationForm```. 63 | This form is for those django apps which use the default user model that only 64 | contains a **username** and **password** for user sign ups. 65 | 66 | To implement that view we need 67 | 68 | **urls.py** 69 | ``` 70 | ... 71 | from .views import signup_view 72 | 73 | urlpatterns = [ 74 | path('admin/', admin.site.urls), 75 | path('signup/', signup_view, name='sign-up'), 76 | ] 77 | ``` 78 | 79 | In ```urls.py``` we simply import the ```signup_view``` that we haven't yet added 80 | to ```views.py``` and create a url for that view. 81 | 82 | Now create ```views.py``` file in the **website** folder and put this code inside 83 | it. 84 | 85 | ``` 86 | from django.shortcuts import render, redirect 87 | from django.contrib.auth import authenticate, login 88 | from django.contrib.auth.forms import UserCreationForm 89 | 90 | def signup(request): 91 | if request.method == "POST": 92 | form = UserCreationForm(request.POST) 93 | if form.is_valid(): 94 | form.save() 95 | username = form.cleaned_data.get('username') 96 | password = form.cleaned_data.get('password1') 97 | user = authenticate(username=username, password=password) 98 | login(request, user) 99 | return redirect('home') 100 | else: 101 | form = UserCreationForm() 102 | 103 | return render(request, 'signup.html', {'form': form}) 104 | ``` 105 | 106 | This is most basic signup view that django has. All of the new user creation 107 | process is done using django. We use the default ```UserCreationForm``` form to 108 | display the signup form. We authenticate the new user using the username and 109 | password that we get from the post request from the **form**. We then login the 110 | user and redirect it to ```home``` view. If the request method is not ```POST``` 111 | we simply show the empty form in ```templates/signup.html``` file. 112 | 113 | Create a **templates** folder in root path (where ```manage.py``` file lies). In 114 | that folder create ```signup.html``` file. 115 | 116 | **signup.html** 117 | ``` 118 | {% extends 'base.html' %} 119 | 120 | {% block content %} 121 |
Bio: {{ user.profile.bio }}
391 |Location: {{ user.profile.location }}
392 |Joined: {{ user.profile.timestamp }}
393 | ``` 394 | 395 | **For customizing the forms you can use [django-widget-tweaks](https://pypi.org/project/django-widget-tweaks/)** 396 | 397 | # Signup With Confirmation Email 398 | Django provides built-in system for sending emails. But first of test purposes 399 | we will be using **Console Backend** for emails. 400 | 401 | Add this settings in ```settings.py``` file 402 | 403 | ``` 404 | EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' 405 | ``` 406 | 407 | Now for checking if a user is authenticated we will create a field in the profile 408 | model to determine if the user is confirmed or not. 409 | 410 | **profiles/models.py** 411 | ``` 412 | class Profile(models.Model): 413 | ... 414 | email_confirmed = models.BooleanField(default=False) 415 | ``` 416 | 417 | And for creating a one time link using django we will create a new file ```tokens.py``` 418 | 419 | ``` 420 | from django.contrib.auth.tokens import PasswordResetTokenGenerator 421 | from django.utils import six 422 | 423 | class AccountActivationTokenGenerator(PasswordResetTokenGenerator): 424 | def _make_hash_value(self, user, timestamp): 425 | return ( 426 | six.text_type(user.pk) + six.text_type(timestamp) + 427 | six.text_type(user.profile.email_confirmed) 428 | ) 429 | 430 | 431 | account_activation_token = AccountActivationTokenGenerator() 432 | ``` 433 | 434 | We use the ```pk``` from the user ```timestamp``` and the ```email_confirmed``` field 435 | to create a token. We basically extended the PasswordResetTokenGenerator to create a 436 | unique token generator to confirm email addresses. This make use of your project’s 437 | SECRET_KEY, so it is a pretty safe and reliable method. 438 | 439 | Now we need to define views for account activation as well as account activation sent 440 | view 441 | 442 | ``` 443 | def account_activation_sent_view(request): 444 | return render(request, 'registration/account_activation_sent.html') 445 | 446 | 447 | def account_activate(request, uidb64, token): 448 | try: 449 | uid = urlsafe_base64_decode(uidb64).decode() 450 | print(uid) 451 | user = User.objects.get(pk=uid) 452 | except (TypeError, ValueError, OverflowError, User.DoesNotExist) as e: 453 | print(e) 454 | user = None 455 | 456 | if user is not None and account_activation_token.check_token(user, token): 457 | user.is_active = True 458 | user.profile.email_confirmed = True 459 | user.save() 460 | login(request, user) 461 | return redirect('users:dashboard') 462 | else: 463 | return render(request, 'registration/account_activation_invalid.html') 464 | ``` 465 | 466 | ```account_activation_sent_view``` is justfor redirecting users if their account activation url is wrong. The template **registration/account_activation_sent.html** 467 | will be 468 | 469 | ``` 470 | {% extends "base.html" %} 471 | 472 | {% block title %} 473 | {{ block.super }} - Check Your Email Account 474 | {% endblock %} 475 | 476 | {% block content %} 477 | 478 |MDB Team
30 |p[c]&&(e.offsets.popper[f]+=s[f]+g-p[c]);var u=s[f]+s[a]/2-g/2,b=t(e.instance.popper,'margin'+l).replace('px',''),y=u-h(e.offsets.popper)[f]-b;return y=X(V(p[a]-g,y),0),e.arrowElement=i,e.offsets.arrow={},e.offsets.arrow[f]=Math.round(y),e.offsets.arrow[m]='',e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=w(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement),i=e.placement.split('-')[0],n=L(i),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case fe.FLIP:p=[i,n];break;case fe.CLOCKWISE:p=K(i);break;case fe.COUNTERCLOCKWISE:p=K(i,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(i!==s||p.length===d+1)return e;i=e.placement.split('-')[0],n=L(i);var a=e.offsets.popper,l=e.offsets.reference,f=_,m='left'===i&&f(a.right)>f(l.left)||'right'===i&&f(a.left) {{ message }} Bio: {{ user.profile.bio }} Joined: {{ user.profile.timestamp }}
13 | {{ field.label_tag }}
14 | {{ field|attr:"rows:20"|attr:"cols:20" }}
15 |
18 | {% for error in field.errors %}
19 | {{ error }} {{ message }} MDB Team {{ message }}Welcome {{ request.user }}
26 | Material Design for Bootstrap
34 |
35 | Thank you for using our product. We're glad you're with us.
36 |
37 | The account activation link you are using is either expired or is no longer valid.
10 |
11 | {% endblock %}
12 |
--------------------------------------------------------------------------------
/templates/registration/account_activation_sent.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}
4 | {{ block.super }} - Check Your Email Account
5 | {% endblock %}
6 |
7 | {% block content %}
8 |
9 | Check your email account for verifying your django account.
10 |
11 | {% endblock %}
12 |
--------------------------------------------------------------------------------
/templates/registration/login.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %}
4 | Sign in
5 | {% endblock %}
6 |
7 | {% block content %}
8 |
9 | {% if messages %}
10 |
11 | {% for message in messages %}
12 |
13 |
14 | You are successfully logged out. You can login again.
10 |
11 | {% endblock %}
12 |
--------------------------------------------------------------------------------
/users/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alexmhack/Django-Signup/28e83a9740ea199295a876a300ea5e316f0ec6af/users/__init__.py
--------------------------------------------------------------------------------
/users/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/users/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class UsersConfig(AppConfig):
5 | name = 'users'
6 |
--------------------------------------------------------------------------------
/users/forms.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 | from django.contrib.auth.forms import UserCreationForm
3 | from django.contrib.auth.models import User
4 |
5 | class SignUpForm(UserCreationForm):
6 | email = forms.EmailField(
7 | label='',
8 | max_length=254,
9 | widget=forms.EmailInput(
10 | attrs={
11 | "placeholder": "Email",
12 | "class": "form-control"
13 | }
14 | )
15 | )
16 |
17 | username = forms.CharField(
18 | label='',
19 | max_length=30,
20 | min_length=5,
21 | required=True,
22 | widget=forms.TextInput(
23 | attrs={
24 | "placeholder": "Username",
25 | "class": "form-control"
26 | }
27 | )
28 | )
29 |
30 | password1 = forms.CharField(
31 | label='',
32 | max_length=30,
33 | min_length=8,
34 | required=True,
35 | widget=forms.PasswordInput(
36 | attrs={
37 | "placeholder": "Password",
38 | "class": "form-control"
39 | }
40 | )
41 | )
42 |
43 | password2 = forms.CharField(
44 | label='',
45 | max_length=30,
46 | min_length=8,
47 | required=True,
48 | widget=forms.PasswordInput(
49 | attrs={
50 | "placeholder": "Confirm Password",
51 | "class": "form-control"
52 | }
53 | )
54 | )
55 |
56 | class Meta:
57 | model = User
58 | fields = ('username', 'email', 'password1', 'password2')
59 |
--------------------------------------------------------------------------------
/users/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alexmhack/Django-Signup/28e83a9740ea199295a876a300ea5e316f0ec6af/users/migrations/__init__.py
--------------------------------------------------------------------------------
/users/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/users/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/users/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 |
3 | from .views import home_view, signup_view, dashboard_view
4 |
5 | app_name = "users"
6 |
7 | urlpatterns = [
8 | path('', home_view, name='home'),
9 | path('signup/', signup_view, name='sign-up'),
10 | path('dashboard/', dashboard_view, name='dashboard'),
11 | ]
12 |
--------------------------------------------------------------------------------
/users/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render, redirect
2 | from django.contrib.auth import authenticate, login
3 | from django.contrib.auth.forms import UserCreationForm
4 | from django.contrib import messages
5 | from django.contrib.auth.decorators import login_required
6 |
7 | from .forms import SignUpForm
8 |
9 | def signup_view(request):
10 | if request.user.is_authenticated:
11 | return redirect('users:dashboard')
12 | if request.method == "POST":
13 | form = SignUpForm(request.POST)
14 | if form.is_valid():
15 | form.save()
16 | username = form.cleaned_data.get('username')
17 | password = form.cleaned_data.get('password1')
18 | user = authenticate(username=username, password=password)
19 | login(request, user)
20 | return redirect('users:dashboard')
21 | else:
22 | messages.error(request, 'Correct the errors below')
23 | else:
24 | form = SignUpForm()
25 |
26 | return render(request, 'app/signup.html', {'form': form})
27 |
28 |
29 | @login_required
30 | def dashboard_view(request):
31 | return render(request, 'app/dashboard.html')
32 |
33 |
34 | def home_view(request):
35 | return render(request, 'app/home.html')
36 |
--------------------------------------------------------------------------------
/website/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Alexmhack/Django-Signup/28e83a9740ea199295a876a300ea5e316f0ec6af/website/__init__.py
--------------------------------------------------------------------------------
/website/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for website project.
3 |
4 | Generated by 'django-admin startproject' using Django 2.0.7.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/2.0/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/2.0/ref/settings/
11 | """
12 |
13 | import os
14 |
15 | from decouple import config
16 |
17 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
18 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
19 |
20 |
21 | # Quick-start development settings - unsuitable for production
22 | # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
23 |
24 | # SECURITY WARNING: keep the secret key used in production secret!
25 | SECRET_KEY = os.environ.get("PROJECT_KEY", False) or config("PROJECT_KEY")
26 |
27 | # SECURITY WARNING: don't run with debug turned on in production!
28 | DEBUG = True
29 |
30 | ALLOWED_HOSTS = []
31 |
32 |
33 | # Application definition
34 |
35 | INSTALLED_APPS = [
36 | 'widget_tweaks',
37 | 'django.contrib.admin',
38 | 'django.contrib.auth',
39 | 'django.contrib.contenttypes',
40 | 'django.contrib.sessions',
41 | 'django.contrib.messages',
42 | 'django.contrib.staticfiles',
43 | 'users',
44 | 'profiles',
45 | ]
46 |
47 | MIDDLEWARE = [
48 | 'django.middleware.security.SecurityMiddleware',
49 | 'django.contrib.sessions.middleware.SessionMiddleware',
50 | 'django.middleware.common.CommonMiddleware',
51 | 'django.middleware.csrf.CsrfViewMiddleware',
52 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
53 | 'django.contrib.messages.middleware.MessageMiddleware',
54 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
55 | ]
56 |
57 | ROOT_URLCONF = 'website.urls'
58 |
59 | TEMPLATES = [
60 | {
61 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
62 | 'DIRS': [os.path.join(BASE_DIR, 'templates')],
63 | 'APP_DIRS': True,
64 | 'OPTIONS': {
65 | 'context_processors': [
66 | 'django.template.context_processors.debug',
67 | 'django.template.context_processors.request',
68 | 'django.contrib.auth.context_processors.auth',
69 | 'django.contrib.messages.context_processors.messages',
70 | ],
71 | },
72 | },
73 | ]
74 |
75 | WSGI_APPLICATION = 'website.wsgi.application'
76 |
77 | DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
78 |
79 |
80 | # Database
81 | # https://docs.djangoproject.com/en/2.0/ref/settings/#databases
82 |
83 | DATABASES = {
84 | 'default': {
85 | 'ENGINE': 'django.db.backends.sqlite3',
86 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
87 | }
88 | }
89 |
90 |
91 | # Password validation
92 | # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
93 |
94 | AUTH_PASSWORD_VALIDATORS = [
95 | {
96 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
97 | },
98 | {
99 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
100 | },
101 | {
102 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
103 | },
104 | {
105 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
106 | },
107 | ]
108 |
109 |
110 | # Internationalization
111 | # https://docs.djangoproject.com/en/2.0/topics/i18n/
112 |
113 | LANGUAGE_CODE = 'en-us'
114 |
115 | TIME_ZONE = 'UTC'
116 |
117 | USE_I18N = True
118 |
119 | USE_L10N = True
120 |
121 | USE_TZ = True
122 |
123 |
124 | # Static files (CSS, JavaScript, Images)
125 | # https://docs.djangoproject.com/en/2.0/howto/static-files/
126 |
127 | STATIC_URL = '/static/'
128 |
129 | STATICFILES_DIRS = [
130 | os.path.join(BASE_DIR, 'static')
131 | ]
132 |
133 |
134 | LOGIN_URL = 'login'
135 | LOGOUT_URL = 'logout'
136 | LOGIN_REDIRECT_URL = 'users:dashboard'
137 | LOGOUT_REDIRECT_URL = 'users:home'
138 |
139 |
140 | # Email backend
141 | EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
142 |
--------------------------------------------------------------------------------
/website/urls.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from django.urls import path, include
3 | from django.contrib.auth.views import LoginView, LogoutView
4 |
5 | urlpatterns = [
6 | path('admin/', admin.site.urls),
7 | path('', include('users.urls', namespace='users')),
8 | path('profile/', include('profiles.urls', namespace='profiles')),
9 | ]
10 |
11 | urlpatterns += [
12 | path('login/', LoginView.as_view(), name='login'),
13 | path('logout/', LogoutView.as_view(template_name='registration/logout.html'), name='logout'),
14 | ]
15 |
--------------------------------------------------------------------------------
/website/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for website project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "website.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------