Project: How To Build a Simple & Extendable Blogging Platform with Django & Python

Preface

Recently I felt like I wanted to branch out and learn something new. I've always been interested in the practical and creative side of programming, so being able to deploy a project that is public facing was an exciting departure from the myriad of bespoke and educational Python scripts I've written.

Django was exciting to me for a few reasons:

  • Popular and Scalable (Instagram, Spotify, Dropbox)
  • Excellent Documentation
  • Embraces Test Based Development

I started my journey by cozying up with the official Django tutorial which teaches you how to write a simple poll app. This was a good intro, and opened my eyes to the simplicity and beauty of writing unit tests in Django. However, I wanted something a bit friendlier – something in-between a drawn out 4 hour monetised Youtube video, and the official documentation. This lead me to (DjangoGirls)[https://tutorial.djangogirls.org/en/], an excellent bottom-up intro to Django with a focus on promoting Women in STEM.

DjangoGirls might not appeal to those who claim to have been grinding out leetcode problems since kindergarten, but for me, the mid-paragraph smiley faces and congratulatory and plainspoken tone of the tutorials was perfect.

I won't try to rework the great tutorial DjangoGirls has already put together, but rather add some additional resources that I found interesting and useful when putting my blog together.

PythonAnywhere

Virtual Environments (venv)

Using a virtual environment at the start of your journey is incredibly important, although it might not seem like it at first, but it's crucial for making sure your code not only works on your machine, but will work for others. See the DjangoGirls tutorial on starting a venv for your project.

GitHub Actions

Automating the testing of your projects is incredibly important, and gives you an inexplicable insight into how your application truly works. Writing tests with Django isn't covered in the DjangoGirls tutorial, so for this I highly recommend this article in the official Django documentation

Here's an example of a simple test I wrote for the DjangoBlog which can be run through python manage.py test:

class IndexPageTests(TestCase):

    def test_request_index_page(self):
        '''
        Make sure the homepage is reachable
        '''
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)


    def test_post_creation(self):
        '''
        Make sure the post creation is working
        '''
        create_post('Test title', 'Test text')
        self.assertTrue(Post.objects.filter(title='Test title').exists())

    def test_posts_are_visible(self):
        '''
        Make sure the posts are visible on the index page
        '''
        create_post('Test title', 'Test text')
        response = self.client.get('/')
        self.assertContains(response, 'Test title')

Once you've written your tests, you can actually get GitHub to run these tests on their servers through the magic of GitHub Actions – this means every new commit you make to your repo will get tested, and quickly let you know if you've broken anything before you get a chance break anything else.

This is where your virtual environment becomes really useful. You'll need to provide GitHub with a requirements.txt file which contains all of your projects dependencies. pip can quickly generate this for you by running $ pip freeze > requirements.txt from inside your virtual environment. For a better understanding of the beauty of a venv, this article is excellent.

With the requirements.txt in your root directory, go to your GitHub repo, click GitHub actions and select Django. This will create a .github/workflows/django.yml file which tells GitHub how to test your codebase. Due to some incompatibilities, I was unable to get my code to pass using python 3.7, so I limited the testing scope to versions 3.8 in the django.yml file:

---snip---
    strategy:
      max-parallel: 4
      matrix:
        python-version: [3.8, 3.9]
---snip---

22