The making of this website

i hate migrations

I decided to put my knowledge of Django to the test by building a blog to host on my domain adrientremblay.com.  It probably would have been much easier to have used something simple like Wordpress or Joomla.  But I'm a self-proclaimed Django God.

A Previous Attempt

Previously I had attempted to create a website using pure HTML, CSS, Javascript and a few javascript plugins such as JQuery.js and Cyclotron.js .  It was a cool one page site with a beautiful carousel homepage image but i wanted the functionality of a blog and I wasn't about to make my own blog engine using PHP .  So I did the only logical thing and made a site using a popular new-age web framework: Django.

Django

Django is a web framework.  Simply put it allows people to create websites using Python instead of more or less by hand using PHP and hard-coded SQL.  It uses 'models' which are used to design tables in the database, 'views' which are Python descriptions of webpages, and 'templates' which serve as the mostly HTML templates for said views.

Django projects are comprised of apps which each have their own migrations, views and models.  A Django project is a web project as a whole, while the apps that make it up are simply the modular packages that comprise that project.  Each app ideally serves a specific purpose for the site, and are meant to be reusable.

Mezzanine

Mezzanine is a Content Management System(CMS) that is built on-top of Django.  CMSs allow one to manage pages and blog posts through a user-interface most often some sort of admin-site.  They are useful for web-developers as a website can be created by web-developers then management of the site can be handed off to the less tech-savvy client.  You may have heard of the ever popular Wordpress CMS.

Design Of The Site

The starting point of the site was a free bootstrap theme I found here https://startbootstrap.com/themes/clean-blog/.  This formed the skeleton of my site.  I collected the Mezzanine Django 'templates' and stitched in the HTML from the theme I found.  Then I copied over the static javascript, and css files from the theme into my site's static folder and created references for them in my blog.  Use of Django and Mezzanine tags was necessary to get the stitched HTML to work.  I went into my settings.py file and changed the base url of my site to point to the Mezzanine blog engine's URL.

This is where things got a tad iffy.  I wanted two things to my site which were not present in core Mezzanine:

- taglines for blog posts and pages

- an image for every page on my site

I added a tagline to the Mezzanine blogpost model using field injection.  Which basically consisted of adding

EXTRA_MODEL_FIELDS = (
    (
        "mezzanine.blog.models.BlogPost.tagline",
        "django.db.models.TextField", # 'django.db.models.' is implied if path is omitted.
        ("Tagline",),
        {"blank": True, "default": ""},
    ),
)

to my settings.py file, and then some mumbo-jumbo in my admin.py file to rip the fields from BlogPostAdmin, add a tagline field, then great my own BlogPostAdmin registering it in place of the old one.

After that, adding a tagline and image to pages was simple enough.  I decided to simply create my own page that extended Page and RichText, (Yay Python multiple inheritance!).  In my models.py I added a tagline field, and an Image field using the mezzanine.core.fields.FileField field.

Migration Issues

Migrations are Django's way to make changes to a websites database schema smoothly and without problems.  These migration files are generated by a console command after changes are made to an app's models.py file.  Usually migrations are automatic and can be trusted to work correctly with the database, like I had experiences with working on other pure Django projects. 

But while working with this site what I did was make changes to Mezzanine's models which caused problems as the migrations that were generated were created in folders inside the mezzanine library.  Ideally one creates migrations in a local test environment then commits them to the deployment server where they are then migrated to make changes to the production database.

Now since the test and production environments each download their own requirement libraries, the migrations that i made to the blog app inside the local environment were not committed to the production server.  I resolved this issue by placing:

MIGRATION_MODULES = {
    "myblog": "myblog.migrations",
    "blog" : "blogmigrations",
}

into my settings.py file to create a folder for the Mezzanine blog app to use for migrations that could be pushed to the production server and used for migration.

Amazon S3 Heroku Filesystem

Heroku has an ephemeral filesystem which means changes last only until the end of each dyno's life.  Dynos last only as long as their is recent activity on the site.  If there is no activity for a while the dyno will shut down.  And will only boot up with a fresh version of the build when sometimes tries to access the site again.  This means static files that are added to the site will disappear after the dyno shuts down.

To solve this issue I hosted my static files with Amazon S3 which is a file storage service.  I had issues with a package called filebrowser_safe which is Mezzanine CMS's default media manager which works fine when files are stored locally but I ended up implementing a replacement called filebrowser_s3.

Conclusion

Having a personal site is important in this day and age and building one using Django (a powerful web framework that could be used to power the most intricate of sites) was a good experience.