Building the front-end of a news site with form

Please login to bookmark Close

In this way, which people call development with Django templates (Django Template Engine) or Server-Side Rendering, the front-end and the backend are not separated. Django takes the data directly from the database and puts it inside HTML files that are written with its own special syntax (like {{ variable }} and {% tag %}). The final result is a complete HTML page that is sent to the browser of the user. In this architecture we do not need a separate API or a front-end framework, and everything is done in one single project. In this way, the logic of showing the data and reaching the data is fully handled on the server side, and the user only sees the final result.

In this part, with the way that we explained and with the html/css/js knowledge from the parts before, we finish the front-end of a real project. For this we follow the steps below.

  • First we get to know the existing project and what it can do.
  • Then I explain the features that we must build.
  • And at the end we start writing code.

Setting up the project

First download the backend of the project by clicking on the button below.

Backend files of the news site front-end project with form

Then, with cmd or Terminal, go into the folder where the manage.py file is. Then make a virtual environment with the command below.

python3 -m venv env
py -m venv env

Then activate it with the command below.

source env/bin/activate
envScriptsactivate

Then install the packages that you need with the command below.

pip install -r requirements.txt

Then make the database with the command below.

python manage.py migrate
py manage.py migrate

Then put some fake news into the database with the command below.

python manage.py import_news
py manage.py import_news

Then run the project with the command below.

python manage.py runserver
py manage.py runserver

If you need to go into the Django admin dashboard, use the command below to make a user. After that you can log in at localhost:8000/admin with the username and the password that you chose.

python manage.py createsuperuser
py manage.py createsuperuser

Getting to know the project

This project is a news site and its backend is built with Django. This part is easier for people who know the basics of Django, but if you know nothing about Django do not worry, because the parts that talk to Django are very simple.

This project has 5 main parts. Some of them are finished and some of them need to be finished.

1. News list page (home page)

A page that shows the list of all the news with pagination buttons to see more news. This page is at the address below.

localhost:8000

2. News detail page

A page to see the details of a news item, with edit and delete buttons. If the id of a news item is 350, you can go to this page with the address below.

localhost:8000/news/350

3. Add news page

A page with a form for adding news. It is not finished yet and right now it is empty. This page is at the address below.

localhost:8000/news/add

4. Edit news page

A page with a form for editing news. It is not finished yet and right now it is empty. If the id of a news item is 350, you can go to this page with the address below.

localhost:8000/news/edit/350

5. Delete news

There is no page for deleting news, but if the id of a news item is for example 350 and we send a POST request to the address below, that news item is deleted.

localhost:8000/news/delete/350

Task one – adding a search and filter form to the home page

Task one description

Build a search and filter form like the picture below.

Final home page of the news site project

For the search action send the word search, and for the filter action send the word category, with the GET method to the address of the same page. The values that category accepts are below.

  • Cultural
  • Political
  • Sports
  • Scientific

Doing task one

Open the index.html page and put the code below on line 14 of it.

<form class="toolbar" method="get">
    <input type="text" name="search" class="search-input" placeholder="Search by title...">
    <select name="category" class="filter-select">
        <option value="">All Categories</option>
        <option value="cultural">Cultural</option>
        <option value="political">Political</option>
        <option value="sports">Sports</option>
        <option value="scientific">Scientific</option>
    </select>
    <button type="submit" class="apply-btn">🔍 Apply Filters</button>
</form>

In the code above:

  • Line 14
    • Because the task says that the information must go to the backend with the GET method, we did not set the method attribute for this form, because by default this attribute is method="get".
    • Because the task says that the form must be sent to the address of the same page, we did not set the action attribute for this form, because its default value is action="" and this means that the form information goes to the page where we are right now.
  • Line 15: the field has name="search" , so when the form is submitted, the value of this field goes to the backend with the key search.
  • Lines 16 to 22: for the select field we set the attribute name="category" , so when the form is submitted, the value of the chosen option goes to the backend with the key category.
  • Line 23: by putting type="submit" on this field, we made it send the form information to the backend when somebody clicks on it.

Task two – building the delete news feature

Task two description

There is a delete button on the news detail page. Make it work, so when the user clicks on it, the news item is deleted.

Doing task two

Open the news-detail.html page and put the code below in the place of the code on lines 33 to 36.

<div style="margin-top: 1.5rem; display: flex; gap: 0.5rem; align-items: center;">
    <!-- Delete form (POST) -->
    <form action="http://localhost:8000/news/delete/{{ article.id }}/" method="post" style="display: inline;">
        <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
        <button type="submit" class="btn btn-danger">🗑 Delete This Article</button>
    </form>
    <!-- Edit link -->
    <a href="{% url 'edit_news' article.id %}" class="btn detail-btn">Edit</a>
</div>

In this code:

  • Line 35
    • We set the action attribute to say the address where the form information must go.
    • By putting method="post" we said that the information must go to the backend with the POST method.
  • Line 36: for more security, Django expects that every form that is submitted with the POST method has a hidden field like the one on this line. What this field is and how it helps the security is not the subject of this course, so I do not explain it. To make it easier, Django gives us a way to replace this line with {% csrf_token %}.
  • Line 37: there is a button for submitting the form.

With the note about csrf_token, we can make the code above better like below.

<div style="margin-top: 1.5rem; display: flex; gap: 0.5rem; align-items: center;">
    <!-- Delete form (POST) -->
    <form action="http://localhost:8000/news/delete/{{ article.id }}/" method="post" style="display: inline;">
        {% csrf_token %}
        <button type="submit" class="btn btn-danger">🗑 Delete This Article</button>
    </form>
    <!-- Edit link -->
    <a href="{% url 'edit_news' article.id %}" class="btn detail-btn">Edit</a>
</div>

Task three – building the add news page

Task three description

Build a form for adding news in add-edit-news.html, so the final result looks like the picture below. For this, use the information that comes after this.

Add news page in the news site project

The information that must go to the backend from this page with the POST method is below.

Field nameExpected valueRequiredDescription
titleStringYesThe title of the news
descriptionString (long)YesThe full text of the news
publish_dateString with the format YYYY-MM-DDYesThe publish date
categoryOne of the category keysYesThe chosen category (cultural, political, sports, scientific)
saveAsDraftThe string ‘on’ when the box is tickedNoIf the checkbox is on, the news is saved as a draft.
imageFile (optional)NoThe image of the news; when editing, if you send nothing, the old image stays.

Doing task three

Open the add-edit-news.html file and replace its line 11 with the code below.

<h2>📝 Add New Article</h2>
<form method="post" enctype="multipart/form-data">
    <div class="form-grid">
        <div class="form-group full-width">
            <label for="title">Title *</label>
            <input type="text" id="title" name="title" placeholder="Enter news title" required>
        </div>
        <div class="form-group full-width">
            <label for="desc">Description *</label>
            <textarea id="desc" name="description" placeholder="Full article text..." required></textarea>
        </div>
        <div class="form-group full-width">
            <label for="img">Image</label>
            <input type="file" id="img" name="image" accept="image/*">
        </div>
        <div class="form-group">
            <label for="date">Publish Date *</label>
            <input type="date" id="date" name="publish_date" required>
        </div>
        <div class="form-group">
            <label for="category">Category *</label>
            <select id="category" name="category" required>
                <option value="">-- Select --</option>
                <option value="cultural">Cultural</option>
                <option value="political">Political</option>
                <option value="sports">Sports</option>
                <option value="scientific">Scientific</option>
            </select>
        </div>
        <div class="form-group full-width">
            <label class="checkbox-wrap">
                <input type="checkbox" id="draft" name="saveAsDraft">
                Save as Draft
            </label>
        </div>
    </div>
    {% csrf_token %}
    <div class="form-actions">
        <button type="submit" class="btn btn-primary">💾 Save Article</button>
        <a href="/" class="btn btn-outline">Cancel</a>
    </div>
</form>

In the code above:

  • Line 12
    • By putting method="post" we made it possible to send the information with the POST method.
    • By putting enctype="multipart/form-data" we made it possible to send a file.
  • Line 16: by putting name="title" we send the title of the news to the backend with the key name.
  • Line 20: by putting name="description" we send the description of the news to the backend with the key description.
  • Line 24
    • By putting type="file" we made a file upload field.
    • By putting name="image" we send the file to the backend with the key image.
    • By putting accept="image/*" we let the user choose only images.
  • Line 28
    • By putting type="date" we turned on the date picker widget (a HTML5 feature) for this field.
    • By putting name=”publish_date”, we send the date to the backend with the key publish_date.
  • Line 32: in this part we used select to make a menu for choosing the news category, and we made the items of this menu with option.
    • By putting name="category" we send the chosen value to the backend with the key category.
    • The value of the option that is chosen when the form is submitted goes to the backend with the key category.
  • Line 42: by putting type="checkbox" we made an input of the checkbox type. If it is ticked, it sends the value on to the backend.
  • Line 47: we put a hidden field for sending the security token to the backend.
  • Line 49: By putting type="submit" we made a button for submitting the form and sending the information to the backend.

Task four – building the edit news form

Task four description

Add the edit feature to the form that you built before for adding news. For this, use the information below, which the backend gives you on this page.

VariableTypeDescription
articleA NewsArticle object or NoneIn edit mode it holds the news information; in the other case it is None.
categoriesA list of tuples (key, label)The category options; for example: [(‘cultural’,’cultural’), (‘political’,’political’), …]

Doing task four

Open the add-edit-news.html page and put the code below in it.

<h2>📝 {% if article.title %}{{ article.title }}{% else %}Add New Article{% endif %}</h2>
<form method="post" enctype="multipart/form-data">
    <div class="form-grid">
        <div class="form-group full-width">
            <label for="title">Title *</label>
            <input type="text" id="title" name="title" placeholder="Enter news title" required value="{{ article.title }}">
        </div>
        <div class="form-group full-width">
            <label for="desc">Description *</label>
            <textarea id="desc" name="description" placeholder="Full article text..." required>{{ article.description }}</textarea>
        </div>
        <div class="form-group full-width">
            <label for="img">Image</label>
            <input type="file" id="img" name="image" accept="image/*">
        </div>
        <div class="form-group">
            <label for="date">Publish Date *</label>
            <input type="date" id="date" name="publish_date" required value="{{ article.publish_date|date:'Y-m-d' }}">
        </div>
        <div class="form-group">
            <label for="category">Category *</label>
            <select id="category" name="category" required>
                <option value="">-- Select --</option>
                <option value="cultural" {% if article.category == "cultural" %}selected{% endif %}>Cultural</option>
                <option value="political" {% if article.category == "political" %}selected{% endif %}>Political</option>
                <option value="sports" {% if article.category == "sports" %}selected{% endif %}>Sports</option>
                <option value="scientific" {% if article.category == "scientific" %}selected{% endif %}>Scientific</option>
            </select>
        </div>
        <div class="form-group full-width">
            <label class="checkbox-wrap">
                <input type="checkbox" id="draft" name="saveAsDraft" {% if article.is_draft %}checked{% endif %}>
                Save as Draft
            </label>
        </div>
    </div>
    {% csrf_token %}
    <div class="form-actions">
        <button type="submit" class="btn btn-primary">💾 Save Article</button>
        <a href="/" class="btn btn-outline">Cancel</a>
    </div>
</form>

In the code above:

  • Line 11: in this part we added a condition, so the correct title of this part is shown. In add mode the user sees the words Add New Article, and in edit mode he sees the title of the news.
  • Line 16: with value="{{ article.title }}" we set the first value of this field.
  • Line 20: by putting {{ article.description }} between the textarea we set the first value of this field.
  • Line 28: in this part, by putting value="{{ article.publish_date|date:'Y-m-d' }}" we give the date of the news to the browser with the format YYYY-MM-DD and we set the first value of this field.
  • Lines 34 to 37: in this part we put the value selected on the category that was chosen before.
  • Line 42: in this part, if this field was ticked before, the value checked is set for it.

The problems of this method

Building the front-end with the old Django templates is really not an interesting job for a front-end developer. He must learn a big part of Django, and this gives him no work or technical benefit, so it is normal that he does not like it. The most important thing is that this way takes away the modern and advanced tools from him (like components, state management, Hot Reload and optimizing bundlers) and makes the development harder for him.

For a backend developer this way is also not logical. No backend developer wants to work this much with HTML, CSS and the details of the user interface. Instead of fighting with the view layer, they prefer to design a clean and standard API and leave the rest to the special front-end frameworks.

In the next part we will see how we can finish this project without touching the Django template layer, only with html/css/js. This way is much more interesting for a front-end developer than the way that we used in this part.

Please login to bookmark Close
نظرات

Leave a Reply

فهرست مطالب

سرفصل دوره

تمرین

این قسمت تمرین ندارد!

پاسخ تمرین ها

هنوز برای تمرین‌های این قسمت پاسخی ثبت نشده است!

اشتراک گذاری

Why we should use VPN?

I upload all CodeBaz videos and podcasts on platforms such as YouTube and SoundCloud, which are often restricted in Iran.

Most tutorials come with both video and podcast formats. Therefore, if you want to make the most out of the site’s content, you will need to use a VPN.

Please note that for shopping in the store, it’s better to turn off your VPN to avoid issues with payment and banking connections.

Settings

Language
Theme