├── .gitignore
├── README.md
├── main
├── __init__.py
├── admin.py
├── apps.py
├── forms.py
├── migrations
│ └── __init__.py
├── models.py
├── static
│ ├── css
│ │ └── styles.css
│ └── js
│ │ └── main.js
├── templates
│ ├── components
│ │ └── response.html
│ ├── homepage.html
│ ├── layouts
│ │ └── page.html
│ ├── login.html
│ ├── navbar.html
│ ├── new-question.html
│ ├── question.html
│ └── register.html
├── tests.py
├── urls.py
└── views.py
├── manage.py
├── mywebsite
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
└── requirements.txt
/.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 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
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 |
49 | # Translations
50 | *.mo
51 | *.pot
52 |
53 | # Django stuff:
54 | *.log
55 | local_settings.py
56 |
57 | # Flask stuff:
58 | instance/
59 | .webassets-cache
60 |
61 | # Scrapy stuff:
62 | .scrapy
63 |
64 | # Sphinx documentation
65 | docs/_build/
66 |
67 | # PyBuilder
68 | target/
69 |
70 | # Jupyter Notebook
71 | .ipynb_checkpoints
72 |
73 | # pyenv
74 | .python-version
75 |
76 | # celery beat schedule file
77 | celerybeat-schedule
78 |
79 | # SageMath parsed files
80 | *.sage.py
81 |
82 | # dotenv
83 | .env
84 |
85 | # virtualenv
86 | .venv
87 | venv/
88 | ENV/
89 | .vscode
90 | # Spyder project settings
91 | .spyderproject
92 | .spyproject
93 |
94 | # Rope project settings
95 | .ropeproject
96 |
97 | # mkdocs documentation
98 | /site
99 |
100 | # mypy
101 | .mypy_cache/
102 |
103 | .DS_Store
104 | *.sqlite3
105 | media/
106 | *.pyc
107 | *.db
108 | *.pid
109 |
110 | # Ignore Django Migrations in Development if you are working on team
111 |
112 | # Only for Development only
113 | **/migrations/**
114 | !**/migrations
115 | !**/migrations/__init__.py
116 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # How to create a Q&A website using Django Python | Django portfolio website
2 |
3 | Find full tutorial here 👉 [Youtube](https://youtu.be/PR9Ws30iIU8)
4 |
5 | Hello everyone, in this video we build a Q&A website using Django, you'll learn a lot of the basic stuff to help you started in your own projects. The idea of this project is that you can use it to create your own version of this project and add that to your portfolio.
6 |
7 | This video cover these topics:
8 | - Django forms
9 | - Django templates
10 | - Django Models & Django databases
11 | - Django QuerySet
12 | - Django ORM
13 | - Relationships in Django
14 | - Django authentication
15 |
16 | Follow me:
17 | https://www.instagram.com/codingvenue/
18 |
--------------------------------------------------------------------------------
/main/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingvenue/questions-and-answers-website-django/79738ae6acd5907683f6b77ae738abebc10cad80/main/__init__.py
--------------------------------------------------------------------------------
/main/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from . import models
3 |
4 | # Register your models here.
5 | admin.site.register(models.Question)
6 | admin.site.register(models.Response)
7 |
--------------------------------------------------------------------------------
/main/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class MainConfig(AppConfig):
5 | name = 'main'
6 |
--------------------------------------------------------------------------------
/main/forms.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
2 | from django.contrib.auth.models import User
3 | from .models import Question, Response
4 | from django import forms
5 |
6 | class RegisterUserForm(UserCreationForm):
7 | class Meta:
8 | model = User
9 | fields = ['username', 'email', 'password1', 'password2']
10 | widgets = {
11 | 'email': forms.EmailInput(attrs={
12 | 'required': True,
13 | 'placeholder': 'lisa@example.com',
14 | 'autofocus': True
15 | }),
16 | 'username': forms.TextInput(attrs={
17 | 'placeholder': 'lisamora',
18 | })
19 | }
20 |
21 | def __init__(self, *args, **kwargs):
22 | super(RegisterUserForm, self).__init__(*args, **kwargs)
23 | self.fields['password1'].widget.attrs = {'placeholder': 'password'}
24 | self.fields['password2'].widget.attrs = {'placeholder': 'confirm password'}
25 |
26 | class LoginForm(AuthenticationForm):
27 | class Meta:
28 | fields = '__all__'
29 |
30 | class NewQuestionForm(forms.ModelForm):
31 | class Meta:
32 | model = Question
33 | fields = ['title', 'body']
34 | widgets = {
35 | 'title': forms.TextInput(attrs={
36 | 'autofocus': True,
37 | 'placeholder': 'How to create a Q&A website with Django?'
38 | })
39 | }
40 |
41 | class NewResponseForm(forms.ModelForm):
42 | class Meta:
43 | model = Response
44 | fields = ['body']
45 |
46 | class NewReplyForm(forms.ModelForm):
47 | class Meta:
48 | model = Response
49 | fields = ['body']
50 | widgets = {
51 | 'body': forms.Textarea(attrs={
52 | 'rows': 2,
53 | 'placeholder': 'What are your thoughts?'
54 | })
55 | }
56 |
--------------------------------------------------------------------------------
/main/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingvenue/questions-and-answers-website-django/79738ae6acd5907683f6b77ae738abebc10cad80/main/migrations/__init__.py
--------------------------------------------------------------------------------
/main/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django.contrib.auth.models import User
3 |
4 | # Create your models here.
5 | class Question(models.Model):
6 | author = models.ForeignKey(User, null=False, on_delete=models.CASCADE)
7 | title = models.CharField(max_length=200, null=False)
8 | body = models.TextField(null=False)
9 | created_at = models.DateTimeField(auto_now_add=True)
10 | updated_at = models.DateTimeField(auto_now=True)
11 |
12 | def __str__(self):
13 | return self.title
14 |
15 | def get_responses(self):
16 | return self.responses.filter(parent=None)
17 |
18 | class Response(models.Model):
19 | user = models.ForeignKey(User, null=False, on_delete=models.CASCADE)
20 | question = models.ForeignKey(Question, null=False, on_delete=models.CASCADE, related_name='responses')
21 | parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE)
22 | body = models.TextField(null=False)
23 | created_at = models.DateTimeField(auto_now_add=True)
24 | updated_at = models.DateTimeField(auto_now=True)
25 |
26 | def __str__(self):
27 | return self.body
28 |
29 | def get_responses(self):
30 | return Response.objects.filter(parent=self)
31 |
--------------------------------------------------------------------------------
/main/static/css/styles.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | font-family: Segoe UI;
4 | background-color: #7ef29d;
5 | }
6 |
7 | *, *::after, *::before {
8 | box-sizing: border-box;
9 | }
10 |
11 | a {
12 | text-decoration: none;
13 | }
14 |
15 | ul {
16 | list-style: none;
17 | padding: 0;
18 | }
19 |
20 | blockquote {
21 | border-left: 6px solid lightgray;
22 | padding-left: 6px;
23 | margin-left: 15px;
24 | }
25 |
26 | .main {
27 | max-width: 800px;
28 | margin: 60px auto;
29 | padding: 24px;
30 | border-radius: 20px;
31 | background-color: white;
32 |
33 | box-shadow: 5px 10px #888888;
34 | }
35 |
36 | .navbar {
37 | display: flex;
38 | flex-direction: row;
39 | justify-content: space-between;
40 | padding: 0 24px;
41 |
42 | border-bottom: 1px solid lightgray;
43 | }
44 |
45 | .user-menu ul li a,
46 | .main-menu ul li a {
47 | color: black;
48 | font-weight: 700;
49 | }
50 |
51 | .user-menu ul li a:hover,
52 | .main-menu ul li a:hover {
53 | text-decoration: underline;
54 | }
55 |
56 | .user-menu ul li {
57 | display: inline;
58 | margin-left: 12px;
59 | }
60 |
61 | .page {
62 | display: flex;
63 | flex-direction: column;
64 | }
65 |
66 | .new-question-page,
67 | .login-page,
68 | .register-page {
69 | margin: 0 auto;
70 | min-width: 50%;
71 | max-width: 50%;
72 | }
73 |
74 | .title {
75 | margin: 20px auto 30px auto;
76 | font-weight: 900;
77 | }
78 |
79 | .question-list-item {
80 | margin-bottom: 20px;
81 | }
82 |
83 | .question-list-item a:hover {
84 | text-decoration: underline;
85 | color: black;
86 | }
87 |
88 | .question-list-item-title {
89 | color: black;
90 | font-size: 18px;
91 | font-weight: 900;
92 | margin: 0
93 | }
94 |
95 | .question-list-item-author {
96 | color: lightgray;
97 | margin: 0;
98 | }
99 |
100 | .register-form {
101 | width: 100%;
102 | }
103 |
104 | .fieldWrapper {
105 | display: flex;
106 | flex-direction: column;
107 | margin-bottom: 20px;
108 | }
109 |
110 | .fieldWrapper label {
111 | font-size: 12px;
112 | font-weight: 600;
113 | text-transform: uppercase;
114 | margin-bottom: 10px;
115 | }
116 |
117 | .fieldWrapper input {
118 | margin-bottom: 6px;
119 | border: 1px solid lightgray;
120 | min-height: 40px;
121 | }
122 |
123 | .error {
124 | font-size: 14px;
125 | color: red;
126 | }
127 |
128 | .errorlist {
129 | margin: 0;
130 | }
131 |
132 | .non_form_errors {
133 | margin-bottom: 20px;
134 | }
135 |
136 | .submit-button {
137 | display: block;
138 | width: 120px;
139 | height: 40px;
140 | border: none;
141 | border-radius: 20px;
142 | background-color: black;
143 | color: white;
144 | margin: 0 auto;
145 | cursor: pointer;
146 | }
147 |
148 | .question-title {
149 | font-weight: 900;
150 | margin: 20px auto 0 auto;
151 | }
152 |
153 | .question-body {
154 | margin-bottom: 6px;
155 | }
156 |
157 | .question-author {
158 | font-size: 14px;
159 | color: lightgray;
160 | }
161 |
162 | .responses-container {
163 | border-top: 1px solid lightgray;
164 | margin-top: 30px;
165 | }
166 |
167 | .responses-container-heading {
168 | color: lightgray;
169 | }
170 |
171 | .no-responses-text {
172 | color: lightgray;
173 | }
174 |
175 | .response-body {
176 | margin: 0;
177 | }
178 |
179 | .response-author {
180 | color: lightgray;
181 | font-style: italic;
182 | }
183 |
184 | .reply-button {
185 | background-color: transparent;
186 | border: none;
187 | padding: 0;
188 | text-transform: lowercase;
189 | color: lightgray;
190 | cursor: pointer;
191 | }
192 |
193 | .response-form {
194 | margin-top: 20px;
195 | border-top: 1px solid lightgray;
196 | padding: 30px;
197 | }
198 |
199 | .reply-form-container {
200 | display: none;
201 | }
202 |
203 | .reply-form-container.enabled {
204 | display: block;
205 | }
206 |
207 | .reply-form textarea {
208 | width: 100%;
209 | }
210 |
211 | .reply-form-cancel-button {
212 | font-weight: 600;
213 | color: orange;
214 | background-color: transparent;
215 | border: none;
216 | padding: 4px 12px;
217 | cursor: pointer;
218 | }
219 |
220 | .reply-form-submit-button {
221 | font-weight: 600;
222 | color: white;
223 | background-color: orange;
224 | border: none;
225 | padding: 4px 12px;
226 | border-radius: 4px;
227 | cursor: pointer;
228 | }
229 |
--------------------------------------------------------------------------------
/main/static/js/main.js:
--------------------------------------------------------------------------------
1 | function handleReplyButton(responseId) {
2 | const replyFormContainer = document.getElementById(`reply-form-container-${responseId}`);
3 | if (replyFormContainer) {
4 | replyFormContainer.className = 'reply-form-container enabled'
5 | }
6 | }
7 |
8 | function handleCancelReply(responseId) {
9 | const replyFormContainer = document.getElementById(`reply-form-container-${responseId}`);
10 | if (replyFormContainer) {
11 | replyFormContainer.className = 'reply-form-container'
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/main/templates/components/response.html:
--------------------------------------------------------------------------------
1 |
2 | {{response.body}}
3 | by {{response.user.username}}
4 |
5 | {% if user.is_authenticated %}
6 |
7 | {% endif %}
8 |
9 |
10 |
18 |
19 |
20 | {% for children in response.get_responses %}
21 | {% include 'components/response.html' with response=children %}
22 | {% endfor %}
23 |
24 |
25 |
--------------------------------------------------------------------------------
/main/templates/homepage.html:
--------------------------------------------------------------------------------
1 | {% extends 'layouts/page.html' %}
2 |
3 | {% block content %}
4 |
5 |
All questions
6 |
7 | {% for question in questions %}
8 |
18 | {% endfor %}
19 |
20 | {% endblock %}
21 |
--------------------------------------------------------------------------------
/main/templates/layouts/page.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | {% include 'navbar.html' %}
13 | {% block content %}
14 | {% endblock %}
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/main/templates/login.html:
--------------------------------------------------------------------------------
1 | {% extends 'layouts/page.html' %}
2 |
3 | {% block content %}
4 |
5 |
Login
6 |
7 |
8 |
27 |
28 |
29 | {% endblock %}
30 |
--------------------------------------------------------------------------------
/main/templates/navbar.html:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/main/templates/new-question.html:
--------------------------------------------------------------------------------
1 | {% extends 'layouts/page.html' %}
2 |
3 | {% block content %}
4 |
5 |
New question
6 |
7 |
8 |
22 |
23 |
24 | {% endblock %}
25 |
--------------------------------------------------------------------------------
/main/templates/question.html:
--------------------------------------------------------------------------------
1 | {% extends 'layouts/page.html' %}
2 |
3 | {% block content %}
4 |
5 |
6 |
{{question.title}}
7 |
{{question.body}}
8 |
author : {{question.author.username}}
9 |
10 |
11 |
Responses
12 |
13 | {% if not question.responses.all %}
14 |
No responses yet
15 | {% else %}
16 | {% for response in question.get_responses %}
17 | {% include 'components/response.html' with response=response %}
18 | {% endfor %}
19 | {% endif %}
20 |
21 |
22 | {% if user.is_authenticated %}
23 |
31 | {% endif %}
32 |
33 |
34 | {% endblock %}
35 |
--------------------------------------------------------------------------------
/main/templates/register.html:
--------------------------------------------------------------------------------
1 | {% extends 'layouts/page.html' %}
2 |
3 | {% block content %}
4 |
5 |
Register
6 |
7 |
8 |
37 |
38 |
39 | {% endblock %}
40 |
--------------------------------------------------------------------------------
/main/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/main/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from . import views
3 |
4 | urlpatterns = [
5 | path('register', views.registerPage, name='register'),
6 | path('login', views.loginPage, name='login'),
7 | path('logout', views.logoutPage, name='logout'),
8 | path('', views.homePage, name='index'),
9 | path('new-question', views.newQuestionPage, name='new-question'),
10 | path('question/', views.questionPage, name='question'),
11 | path('reply', views.replyPage, name='reply')
12 | ]
13 |
--------------------------------------------------------------------------------
/main/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render, redirect
2 | from django.contrib.auth import login, logout
3 | from django.contrib.auth.decorators import login_required
4 | from .models import Question, Response
5 | from .forms import RegisterUserForm, LoginForm, NewQuestionForm, NewResponseForm, NewReplyForm
6 |
7 | # Create your views here.
8 |
9 | def registerPage(request):
10 | form = RegisterUserForm()
11 |
12 | if request.method == 'POST':
13 | try:
14 | form = RegisterUserForm(request.POST)
15 | if form.is_valid():
16 | user = form.save()
17 | login(request, user)
18 | return redirect('index')
19 | except Exception as e:
20 | print(e)
21 | raise
22 |
23 | context = {
24 | 'form': form
25 | }
26 | return render(request, 'register.html', context)
27 |
28 | def loginPage(request):
29 | form = LoginForm()
30 |
31 | if request.method == 'POST':
32 | try:
33 | form = LoginForm(data=request.POST)
34 | if form.is_valid():
35 | user = form.get_user()
36 | login(request, user)
37 | return redirect('index')
38 | except Exception as e:
39 | print(e)
40 | raise
41 |
42 | context = {'form': form}
43 | return render(request, 'login.html', context)
44 |
45 | @login_required(login_url='register')
46 | def logoutPage(request):
47 | logout(request)
48 | return redirect('login')
49 |
50 | @login_required(login_url='register')
51 | def newQuestionPage(request):
52 | form = NewQuestionForm()
53 |
54 | if request.method == 'POST':
55 | try:
56 | form = NewQuestionForm(request.POST)
57 | if form.is_valid():
58 | question = form.save(commit=False)
59 | question.author = request.user
60 | question.save()
61 | except Exception as e:
62 | print(e)
63 | raise
64 |
65 | context = {'form': form}
66 | return render(request, 'new-question.html', context)
67 |
68 | def homePage(request):
69 | questions = Question.objects.all().order_by('-created_at')
70 | context = {
71 | 'questions': questions
72 | }
73 | return render(request, 'homepage.html', context)
74 |
75 | def questionPage(request, id):
76 | response_form = NewResponseForm()
77 | reply_form = NewReplyForm()
78 |
79 | if request.method == 'POST':
80 | try:
81 | response_form = NewResponseForm(request.POST)
82 | if response_form.is_valid():
83 | response = response_form.save(commit=False)
84 | response.user = request.user
85 | response.question = Question(id=id)
86 | response.save()
87 | return redirect('/question/'+str(id)+'#'+str(response.id))
88 | except Exception as e:
89 | print(e)
90 | raise
91 |
92 | question = Question.objects.get(id=id)
93 | context = {
94 | 'question': question,
95 | 'response_form': response_form,
96 | 'reply_form': reply_form,
97 | }
98 | return render(request, 'question.html', context)
99 |
100 |
101 | @login_required(login_url='register')
102 | def replyPage(request):
103 | if request.method == 'POST':
104 | try:
105 | form = NewReplyForm(request.POST)
106 | if form.is_valid():
107 | question_id = request.POST.get('question')
108 | parent_id = request.POST.get('parent')
109 | reply = form.save(commit=False)
110 | reply.user = request.user
111 | reply.question = Question(id=question_id)
112 | reply.parent = Response(id=parent_id)
113 | reply.save()
114 | return redirect('/question/'+str(question_id)+'#'+str(reply.id))
115 | except Exception as e:
116 | print(e)
117 | raise
118 |
119 | return redirect('index')
120 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mywebsite.settings')
10 | try:
11 | from django.core.management import execute_from_command_line
12 | except ImportError as exc:
13 | raise ImportError(
14 | "Couldn't import Django. Are you sure it's installed and "
15 | "available on your PYTHONPATH environment variable? Did you "
16 | "forget to activate a virtual environment?"
17 | ) from exc
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/mywebsite/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codingvenue/questions-and-answers-website-django/79738ae6acd5907683f6b77ae738abebc10cad80/mywebsite/__init__.py
--------------------------------------------------------------------------------
/mywebsite/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for mywebsite project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mywebsite.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/mywebsite/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for mywebsite project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.1.3.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.1/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.1/ref/settings/
11 | """
12 |
13 | from pathlib import Path
14 |
15 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
16 | BASE_DIR = Path(__file__).resolve().parent.parent
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = '+q*p#-#2)u*p9t68n#tb)rn^$w7$wd8u)4qu^((61=2&lu8s8_'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = []
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'django.contrib.admin',
35 | 'django.contrib.auth',
36 | 'django.contrib.contenttypes',
37 | 'django.contrib.sessions',
38 | 'django.contrib.messages',
39 | 'django.contrib.staticfiles',
40 | 'main'
41 | ]
42 |
43 | MIDDLEWARE = [
44 | 'django.middleware.security.SecurityMiddleware',
45 | 'django.contrib.sessions.middleware.SessionMiddleware',
46 | 'django.middleware.common.CommonMiddleware',
47 | 'django.middleware.csrf.CsrfViewMiddleware',
48 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
49 | 'django.contrib.messages.middleware.MessageMiddleware',
50 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
51 | ]
52 |
53 | ROOT_URLCONF = 'mywebsite.urls'
54 |
55 | TEMPLATES = [
56 | {
57 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
58 | 'DIRS': [],
59 | 'APP_DIRS': True,
60 | 'OPTIONS': {
61 | 'context_processors': [
62 | 'django.template.context_processors.debug',
63 | 'django.template.context_processors.request',
64 | 'django.contrib.auth.context_processors.auth',
65 | 'django.contrib.messages.context_processors.messages',
66 | ],
67 | },
68 | },
69 | ]
70 |
71 | WSGI_APPLICATION = 'mywebsite.wsgi.application'
72 |
73 |
74 | # Database
75 | # https://docs.djangoproject.com/en/3.1/ref/settings/#databases
76 |
77 | DATABASES = {
78 | 'default': {
79 | 'ENGINE': 'django.db.backends.sqlite3',
80 | 'NAME': BASE_DIR / 'db.sqlite3',
81 | }
82 | }
83 |
84 |
85 | # Password validation
86 | # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
87 |
88 | AUTH_PASSWORD_VALIDATORS = [
89 | {
90 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
91 | },
92 | {
93 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
94 | },
95 | {
96 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
97 | },
98 | {
99 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
100 | },
101 | ]
102 |
103 |
104 | # Internationalization
105 | # https://docs.djangoproject.com/en/3.1/topics/i18n/
106 |
107 | LANGUAGE_CODE = 'en-us'
108 |
109 | TIME_ZONE = 'UTC'
110 |
111 | USE_I18N = True
112 |
113 | USE_L10N = True
114 |
115 | USE_TZ = True
116 |
117 |
118 | # Static files (CSS, JavaScript, Images)
119 | # https://docs.djangoproject.com/en/3.1/howto/static-files/
120 |
121 | STATIC_URL = '/static/'
122 |
--------------------------------------------------------------------------------
/mywebsite/urls.py:
--------------------------------------------------------------------------------
1 | """mywebsite URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.1/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import path, include
18 |
19 | urlpatterns = [
20 | path('admin/', admin.site.urls),
21 | path('', include('main.urls'))
22 | ]
23 |
--------------------------------------------------------------------------------
/mywebsite/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for mywebsite 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/3.1/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', 'mywebsite.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | asgiref==3.3.1
2 | Django==3.1.3
3 | pytz==2020.4
4 | sqlparse==0.4.1
5 |
--------------------------------------------------------------------------------