Upgrading My Website with Django
I've been dabbling with Python here and there for small projects, but for most of my web development work, I had been sticking to the modern go-to stacks like React. However, a friend was learning Django, and I figured—why not throw myself into it as well? I really liked what I saw and enjoyed the development flow a lot! After getting familiar with the basics and setting up some test pages, I decided to go all in and upgrade my portfolio website using Django.
But why make the switch? Just for the sake of a new stack? Not exactly. The biggest draw for me was Django’s built-in admin interface, which is easily configurable and can be turned into a mini CMS. I had two specific goals for this upgrade:
Make it easy to add new projects to my site – Previously, I had to manually edit the code every time I wanted to showcase a new project. Not the fastest or easiest process.
Enable basic blogging features – I wanted a simple way to share my thoughts and experiences without jumping through hoops.
Choosing a WYSIWYG Editor
A crucial part of setting up a blog was having a solid WYSIWYG editor. I experimented with two options: TinyMCE and Summernote.
TinyMCE: I initially tried TinyMCE, but I ran into numerous configuration issues, and overall, I had a frustrating experience.
Summernote: Much easier to set up, and it integrated well with Django’s admin interface.
However, one thing didn’t work out of the box—sanitizing the HTML stored in the database and displayed on the site. To fix this, I installed Mozilla Bleach and fine-tuned Summernote’s configuration to strip unwanted elements. Most of the security concerns were resolved quickly, but one glaring issue remained: video embed iframes.
Securing Video Embeds
Even with strict settings, I discovered multiple ways to inject unauthorized web addresses into iframes. While I wasn’t too worried about attacking myself, I wanted to properly secure my site. This led to a deep dive into custom saving and scrubbing methods to ensure that only specific, whitelisted domains were allowed for video embeds.
To test my setup, I ran my implementation through:
- PayloadBox's XSS Payload List
- Various test cases I generated with ChatGPT
- A few sneaky attacks I attempted myself
After rigorous testing, my solution held up, and I was pretty happy with the results!
Building the Blog and Project System
With a secure WYSIWYG in place, I moved on to structuring the blog and project models. I created the necessary Django apps and templates, built out the vision, and pieced together a dynamic content system that would allow me to manage everything from the admin panel easily.
Improving URL Structure
An enhancement I made was improving the blog URL structure. While only the blog ID is required, I set it up so that users can include the title in the URL for readability. All of these URLs point to the same blog post:
- https://isaachisey.com/blog/7/upgrading-my-website-using-django/
- https://isaachisey.com/blog/7
- https://isaachisey.com/blog/7/Jumping-Jehosephets
This way, the links remain user-friendly while keeping the core routing logic simple.
All of the above resolve to:
https://isaachisey.com/blog/7/upgrading-my-website-using-django/
Deployment Setup
Deployment required a few extra components and configuration tweaks:
- Gunicorn – Acting as the WSGI layer between Django and Nginx.
- python-env – Storing environment variables to keep secrets out of the codebase.
And now? The site is live and running at IsaacHisey.com!
Cloudflare Tunneling: No Open Ports Needed!
One of the most intriguing aspects of my deployment is that the machine hosting my website has no open ports. That’s right—none! So, how are you connecting and reading this blog post? Cloudflare Tunnel.
Initially, my ISP was making traditional hosting difficult, so I explored alternatives. Cloudflare’s tunneling service turned out to be the perfect solution. It allowed me to completely bypass the need for:
- Router configurations
- Static IP addressing
- Dynamic DNS updates
Now, all traffic securely routes through Cloudflare without exposing any ports on my server. You can learn more about how it works here.
Future Plans
This upgrade was far easier than I expected, and I now have a much more robust system in place. But I’m not stopping here!
Next on my roadmap:
- Adding search functionality for both the Blog and Projects pages
- Using HTMX and Django URLs to enable partial page updates (because let’s be real—no one likes full-page refreshes just to do a search!)
This journey into Django has been a fantastic experience, and I can’t wait to continue improving my site. Stay tuned for more updates!
Code
If you're interested in the code you can find it on my Github.