Starting Python Django Zinnia Blog

Python Django Zinnia is a great alternative for WordPress, especially for those who don’t want to use PHP but Python for web development.
It uses Django which is a web application framework for python web app development. Django comes with a little web server and uses sqlite for backend database server by default. Here, I leave a note on how to set up django zinnia on top of postgresql, nginx and python3 on Arch Linux

 1. install necessary packages from repo.

pacman -S python python-pip nginx postgresql  python-psycopg2
pacman -S libjpeg-turbo gcc

 

2. install python modules.  don’t use uwsi from aur as it depends on python2 and some other unnecessary packages.

pip3 install django-blog-zinnia
pip3 install uwgsi

 

3. setup postgresql.

# Initialise DB
initdb --locale en_GB.UTF-8 -E UTF8 -D '/var/lib/postgres/data'

# disble cow (for btrfs filesystem)
chattr +C /var/lib/postgres/data

# start the service
exit
systemctl start postgresql
systemctl enable postgresql

# create user and db and grant privileges
createuser –interactive
createdb mydjangodb

# login to db
GRANT ALL PRIVILEGES ON DATABASE mydjangodb TO username;
\q

# change db config according to your needs
# default listen port is localhost:5432
/var/lib/postgres/data/postgresql.conf

 

3. Setup uwsgi.

# create directory

mkdir -p /etc/uwsgi/vassals

# Create emperor file (for managing multiple instances)

vim /etc/uwsgi/emperor.ini
[uwsgi]
emperor = /etc/uwsgi/vassals
uid = http
gid = http

# Create systemd unit file

vim /etc/systemd/system/emperor.uwsgi.service

[Unit]
Description=uWSGI Emperor
After=syslog.target

[Service]
ExecStart=/usr/bin/uwsgi –ini /etc/uwsgi/emperor.ini
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -INT $MAINPID
Restart=always
Type=notify
StandardError=syslog
NotifyAccess=all
KillSignal=SIGQUIT

[Install]
WantedBy=multi-user.target

 

3. change django db setting.

# Create django project under opt/django
mkdir -p /opt/django
cd /opt/django
django-admin.py startproject mysite

# Edit django a setting file, and change database setting.
vi mysite/mysite/settings.py

# DATABASES = {
# ‘default’: {
# ‘ENGINE’: ‘django.db.backends.sqlite3’,
# ‘NAME’: os.path.join(BASE_DIR, ‘db.sqlite3’),
# }
# }

Comment out like above and add lines below.
DATABASES = {
‘default’: {
‘ENGINE’: ‘django.db.backends.postgresql’,
‘NAME’: ‘mydjangodb’,
‘USER’: ‘username’,
‘HOST’: ‘localhost’,
‘PORT’: ‘5432’,
}
}

 

4. set django and nginx

 # Copy nginx uwsgi parameter files to django project directory.

cp /etc/nginx/uwsgi_params /opt/django/mysite/

# Create nginx config file under django project directory, and add the following.

vim /opt/django/mysite/mysite_nginx.conf

 

upstream django {
#server unix:///path/mysite.sock; # for using unix socket
server 127.0.0.1:8001;
}

server {
listen 8000;
server_name 127.0.0.1;
charset utf-8;

location /static {
alias /opt/django/mysite/static;
}

location / {
uwsgi_pass django;
include /opt/django/mysite/uwsgi_params;
}

}

# add below to http directive of nginx main config file

vim /etc/nginx/nginx.conf

include /etc/nginx/sites-enabled/*;

 

# Create nginx include config directory and link symbolically.
mkdir /etc/nginx/sites-enabled/
ln -s /opt/django/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/

# Create uwsgi config file under django directory and link symbolically.

vim /opt/django/mysite/mysite_uwsgi.ini
[uwsgi]

chdir = /opt/django/mysite/
module = mysite.wsgi
master = true
processes = 4
socket = 127.0.0.1:8001

ln -s /opt/django/mysite/mysite_uwsgi.ini /etc/uwsgi/vassals/

cp -R /usr/lib/python3.5/site-packages/django/contrib/admin/static /opt/django/mysite/

 

5. Start the services

 

systemctl start emperor.uwsgi
systemctl start nginx

Now, you should be able to access to http://127.0.0.1:8000/admin/

 

6. Set up django-zinnia-blog

Trying to figure out…
adding ‘tagging’ to INSTALLED APPS fails the program.
without adding ‘tagging’ app, i cannot load zinnia…

python is failing to load the following module. get_model method is not included in the source from the first place!
‘from django.db.models import get_model’

OK. I found a solution.

# back up the original python module.
cp -p /usr/lib/python3.5/site-packages/tagging/templatetags/tagging_tags.py /usr/lib/python3.5/site-packages/tagging/templatetags/tagging_tags.py.ori# Rewrite the module.
Comment the following line
# from django.db.models import get_modelAnd add the following lines.
from django.apps import apps
get_model = apps.get_model# Copy the static files
cp -Rp /usr/lib/python3.5/site-packages/zinnia/static/zinnia /opt/django/mysite/static/

mysite-nginx.conf look like this.

upstream django {
#server unix:///path/mysite.sock; # for using unix socket
server 127.0.0.1:8001;
}

server {
listen 80;
server_name 0.0.0.0;
charset utf-8;

location /static {
alias /opt/django/mysite/static;
}

location / {
uwsgi_pass django;
include /opt/django/mysite/uwsgi_params;
}

}

setting.py looks like this.

import os

gettext = lambda s: s

DEBUG = False

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydjangodb',
'USER': 'username',
'HOST': 'localhost',
'PORT': '5432',
}
}

TIME_ZONE = 'Asia/Tokyo'

STATIC_URL = '/static/'
STATIC_ROOT = '/opt/django/mysite/static/'

MEDIA_URL = '/media/'

SECRET_KEY = 'jo-1rzm(%sf)3#n+fb7h955yu$3(pt63abhi12_t7e^^5q8dyw'

USE_TZ = True
USE_I18N = True
USE_L10N = True

SITE_ID = 1

LANGUAGE_CODE = 'en'

ALLOWED_HOSTS = ('*')

LANGUAGES = (
('en', gettext('English')),
('fr', gettext('French')),
('de', gettext('German')),
('es', gettext('Spanish')),
('it', gettext('Italian')),
('nl', gettext('Dutch')),
('sl', gettext('Slovenian')),
('bg', gettext('Bulgarian')),
('hu', gettext('Hungarian')),
('cs', gettext('Czech')),
('sk', gettext('Slovak')),
('lt', gettext('Lithuanian')),
('ru', gettext('Russian')),
('pl', gettext('Polish')),
('eu', gettext('Basque')),
('he', gettext('Hebrew')),
('ca', gettext('Catalan')),
('tr', gettext('Turkish')),
('sv', gettext('Swedish')),
('is', gettext('Icelandic')),
('hr_HR', gettext('Croatian')),
('pt_BR', gettext('Brazilian Portuguese')),
('fa_IR', gettext('Persian')),
('fi_FI', gettext('Finnish')),
('uk_UA', gettext('Ukrainian')),
('zh-hans', gettext('Simplified Chinese')),
)

MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.admindocs.middleware.XViewMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)

ROOT_URLCONF = 'mysite.urls'

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.i18n',
'django.template.context_processors.request',
'django.contrib.messages.context_processors.messages',
'zinnia.context_processors.version',
]
}
}
]

INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.sitemaps',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.sites',
'django.contrib.admin',
'django.contrib.admindocs',
'django.contrib.staticfiles',
'django_comments',
'django_xmlrpc',
'mptt',
'tagging',
'zinnia'
)

from zinnia.xmlrpc import ZINNIA_XMLRPC_METHODS
XMLRPC_METHODS = ZINNIA_XMLRPC_METHODS


urls.py looks like this.

"""Urls for the demo of Zinnia"""
from django.conf import settings
from django.contrib import admin
from django.conf.urls import url
from django.conf.urls import include

# from django.views.static import serve
from django.views.defaults import bad_request
from django.views.defaults import server_error
from django.views.defaults import page_not_found
from django.views.defaults import permission_denied
from django.views.generic.base import RedirectView
from django.contrib.sitemaps.views import index
from django.contrib.sitemaps.views import sitemap

from django_xmlrpc.views import handle_xmlrpc

from zinnia.sitemaps import TagSitemap
from zinnia.sitemaps import EntrySitemap
from zinnia.sitemaps import CategorySitemap
from zinnia.sitemaps import AuthorSitemap

urlpatterns = [
url(r'^$', RedirectView.as_view(url='/blog/', permanent=True)),
url(r'^blog/', include('zinnia.urls', namespace='zinnia')),
url(r'^comments/', include('django_comments.urls')),
url(r'^xmlrpc/$', handle_xmlrpc),
url(r'^i18n/', include('django.conf.urls.i18n')),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
]

sitemaps = {
'tags': TagSitemap,
'blog': EntrySitemap,
'authors': AuthorSitemap,
'categories': CategorySitemap
}

urlpatterns += [
url(r'^sitemap.xml$',
index,
{'sitemaps': sitemaps}),
url(r'^sitemap-(?P<section>.+)\.xml$',
sitemap,
{'sitemaps': sitemaps}),
]

urlpatterns += [
    url(r'^400/$', bad_request),
    url(r'^403/$', permission_denied),
    url(r'^404/$', page_not_found),
    url(r'^500/$', server_error),
]

if settings.DEBUG:
    urlpatterns += [
    url(r'^media/(?P<path>.*)$', serve,
    {'document_root': settings.MEDIA_ROOT})
    ]


 

7. Sync DB and Restart the uwsgi service and access the site.
Now you should build your website and webapps. Change urls according to your needs.

python manage.py migrate
systemctl restart emperor.uwsgi

Access http://127.0.0.1:8000/blog

 

8. Restrict access to admin page

Advertisements
Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: