This repository is created to save you from some of the common problems that occur during the development of a django app.
- Creating Virtual Environment
- Setting Up the PostgreSQL DB locally
- When changing
DEBUG = True
toDEBUG = False
in settings.py file - Handling Class-based view of django authentication system (New in django 1.11+)
Some of the hacks you might not know
Virtual Environment - a package (or a functionality) that allows us to have different versions for the same python package. Now you must be thinking, what would I do with different versions of same python packages. Take django as an example, django release its new version after a very short time. Now you don't wanna mess up your current project by installing the new version. Also you want to understand and work with the new functionalities, included in the new django version, so that, in future, you can upgrade your project to the newer version of django. So how can you have both version of django? That's where virtualenv comes to play. It is a python package that helps you to install different versions of the same python packages in one machine. You can even have python 2.x
and python 3.x
in the same machine using virtualenv.
Now that you know what kind of power it possess, lets install virtual environment firstly before creating one. Make sure you have python and pip installed already. And then, just use the following command and you are good to go:
pip install virtualenv
Now to create a virtual environment, firstly create a new directory to have all the virtual environments in one place and change the current working directory using command-line/terminal.
Windows User:
md VEnvironments
cd VEnvironments
Mac/Linux User:
mkdir VEnvironments && cd VEnvironments
Create a virtual environment : Create a virtual envrionment for your project in the '/VEnvironments/' directory using following command:
virtualenv virtual_environment_name
Activate the virtual environment : Activating the virtual environment will make a copy of the python 2.x or python 3.x, which is installed in your local machine but outside of the virtual environment. When the virtual environment is activated, you can install any python packages, according to your need. You can even change the version of python.
Windows User
virtual_environment_name\scripts\activate
Mac/Linux User
source virtual_environment_name/scripts/activate
and you will see something like this in the command-line/terminal virtual_environment_name)
indicating the virtual environment is activated and you can install any version of any packages as your need without messing up the main packages on your local machine outside the virtual environment.
Deactivate the virtual environment: When you don't want to use the virtual environment, just run the following command and it will kind of "log you out" of the virtual environment:
deactivate
Local Setup of PostgreSQL Database
- Django v1.11+
- PostgreSQL
- psycopg
If you already have pip installed, then installing django is really a matter of seconds. Just type the following command:
pip install django
PostgreSQL is an efficient, powerful and open-source object-relational database system. Most of the developers recommend using PostgreSQL because of its features, open-source nature. Even Instagram uses PostgreSQL with django.
PostgreSQL Database - Download Here
Note 📝 : During installation of PostgreSQL, it will ask for a password. Set the password for it and do not forget it. The default user of the PostgreSQL database is postgres
and default port is 5432
. It also creates a default database, which is postgres
.
psycopg is an adapter for PostgreSQL i.e. it is needed to interact with the PostgreSQL Database. It helps in performing concurrent SQL operations such as SELECT, INSERT, UPGRADE, DELETE
from the database etc.
Installing psycopg
Make sure you upgrade pip
pip install -U pip
and then type the following command to install psycopg
pip install psycopg2
To interact with the database, you can either use the GUI tool for PostgreSQL i.e. pgAdmin or you can use the command-line tool, ie SQL Shell (psql). Let me give you a quick demo on how things work PostgreSQL by using the command-line tool, which is installed with PostgreSQL. Just search for the SQL Shell (psql) app and open it.
You will see something like this:
Server [localhost]:
Press enter a few times, and you will see something like this:
Server [localhost]:
Database [postgres]: # Default Database
Port [5432]: # Default Port
Username [postgres]: # Default User
Password for user postgres:
Now, enter the password that you have set during the installation of PostgreSQL. If the password is incorrect, it will close the SQL Shell tool. So you have to again open it and repeat the steps until it ask for password. If the password is correct, you will see something like this:
postgres=#
To create a database, enter the following command, without square brackets:
postgres=# CREATE DATABASE [myDatabaseName];
To connect the database to your local django app, just go to the settings.py file and in the [Database] Section, you will see something like this:
# SQLite3 Database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
Change it to the following 🔃 :
# PostgreSQL Database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'myDatabaseName', # Enter the database name you created above
'USER': 'myDatabaseUser', # Default User = postgres
'PASSWORD': 'myPassword',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
Thats's all, and you are set with the PostgreSQL. 👍
Only change
DEBUG = False
when your site is in PRODUCTION
First things first. DEBUG allows us to see the errors and traceback them. Now if our app raise an exception, django shows a detailed trackeback which includes "almost" every information related to our django environmnet and currently defined settings in settings.py file, except some sensitive information. With DEBUG turned on, the developer can see the reason of the error and remove them. It's only good during development, not production.
When you change the settings from DEBUG = True
to DEBUG = False
in settings.py file, there are things to be taken care of which are:
- You have to set ALLOWED_HOSTS setting, so that your app don't return Bad Request (400) error on requesting. For example:
ALLOWED_HOSTS = [
'example.dev',
]
- Django doesn't take care of your static files with DEBUG turned off, but it allows the web server you chose for production, to take care of the static files for you. See here
- If you still want to load the static files with DEBUG turned off or
DEBUG = False
(for testing purpose), run the following command to run the development server in insecure mode:
python manage.py runserver --insecure
- For more on deploying the static files when in production, click here
Warning ⚠️ - Never-ever deploy a site or a django app into production with DEBUG turned on or DEBUG =True
.
Most of the people (usually beginners) find it really hard to use the django's built-in authentication system since the release of django version 1.11 due to the class-based view for the authentication system included in the new django 1.11+. I personally waste a half day for googling the errors I was encountering. But then, I realised it is time for a change. So I decided to dive into the django documentation and had a look in the authentication views. What I realized is that, the default auth views of django have many things set to default, which gives us some errors, one of which is like this:
NoReverseMatch at /socialNetwork/password_reset/
Reverse for 'password_reset_done' not found. 'password_reset_done' is not a valid view function or pattern name.
All we need to successfully implement the django's built-in authentication system, is to override the default values with our values.
The following templates should be there in your app's templates folder, (e.g. - /app_name/templates/app_name/
folder)
- password_reset_form.html
- password_reset_done.html
- password_reset_email.html
- password_reset_confirm.html
- password_reset_complete.html
- password_reset_subject.txt
{% block content %}
<h3>Forgot password</h3>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
{% endblock %}
{% block content %}
<h3>Password Reset Email Sent</h3>
<p>We've emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly.</p>
<p>If you don't receive an email, please make sure you've entered the address you registered with, and check your spam folder.</p>
{% endblock %}
{% autoescape off %}
You're receiving this email because you requested a password reset for your user account at Social Network.
Please go to the following page and choose a new password:
{{ protocol }}://{{ domain }}{% url 'socialNetwork:password_reset_confirm' uidb64=uid token=token %}
Your username, in case you've forgotten: {{ user.get_username }}
Thanks for using our site!
Sincerely,
Social Network Security team
{% endautoescape %}
{% block content %}
{% if validlink %}
<h3>Set New Password</h3>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Set Password</button>
</form>
{% else %}
<p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p>
{% endif %}
{% endblock %}
{% block content %}
Your new password has been successfully set. Now you can access your account using your new password by <a href="{% url 'socialNetwork:login' %}">logging in</a>.
{% endblock %}
Social Network : Request for resetting the password
from django.conf.urls import url, include
from django.contrib.auth.views import (
PasswordResetView,
PasswordResetDoneView,
PasswordResetConfirmView,
PasswordResetCompleteView
)
from django.urls import reverse_lazy
from . import views
app_name='socialNetwork'
urlpatterns = [
url(r'^$', views.home, name='home'),
url(r'^login/$', views.login_view, name='login'),
url(r'^logout/$', views.logout_view, name='logout'),
url(r'^signup/$', views.signup, name='signup'),
url(r'^profile/$', views.profile, name="profile"),
url(r'^change-password/$', views.changePassword, name='changepwd'),
# Default values for password_reset_view
# template_name='registration/password_reset_form.html'
# email_template_name = 'registration/password_reset_email.html'
# subject_template_name = 'registration/password_reset_subject.txt'
# success_url = reverse_lazy('password_reset_done')
url(r'^reset_password/$',
PasswordResetView.as_view(template_name='socialNetwork/password_reset_form.html',
success_url=reverse_lazy('socialNetwork:password_reset_done'),
email_template_name='socialNetwork/password_reset_email.html',
subject_template_name='socialNetwork/password_reset_subject.txt'),
name='password_reset'),
# Default values for password_reset_view
# template_name='registration/password_reset_done.html'
url(r'^reset_password/done/$',
PasswordResetDoneView.as_view(template_name='socialNetwork/password_reset_done.html'),
name='password_reset_done'),
# Default values for password_reset_view
# template_name='registration/password_reset_confirm.html'
# success_url = reverse_lazy('password_reset_complete')
url(r'^reset_password/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
PasswordResetConfirmView.as_view(template_name='socialNetwork/password_reset_confirm.html',
success_url = reverse_lazy('socialNetwork:password_reset_complete')),
name='password_reset_confirm'),
# Default values for password_reset_view
# template_name='registration/password_reset_complete.html'
url(r'^reset/complete/$',
PasswordResetCompleteView.as_view(template_name='socialNetwork/password_reset_complete.html'),
name='password_reset_complete'),
]
Note 📝 : See the comments in the urls.py for the default values . For more details, dive into the documentation or directly in the django/contib/auth/views.py file
Only do this if your site has SSL certificate
Before we get started with that, you should have a basic knowledge of SSL. Have you ever seen the SECURE or LOCK sign in the address bar for some or most of the websites such as www.google.com or github.com. It looks like this:
Well, if you have seen them now, let me just give you an overview about it. Secure Sockets Layer is the standard technology that enables a secure connection between the web server and the web browser, ensuring the integrity and privacy of all the data passed between the two. If you have a secure certificate or SSL(Secure Sockets Layer) on your website, you can automatically redirect visitors to the secured (HTTPS) version of your website to make sure their information is protected. If you don't have the certificate, visit Lets Encrypt to get a free SSL certificate. Now the type of hosting you have, plays an important role in here.
-
If you have Linux hosting with cPanel then login to cPanel and go to the File manager. In the /public_html/ folder, you'll find the .htaccess file. Make sure, hidden files are also being displayed. On the top-right corner, click on the Setting and check the box that says Show Hidden Files.
- If the file doesn't exist there, then create one with the name .htaccess using cPanel Control Panel. Now, click on Edit in the cPanel to edit the file and paste the following code without any editing:
RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
- If there is an existing file, then just edit it. But remember these two things:
- don't paste or type again
RewriteEngine On
. It is only written one time. - And make sure of it, to paste the line initializing with
RewriteCond
andRewriteRule
afterRewriteEngine On
- don't paste or type again
-
If you have Windows based hosting and Plesk, then the name of the file is web.config file. Don't know much about Plesk but the file must be on the same folder, where your website's Welcome page or Home Page's HTML file resides. Make sure every file is displaying including Hidden Files.
- If the file doesn't exist there, then create one with the name web.config using the Plesk Control Panel. Now, edit the file and paste the following code without any editing:
<configuration> <system.webServer> <rewrite> <rules> <rule name="HTTP to HTTPS redirect" stopProcessing="true"> <match url="(.*)" /> <conditions> <add input="{HTTPS}" pattern="off" ignoreCase="true" /> </conditions> <action type="Redirect" redirectType="Permanent" url="https://{HTTP_HOST}/{R:1}" /> </rule> </rules> </rewrite> </system.webServer> </configuration>
- If there is an existing file, then just edit it. But remember these two things:
- Make sure you have the following tags or code blocks in that file:
-
configuration
-
system.webServer
-
rewrite
-
rules
-
- And then paste the code-block of
<rule> </rule>
(rule without an 's') between the<rules> </rules>
("rules" with an 's') code-block.
- Make sure you have the following tags or code blocks in that file:
If you know already how to automatically redirect HTTP to HTTPS then it is a lot easier for you. If not, then check it out here and then come back.
-
Force redirecting your site and all its links from www.example.com ➡️ example.com
Just put on the following code after RewriteEngine on
and you are all done:
RewriteCond %{HTTP_HOST} ^www\.example.com\.com$
RewriteRule ^/?$ "https\:\/\/example\.com\/" [R=301,L]
Note 📝 : Don't Forget to replace the "example" and "com" with your website's name and clear your cache (sometimes clearing the cache is required)
-
Force redirecting your site and all its links from example.com ➡️ www.example.com
Put on the following code after RewriteEngine on
:
RewriteCond %{HTTP_HOST} !^www.example.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]