Project1 - Wikipedia and First Look at Django
Tags: django, cs50w, webdev, backend
Published: 2021-01-31 12:00:08

>  * [ ▶️ Background](#background)  
>  * [ ▶️ Jumping into Project1](#jumping-into-project1)  
>  * [ 1️⃣ First Specification](#first-specification)  
>    * [ encyclopedia/views.py](#views)  
>    * [ encyclopedia/urls.py](#urls)  
>  * [ 2️⃣ Second Specification](#second-specification) 

After the HTML & CSS project0 of creating Google Search front-end, project1 is to design a Wikipedia-like online encyclopedia backend using Django.

## ▶️ Background <a name="background"></a>
The first impression on Django is surprisingly not as bad as I would have thought. I have used NodeJS and ReactJS before and frankly did had some skepticism towards the ease of use of Django. 

To my pleasant surprise, aside from a little getting used to Django isn't actually that convoluted. To be fair, I am used to using Python as that is my "day job" language. And I have to add on that the documentation of Django feels overwhelming with a lot of features. 

## ▶️ Jumping into Project1 <a name="jumping-into-project1"></a>
A little background before going into details of the 7 specifications required to complete this Wikipedia-like online encyclopedia project. The wiki pages are organized as individual markdown files with its filename as its title. Below is the directory overview:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/gtcwnd25018yd85jxd1t.png)

All the of files shown above are provided except for **entry.html & notfound.html which are colored green**. This GIF summarized what I had done so far:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/p0h75q6o3v3xppnz7ftj.gif)

In words, I had done the first two specifications which are as follows:

1. Entry Page: Visiting `/wiki/TITLE`, where `TITLE` is the title of an encyclopedia entry, should render a page that displays the contents of that encyclopedia entry.
    - The view should get the content of the encyclopedia entry by calling the appropriate util function.
    - If an entry is requested that does not exist, the user should be presented with an error page indicating that their requested page was not found.
    - If the entry does exist, the user should be presented with a page that displays the content of the entry. The title of the page should include the name of the entry.
2. Index Page: Update `index.html` such that, instead of merely listing the names of all pages in the encyclopedia, user can click on any entry name to be taken directly to that entry page.

### 1️⃣ First Specification <a name="first-specification"></a>
In order to display the correct entry when `/wiki/TITLE` is requested:
* `views.py` needs to handle the request
* `urls.py` of the encyclopedia app need to route to the correct function in the `views.py`

#### encyclopedia/views.py <a name="views"></a>
Here, the [markdown2 python package](https://github.com/trentm/python-markdown2) is used to convert the markdown wiki entries which are then rendered as `entry.html`.
```py
# encyclopedia/views.py

import markdown2
# ...
def topic(request, title):
    mdStr = util.get_entry(title)
    if mdStr:
        html = markdown2.markdown(mdStr)
        return render(request, "encyclopedia/entry.html", {
            "title": title,
            "content": html
        })
    else:
        return render(request, "encyclopedia/notfound.html", {
            "message": f"Error: Wiki page titled '{title}' not found"
        })
# ...
```

#### encyclopedia/urls.py <a name="urls"></a>
```py
# encyclopedia/urls.py
# ...
urlpatterns = [
    # ...
    path("wiki/<str:title>/", views.topic, name="topic"),
    # ...
]
```

### 2️⃣ Second Specification <a name="second-specification"></a>
The second specification is much more straight forward, [this documentation example](https://docs.djangoproject.com/en/3.0/topics/http/urls/#examples) in Django shows how to create an anchor link in HTML that automatically uses the `topic` route we specified in `urls.py`.

Showing the example from the documentation for better illustration:
```py
from django.urls import path

from . import views

urlpatterns = [
    #...
    path('articles/<int:year>/', views.year_archive, name='news-year-archive'),
    #...
]
```
In the HTML template code:
```html
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>
```

That's all for this post! It's more lengthy this time as I thought of sharing in more details of what I had learnt. Hopefully it's helpful and feel free to discuss any improvements or how easy this can be achieved using any other languages 😉