How to make CMS with Django ?
Tags: django, python, webdev, backend
Published: 2022-02-01 13:22:41

Hello all dev.to community, 
I hope that you receive my post in a good health in a good conditions.
Today we are going to make a CMS(Content Management System) with Django and that covers all the CRUD(Create, Read, Update, Delete) operations and how to do them with Django, and you will see how easy it is.

> If you don't like reading, check my video on my YouTube Channel : https://youtu.be/H_iW3Z2ozYE

> You can find the final code for this project here : https://github.com/yassercher/CRUD-Django

Enough talk, let's start coding...
First of all we create our project and let's name it **crud**:

```shell
django-admin startproject crud
```
Then we create our first app:

```shell
cd crud
```

```
py manage.py startapp main
```
Now as you see I have named our app **main**, then we should go to _crud/settings.py_ and declare it inside **INSTALLED_APPS** list variable like this:

```python
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'main' #add this line 
]
```
Now our projects knows that we have an app called main and it should call it whenever we run the server.
First of all we create our first model **Post**:
_crud/main/models.py_

```python
from django.db import models

# Create your models here.


class Post(models.Model):
    title = models.CharField(max_length=255, blank=False, null=False)
    content = models.TextField(blank=False, null=False)

    def __str__(self):
        return self.title

```
And then we make our URL paths,
_crud/main/urls.py _

```python
from django.urls import path
from .views import index, read, create, delete, update
app_name = 'main'


urlpatterns = [
    path('', index, name='index'),
    path('create/', create, name='create'),
    path('update/<int:post_id>', update, name='update'),
    path('read/<int:post_id>', read, name='read'),
    path('delete/<int:post_id>', delete, name='delete'),
]

```
Then we need to include them in _crud/urls.py_:

```python
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('main.urls'))
]

```
For now we code the views: 
_crud/main/views.py_

```python
from django.http import HttpResponse
from django.shortcuts import redirect, render
from .models import Post
# Create your views here.


def index(request):
    data = Post.objects.all()
    return render(request=request, template_name='main/index.html', context={'data': data})


def read(request, post_id):
    if post_id:
        post = Post.objects.filter(pk=post_id)

    return render(request=request, template_name='main/read.html', context={'post': post.get()})


def update(request, post_id):
    if post_id:
        post = Post.objects.filter(pk=post_id)
    if request.POST:
        n_t = request.POST['title']
        n_c = request.POST['content']
        post.update(title=n_t, content=n_c)
        return redirect('/')
    return render(request=request, template_name='main/update.html', context={'post': post.get()})


def delete(request, post_id):
    if post_id:
        p = Post.objects.filter(pk=post_id)
        p.delete()
        return HttpResponse('Post has been successfully deleted')
    return HttpResponse('insert a post id to delete')


def create(request):
    if request.POST:
        title = request.POST['title']
        content = request.POST['content']
        Post.objects.create(title=title, content=content)
        return redirect('/')
    return render(request=request, template_name='main/create.html', context={})

```
So far we have worked only on the backend, we should make our frontend now:

1. Create a directory on _/main/_ with the name _templates_.
2. Create a subdirectory with the name _main_.
3. Create four HTML files: _index.html, create.html, read.html, update.html_
Now paste the code there: 
_crud/main/templates/main/index.html_
```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css"
    />
    <title>CRUD Project</title>
  </head>
  <body>
    <h1 class="title is-2">Welcome to the CRUD Project</h1>
    {% for post in data %}
    <div class="card">
      <header class="card-header">
        <p class="card-header-title">{{post.title}}</p>
        <button class="card-header-icon" aria-label="more options">
          <span class="icon">
            <i class="fas fa-angle-down" aria-hidden="true"></i>
          </span>
        </button>
      </header>
      <div class="card-content">
        <div class="content">{{post.content}}</div>
      </div>
      <footer class="card-footer">
        <a href="{% url 'main:read' post.id %}" class="card-footer-item"
          >Read</a
        >
        <a href="{% url 'main:update' post.id %}" class="card-footer-item"
          >Update</a
        >
        <a href="{% url 'main:delete' post.id %}" class="card-footer-item"
          >Delete</a
        >
      </footer>
    </div>
    {% endfor %}
  </body>
</html>

```
_crud/main/templates/main/create.html_

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css"
    />
    <title>Create a new Post</title>
  </head>
  <body>
    <h1 class="title is-3">Create a new post</h1>
    <form method="POST">
      {% csrf_token %}
      <div class="field">
        <label class="label">Title</label>
        <div class="control">
          <input
            class="input"
            type="text"
            placeholder="Text input"
            name="title"
          />
        </div>
      </div>

      <div class="field">
        <label class="label">Content</label>
        <div class="control">
          <textarea
            class="textarea"
            placeholder="Textarea"
            name="content"
          ></textarea>
        </div>
      </div>

      <div class="field is-grouped">
        <div class="control">
          <button class="button is-link">Submit</button>
        </div>
        <div class="control">
          <button class="button is-link is-light">Cancel</button>
        </div>
      </div>
    </form>
  </body>
</html>

```
_crud/main/templates/main/update.html_

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css"
    />
    <title>Update Post</title>
  </head>
  <body>
    <h1 class="title is-3">Update Post</h1>
    <form method="POST">
      {% csrf_token %}
      <div class="field">
        <label class="label">Title</label>
        <div class="control">
          <input
            class="input"
            type="text"
            placeholder="Text input"
            name="title"
            value="{{post.title}}"
          />
        </div>
      </div>

      <div class="field">
        <label class="label">Content</label>
        <div class="control">
          <textarea class="textarea" placeholder="Textarea" name="content">
{{post.content}}
        </textarea
          >
        </div>
      </div>

      <div class="field is-grouped">
        <div class="control">
          <button class="button is-link" type="submit">Update</button>
        </div>
        <div class="control">
          <button class="button is-link is-light">Cancel</button>
        </div>
      </div>
    </form>
  </body>
</html>

```
_crud/main/templates/main/read.html_

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Read Post {{post.id}}</title>
  </head>
  <body>
    <h1>{{post.title}}</h1>
    <p>{{post.content}}</p>
  </body>
</html>
```
Now all what we have to do is to make migrations so that the database creates new tables for our models, and then apply them: 

```
py manage.py makemigrations
```

```
py manage.py migrate
```
Finally run the server and that's it :) 

```
py manage.py runserver
```
That was everything for today, thank you so much for your time if you like the post, give it a like and follow me for more content like this.