CS50’s Web Programming with Python and JavaScript: Django and ‘Wiki’ Project

Ross P. Coron
7 min readMar 3, 2022

--

This is part two of a six-part series tracking my progress through Harvard University’s CS50W (Web Programming with Python and JavaScript) programming course.

This entry covers week 4 and the ‘Wiki’ project. For a video walkthrough of my solution to the project, click HERE. My previous entry in this series can be found HERE; the next can be found HERE.

Last week’s lecture culminated in ‘Search’, a re-implementation of Google search, image search, and advanced search. Sleek and functional, yes; but also static. Unlike modern websites, such as BBC news and Facebook, the project viewed today would appear identical to how it appeared the day before. Moving beyond static webpages, this week we learned how to design and implement dynamically generated websites using the Python framework, Django.

Django

HTTP

Before covering Django itself, we first learned one of the world wide web’s fundamentals - HyperText Transfer Protocol (HTTP). HTTP is a ubiquitous method for transferring data back and forth across the internet, typically between a client (i.e. a user) and a server.

In this convention, a client submits a request to a URL address (hosted on a server) which responds with a response code (common examples include 200 OK and 404 NOT FOUND) followed by HTML content to be rendered in the user’s web browser.

Django

Now familiar with the theory of how data is shuttled back and forth between server and user, we moved onto Django - a web framework which allows users to rapidly build dynamic websites without having to worry about the fiddlier aspects of web development. Moving beyond our previous Search website where we (almost) wrote every line of code ourselves, Django allows users to generate HTML and CSS programmatically using the Python language.

In just four Terminal commands (three excluding Django’s installation), we had the bare skeleton of a website - hosted locally on a development server; rendered in our browser; and supported by a (mostly hidden) intricate web of underpinning files and directories.

Routes

Fundamental to a Django project is the file views.py. Somewhat misleadingly named, views.py contains the majority of our Python code, primarily functions. At their most simple, these functions accept a Request object, do something with some data, and return an HttpResponse - a response code (hopefully 200 OK) followed by a string of text. It is this response, or alternatively, a returned HTML file, which is ultimately viewed by the user in a web browser.

But a website is not a text editor, how do we call these functions? The answer is by tying them to URLs, calling a specific function when a predefined URL is visited by a user. In practise, this mapping of URLs to functions is described in the file urls.py. Each item in this file contains two or three parameters: a string representing a URL’s path, the function we wish to call when the URL is visited, and (optionally) a name for the path.

Django installed, project created, server running, function defined, and URL pattern described, we were able to render our very first Hello, World! in Django.

By hard coding multiple URL paths, we can serve up different web pages in response to visiting different URLs. This may work well when we have just two or three webpages but consider a website like Facebook with billions of users. To make a more flexible path, we learned how to write functions which accept not just a request object but also an additional argument, taken from the URL address itself.

Templates

So far, our test websites had only rendered unformatted text written as strings sandwiched between quotation marks in our views.py file. Akin to an incredibly convoluted Python print() function, this presented two limitations: rendering a string isn’t particularly dynamic and it feels somewhat messy to hard code HTML in the midst of Python code. Better to sequester content and design in one part of a website’s backend and our computational code (IF, WHILE, FOR, etc.) in another part.

Enter Django templates, a way to render HTML and CSS code saved outside of our Python functions (typically in an appropriately named ‘templates’ directory). Powerfully, we can use Django to dynamically change the content of our template files, passing in data (known as content) upon returning a rendered HTML file at the end of a function. Exactly what data is up to the user: strings (names?), numbers (dates?), objects (interactive forms?)

Conditionals

But Django’s templating goes well-beyond dynamically converting Hello, World! into Hello, {{ user }}! Using the Django framework, we can now give our HTML files the ability to use conditional arguments: IF statements, FOR loops, and boolean arguments. In short, templates give our webpages not just the ability to display content, but do something with it.

Forms, Tokens, and Sessions

We ended the lecture by implementing an online to do list. This app introduced a number of new Django features. One useful feature was layout files - files containing HTML code otherwise repeated across multiple pages (such as header blocks and basic styling). We additionally expanded our HTTP method vocabulary, from GET requests only to POST requests as well. Unlike GET (a common method to request data from a server), POST is used to send data to a server to create or update a resource. In the to do list example, GET is used to read the to do list, whereas POST is used to add or remove things from it.

We finished the lecture with two topics which, although less fundamental programmatically speaking (and somewhat duller…) will clearly be important as our websites grow in size, moving from our machines to public servers: Cross-Site Request Forgery (CSRF) tokens and sessions. CSRF tokens are hidden input fields in webforms, preventing malicious users from sending requests to a server from a location other than your site. In a similar security / privacy vein, sessions are a way of storing unique data about a website’s visitors, server-side. This can be done with several purposes in mind: from serving up personalised web ads to preventing your online to do list being shared with every other user of the same website!

Video walkthrough of my implementation of CS50W’s ‘Search’ project

Project 1: Wiki

Description

For CS50W’s second project we were tasked with re-implementing Wikipedia using Python and the Django framework. Like the real Wikipedia, our website was to contain a number of individual entries; the ability to edit and create entirely new pages; and a search functionality. Helpfully, the project’s distribution files provided a sparse but stable foundation: a Django project file structure, some template files, and a few helper functions on which to call.

Approach

As with previous CS50 assignments, I tackled the project’s requirements one by one, implementing the most basic version of a requirement (often in small standalone test files) before developing further. One example of this was ensuring I could programatically determine if a word was present in a list of strings before implementing a full search function. Unlike previous PSETs, I ended up with multiple versions of my project, ultimately finding it easier on occasion to start over from scratch than ctlr-zing myself back to a stable, functional version of my site.

Learnings

While I gained a great deal of practical experience working with Django in this project, I additionally learned a lot beyond the framework. I learned how to call functions stored elsewhere in a project and written by someone else; abstracting away from the line-to-line detail of the code and focussing purely on its function. Unlike other projects, particularly those written in C, I found myself spending a similar amount of time knitting together code written by others as I did writing my own. Going well beyond fundamental programming concepts, I additionally found myself consulting Stack Exchange and documentation more than I had ever done in the past.

As somewhat of a perfectionist (I know, not very conducive for web programming where a div can be moved a single pixel…), I also took great pleasure in finding hack-y workaround to small issues in the project’s source code: hiding overflow in CSS for example to prevent the page moving ever so slightly when text was input; changing a form’s width to 98% to prevent it extending beyond the screen’s edge. These fixes didn’t make or break my implementation but it did make it more pleasant to interact with.

Challenges

Although now more comfortable writing Django apps, my understanding of the framework remains incomplete. Incomplete because I’m aware I’ve only explored a fraction of its functionality but also because I’m still not exactly sure how Django fundamentally… works. Unlike previous code read from top to bottom, Django feels (to me at least) very circular, very three-part chicken and egg: a user visits a URL which calls a function which renders an HTML page which contains a form which is submitted to a URL which calls a function which… Often, I’d find my code breaking down, with trying to fix an error in one place creating two in another. Although I didn’t use it in this assignment, this project has demonstrated to me the immense power of Git version control. I’ll force myself to use it for the next project (…maybe).

I’m particularly conscious that I will have to do some additional reading on Django’s templating syntax and how URLs are generated using the framework. I acutely felt this when implementing the project’s edit specification: dynamically generated URLs, GET and POST requests, passing values into forms AND HTML pages, and extracting user input from a form. Regardless, I submitted my project’s code with a far better understanding of Django than I did typing in my first django-admin startproject command. I’m confident one more project with the Framework will solidify this understanding.

Regardless, on to the next one!

--

--

Ross P. Coron

Rehabilitated academic. I enjoy solving complex problems with pipettes, programming, and policy. Twitter: @Ross_Coron; LinkedIn: www.linkedin.com/in/ross-coron/