Building and deploying a personal site with blog. Part 1

Published 2018-07-21 on Yaroslav's weblog

I will be explaining in this guide how I built, and how I deployed this site. This will be a really simple tutorial, on how to do it using Python and Django. You might want to have a little knowledge of Django and Python previous to attempting to follow the instructions laid out in this tutorial, as the goal of this tutorial is not to teach you the basic principles of either the Python programming language, or Django framework. It is just meant as a little guide on the basic workflow when building and deploying sites with Django.

Initially I intended for the whole guide to be just one post, but I had to break it into two posts since it ended up being too long. This first part will focus on the initial process of setting up and building a kind of personal blog site based on what I did for my own site, using the Django framework.

I will not be writing here on how I made the blog engine for this site, rather I will be using a blog engine that I have made, called w3blog (you can read it either as "weblog", or as "w3/www blog"). Checkout the GitHub page here. I will not be writing on this guide all of the possible configurations of w3blog, I will be writing a separate post about it soon (actually, I should also write thorough documentation for the module, and I will, but while I get enough time to do it, I will write a short post about it in the meantime).

So let's get our hands dirty...

Part I: Building and getting the site ready for deployment

Before getting started, we need to make that everything we need is installed. In this case I am building my site using Python 3.6, and Django 2.0. I am also using PostgreSQL as my database.

First steps

I am using Manjaro as my OS, so I already have installed Python 3.6. You should also have Python 3.6 installed if you are using Ubuntu 18.04. PostgreSQL doesn't come by default, so using the terminal I installed postgres using the following command (this is for Manjaro and other Arch based distros):

$ sudo pacman -S postgresql

Or for Ubuntu and other Debian-based distros:

$ sudo apt-get update
$ sudo apt-get install postgresql

If you're using Windows, these commands will obviously not be of much help (unless you are using the Linux Subsystem for Windows, or whatever Micro$oft is calling it these days).

I would recommend using Linux for web development (or any kind of development (or any kind of use case for that matter)), especially with Python, or even Mac OSX (or whatever Apple has taken to calling their OS these days), since it is also Unix-like, and you have bash installed natively. However, if you do plan on using Windows to develop your site, you should be able to download the respective installers from their respective websites.

Anyway, back to the topic.

Next, we start PostgreSQL using systemd (or your init system of choice):

$ sudo systemctl start postgresql

Once we have Python and Postgres installed, we need to create a virtual environment to keep all the packages that we need for our site all in one place. Now, you could of course skip this step and just install the packages system-wide, however, it is a better practice to have different environments for different projects.

I am not going to be explaining the reasons for that since there already are a lot of articles on the internetz which do a better job at explaining why, than I would.

If you don't have virtualenv installed, go ahead and do it now:

$ sudo pacman -S python-virtualenv

Or

$ sudo apt-get install python-virtualenv

Now we cd into the directory where we want to keep our environments and do:

$ virtualenv envname -p python3

After some seconds we should have a new folder with our new virtual environment. To activate the environment we need to source the "activate" script inside the environment, like so:

$ source envname/bin/activate

You should now notice the name of the environment on the left side of your prompt. After that we can proceed to install with pip the packages that we need, for example, to install Django:

$ pip install Django

The list of packages needed to build the site in this tutorial:

Django
Pillow
psycopg2
django-summernote
w3blog

Pillow is a package used by Django to work with images saved on the database. psycopg2 is needed to use PostgreSQL with and Django. w3blog is my blog engine, it makes use of django-summernote, a module to integrate the wonderful editor summernote. You can find out more about it here.

Starting and setting up the project

After that we are ready to initialize our project. We cd into a directory where we usually keep all our projects, and tell django to initialize it for us

$ django-admin startproject mysite

Django will create the basic directory structure for our project and generate some basic files to get started. If you run "manage.py runserver" right now you will get the welcome screen from Django telling you your project has been correctly initialized. I will be skipping that part and go on ahead and start configuring my project as needed.

First let's set up the settings.py file by modifying the following settings, the other we can leave for the time being:

from django.utils.translation import ugettext_lazy as _

SECRET_KEY = os.environ.get('SITE_SECRETKEY')
DEBUG = os.environ.get('SITE_DEBUG') == true

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'sitedb',
        'USER': os.environ.get('SITE_DBUSER'),
        'PASSWORD': os.environ.get('SITE_DBPASSWORD'),
        'HOST': os.environ.get('SITE_DBHOST'),
        'PORT': os.environ.get('SITE_DBPORT')
    }
}

LANGUAGE_CODE = 'en-us'

LANGUAGES = (
        ('es', _('Spanish')),
        ('en', _('English')),
        ('ru', _('Russian')),
)

LOCALEPATHS = (
os.path.join(BASE_DIR, 'locale'),
)

TIME_ZONE = 'Europe/Moscow'

USE_I18N = True
USE_L10N = True
USE_TZ = True

STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')

You may have noticed that I am using os.environ.get('ENVVAR_NAME') to get some of my settings from environmental variables, instead of typing those settings directly into my file. Part of the reason I do that, is because it is not safe to store information such as passwords, or secret keys in your code.

Also, since not all of my settings are the same in my local, or testing machine, as in my server or production machine, this makes it more convenient and easier, since I don't have to keep two different "settings.py" files, and I don't risk the chance of, for example, uploading my passwords, and other private information to a service like GitHub, or BitBucket, should I decide to publicly host the source code of my site.

There are other reasons for that, and there are other ways to keep config separated from code, but I will not be going into much detail now.

To export the environmental variables while you're developing, you can create a script (for example variables.sh) that will export them for you, it should something like this

#!/bin/sh
export SITE_SECRETKEY="YOURSECRETKEYGOESHERE"
export SITE_DEBUG="false"
export SITE_DBPASSWORD="YOURPOSTGRESPWDGOESHERE"
export SITE_DBUSER="postgres"
export SITE_HOST="localhost"
export SITE_PORT="5342"

To export the variables from the file to your current shell you would run either

$ source variables.sh

or

$ . variables.sh

Both work equally fine.

The other settings are the language and locale settings. This is an example of my settings, so you should them accordingly to your needs. For example, my site is available in three languages, so I them accordingly in the LANGUAGES tuple, and also enabled Django's localization services by setting the USE_I18N and USE_L10N variables to True.

If you want Django to translate your site according to the user settings automatically, you also need to add the following to MIDDLEWARE before CommonMiddleWare, but after SessionMiddleware:

    'django.middleware.locale.LocaleMiddleware',

The last three settings back there, are so that Django knows where to look for static files such as images, css, js, etc. And so that it knows where to save and look for images belonging to models in the database, for example, if a user uploads a picture, or this case, if I embed an image in one of my blog posts.

Let us not forget about adding the modules that we downloaded with pip to the list of installed apps:

INSTALLED_APPS = [
    '...',
    'django-summernote',
    'weblog',
]

And set our allowed hosts:

ALLOWED_HOSTS = [
    '127.0.0.1',
    'mysite.xyz',
]

Configuring the DB

With these settings, we can now migrate our models to the database. However, before doing that we need to set up the database in PostgreSQL. For that we need to open up the terminal and switch to user postgres, and open up the psql shell:

$ sudo su - postgres
$ psql

Inside the shell, if you haven't set up a password for user postgres, do so now:

postgres=# \password

After that, we create our database

postgres=# create database sitedb;

And NOW, we can migrate our models. Let us do so by going back to our project's root directory, and typing:

$ ./manage.py migrate

If for some reason, it complains to you about some model migrations conflicts, go ahead and do the following, typing "y" when it prompts you:

$ ./manage.py makemigrations --merge

After migrating we can create a superuser so that we can enter the Django admin site:

# ./manage.py createsuperuser

Launching the project

One final thing before our site is ready for use. We need to add the corresponding urls for the w3blog engine, and summernote editor in our projects main urls.py file. So let's go ahead and add them, our urls.py file should like this:

from django.contrib import admin
from django.conf import settings
from django.urls import path, include
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('summernote/', include('django_summernote.urls')),
    path('', include('weblog.urls')),
]
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Now we if we launch our development server

$ ./manage.py runserver

And go to 127.0.0.1:8000 in our browser, we should see a basic blog site with no posts on it yet, however, if we go to the django admin page, we can some posts, and so our site is not so empty anymore!

Now, if you are planning on having some other things on you site besides the blog, you need to start a new django app inside your project's root directory

$ django-admin startapp myapp

Add an include to it's urls config to the main urls.py file. So your project's urlpatterns variable now might be looking something like this:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('summernote/', include('django_summernote.urls')),
    path('weblog/', include('weblog.urls')),
    path('', include('myapp')),
]

And don't forget to add your app's name to the INSTALLED_APPS list in "settings.py".

This is it for part 1 of this little guide. Soon I will post the second part where I'll write about how I deployed my site to a Debian server.

Continue reading part two here.

© 2018—2024 Yaroslav de la Peña Smirnov.