aboutsummaryrefslogtreecommitdiff
path: root/content/weblog/2018-07-21_building-deploying-personal-site-with-blog-pt1/index.md
blob: 170ee300656b5544fdc40e5768c61b6352a907eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
+++
title = "Building and deploying a personal site with blog. Part 1"
date = 2018-07-21T21:46:00Z
+++

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.

<!-- more -->

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](https://github.com/Yaroslav-95/w3blog). 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):

```sh
$ sudo pacman -S postgresql
```

Or for Ubuntu and other Debian-based distros:

```sh
$ 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):

```sh
$ 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:

```sh
$ sudo pacman -S python-virtualenv
```

Or

```sh
$ sudo apt-get install python-virtualenv
```

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

```sh
$ 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:

```sh
$ 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:

```sh
$ 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](https://summernote.org/).

### 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

```sh
$ 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:

```py
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

```sh
#!/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

```sh
$ source variables.sh
```

or

```sh
$ . 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`:

```py
    '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:

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

And set our allowed hosts:

```py
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:

```sh
$ sudo su - postgres
$ psql
```

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

```sh
postgres=# \password
```

After that, we create our database

```sh
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:

```sh
$ ./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:

```sh
$ ./manage.py makemigrations --merge
```

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

```sh
# ./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:

```py
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

```sh
$ ./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

```sh
$ 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:

```py
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](/weblog/building-deploying-personal-site-with-blog-pt2/).