Create your blog in 20 mins

Presented by 劉純睿 a.k.a 阿吉

About me

aji.tw

What you need...

  • A Heroku account
  • Basic knowledge of Git
  • Basic knowledge of Django
  • pyenv / virtualenv

Some anecdotes

  • Chief architect
  • Yukihiro "Matz" Matsumoto

  • Etymology
  • Hero + Haiku

Why Heroku?

  1. Free host
  2. Free database
  3. Free domain
  4. Free https
  5. Continuous integration (CI)

What you'll get...

  • https://your_project.herokuapp.com

What is Mezzanine?

A django-based Content Management System (CMS)

Why Mezzanine?

  • Full-fledged
  • Community
  • Plugins
  • i18n

What you need?

Django, nothing more

Demo: Tipei.py blog site

Link

https://taipei-py.herokuapp.com

Github

https://github.com/amigcamel/taipei.py

Let's get started!

Install Heroku CLI

OS X Homebrew:


brew install heroku
                        

Debian/Ubuntu:


sudo apt-get install software-properties-common
sudo add-apt-repository "deb https://cli-assets.heroku.com/branches/stable/apt ./"
curl -L https://cli-assets.heroku.com/apt/release.key | sudo apt-key add -
sudo apt-get update
sudo apt-get install heroku
                        

Others:

see here

Create a Heroku app


heroku login
heroku create your_project
                        

Create a Project


# Install from PyPI
pip install Mezzanine==4.2.2

# Create a project
mezzanine-project your_project
                        

Heroku Specifics

Procfile


web: gunicorn your_project.wsgi --log-file -
                        

requirements.txt


Django==1.8.17
Mezzanine==4.2.2
gunicorn==19.6.0
dj-database-url==0.4.2
psycopg2==2.6.2
whitenoise==3.2.3
                        

runtime.txt


python-3.5.2
                        

Structure


▼ your_project
    ▼ your_project
        __init__.py
        settings.py
        local_settings.py
        urls.py
        wsgi.py
    ▶ static
    Procfile
    requirements.txt
    runtime.txt
                        

Set up Django SECRET_KEY

your_project/settings.py


SECRET_KEY = os.environ.get('SECRET_KEY')
                        

heroku config:set SECRET_KEY="your_django_secret_key"
                        

Database for Heroku

your_project/settings.py

import dj_database_url


DATABASES: {
    'default': {
        "ENGINE": "django.db.backends.postgresql_psycopg2",
        ...
    }
}

DATABASES['default'] = (
    dj_database_url.config() or
    DATABASES['default']
)
                        

Static files for Heroku

your_project/wsgi.py


# put this line at the bottom

from whitenoise.django import DjangoWhiteNoise
application = DjangoWhiteNoise(application)
                        
your_project/settings.py

MIDDLEWARE_CLASSES = (
    ...
    'whitenoise.middleware.WhiteNoiseMiddleware',
    ...
)

STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
                        

Add ALLOWED_HOSTS

your_project/settings.py

ALLOWED_HOSTS = [
    'localhost',
    'your_project.herokuapp.com',
]
                        

Deploying

Create a Git container


git init
heroku git:remote -a your_project
git add -A .
git commit -m 'first commit'
                        

Publishing


# push your project
git push heroku master

# create db
heroku run python manage.py createdb

# db migration
heroku run python manage.py migrate

# deploy
heroku ps:scale web=1
                        

Debugging


heroku logs -t
                        

Customization (1)

Change Site Name and Tagline

settings.py


SITE_NAME = 'Taipei.py'
SITE_TAGLINE = '好聚會,不加入?'
                        

Customization (2)

Localization

Modify settings.py


LANGUAGE_CODE = "zh-tw"

LANGUAGES = (
    ('zh-tw', _('繁體中文')),
)

USE_I18N = True

MIDDLEWARE_CLASSES = (
    ...
    'django.middleware.locale.LocaleMiddleware',
    ...
)
                        

DB migration


heroku run python manage.py makemigrations
heroku run python manage.py migrate                                
                        

Customization (3)

Markdown Editor

pip install


pip install mezzanine-pagedown
pip freeze | grep mezzanine-pagedown >> requirements.txt
                        

settings.py


INSTALLED_APPS = [
    ...
    'mezzanine_pagedown',
]

RICHTEXT_WIDGET_CLASS = 'mezzanine_pagedown.widgets.PageDownWidget'
PAGEDOWN_SERVER_SIDE_PREVIEW = True
RICHTEXT_FILTER_LEVEL = 3
RICHTEXT_FILTERS = [
    'mezzanine_pagedown.filters.extra'
]
                        

urls.py


import mezzanine_pagedown.urls

urlpatterns = i18n_patterns(
    ...
    url("^pagedown/", include(mezzanine_pagedown.urls)),
)
                        

Customization (4)

Google Analytics Integration

Be sure to have this...

base.html


{% block footer_js %}
    {% include "includes/footer_scripts.html" %}
{% endblock %}
                        

You can set it here...

settings.py


GOOGLE_ANALYTICS_ID = 'UA-12345678-9'
                        

or here...

admin > settings > Miscellaneous > Google Analytics ID

Customization (5)

Blog-only Site

urls.py


import mezzanine.blog.views

urlpatterns += [
    ...
    # url("^$", direct_to_template, {"template": "index.html"}, name="home"),
    ...
    url("^$", mezzanine.blog.views.blog_post_list, name="home"),
]
                        

settings.py


BLOG_SLUG = ''
                        

Customization (6)

Override templates

Override templates

Collect all templates:


python manage.py collecttemplates
                        

Collect specific templates:


python manage.py collecttemplates [-t template_name]
                        

Example

  1. Remove cartridge for all pages
  2. Show right panel within blog pages only
templates/base.html

{% if request.path|slice:":5" == '/blog' %}
    
{% comment %} {% nevercache %} {% include "includes/language_selector.html" %} {% include "includes/user_panel.html" %} {% endnevercache %} {% endcomment %}
{% block right_panel %} {% ifinstalled mezzanine.twitter %} {% include "twitter/tweets.html" %} {% endifinstalled %} {% endblock %}
{% endif %}

Thank you