DEV Community

JMG
JMG

Posted on

Simple Django CRUD App

Hello, if you are just beginning to learn Django, this is a good example of simple CRUD (Create Retrieve Update and Delete) operations.
In this tutorial, we are going to create a simple application that allows us to create, retrieve, update and delete a student.

Steps

1.Create new project
2.Create the models
3.Create a form
4.Add templates folder
5.Create the views

1.Create new project

Create a new django project (preferably in a virtual environment) using django-admin startproject students-crud
proceed to create an app students using python manage.py startapp students.
Register the app in your settings.py file.

2.Create the models

We are going to have 2 models, Stream model and Student model.
Register the app in your settings.py file.
Open your students app's models.py file. This is where we will create our models, using the code below:

class Stream(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return f'{self.name}'

class Student(models.Model):
    name = models.CharField(max_length= 50)
    description = models.TextField()
    joindate = models.DateTimeField(auto_now_add = True)
    reg_no = models.CharField(max_length=100, unique=True)
    stream = models.ForeignKey(Stream, on_delete=models.CASCADE, 
             related_name="students")


    def __str__(self):
        return f'{self.name} reg {self.reg_no}' 

Enter fullscreen mode Exit fullscreen mode

Navigate to admin.py and register your 2 models as follows:

from students.models import Student, Stream
# Register your models here.
admin.site.register(Student)
admin.site.register(Stream)
Enter fullscreen mode Exit fullscreen mode

3.Create a form

In your app's folder, create a new file and name it forms.py.
Add the following code to your file:

from django import forms
from .models import Student 


class CreateStudentForm(forms.ModelForm):

    class Meta:
        model = Student
        fields = "__all__"
Enter fullscreen mode Exit fullscreen mode

4.Create a folder for our templates

To make it easier to access our templates, we shall create a single folder named templates that will contain all of our templates.
Navigate to your settings.py , locate your Templates array and replace it with the following:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
Enter fullscreen mode Exit fullscreen mode

Navigate to the root folder of your project and create a folder named templates

5.Create Views

Navigate to your views.py file and we'll start writing code.
We are going to use function based views for this.

First, we create a view to create a student instance (object).
This will also be the view for our landing page.
To do this, we need to import the form we created in forms.py.
Include this import from .forms import CreateStudentForm
Here now goes the view:

def CreateStudent(request):
    if request.method == "POST":
        form = CreateStudentForm(request.POST)
        if form.is_valid():
            form.save()
            form = CreateStudentForm()
    else:
        form = CreateStudentForm()

    students = Student.objects.all().order_by("-id")
    context = {'form':form, 'students':students}
    return render(request, 'home.html', context)
Enter fullscreen mode Exit fullscreen mode

We want to display our students starting with the last added, hence order_by("-id") in
students = Student.objects.all().order_by("-id")

Create a file index.html in the templates we created in the previous step.
This template will show a form for creating new students and also list the existing students in a table.
For each student instance or record, you will be able to view or delete it.
I have added bootstrap to it to make it look better.
Your index.html should be like this:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
        integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
        integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
        crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx"
        crossorigin="anonymous"></script>
    <title>Good Schools | Home</title>
</head>

<body>
  <div>
      <form method="post">
            {% csrf_token %} 
            {{form.as_p}}
            <button type="submit">Submit</button>
      </form>
  </div>
        <!-- list of students  -->
        <div>
            <h4 class="text-center mb-3 mt-3">Students List</h4>
            <div class="table-responsive-sm">
                <table class="table table-hover">
                    <thead class="thead-light">
                        <tr>
                            <th scope="col">Name</th>
                            <th scope="col">Reg No.</th>
                            <th scope="col">Stream</th>
                            <th scope="col">Description</th>
                            <th scope="col">Join Date</th>
                            <th scope="col">View</th>
                            <th scope="col">Delete</th>
                        </tr>
                    </thead>
                    <tbody>
                        {% for student in students %}
                        <tr>
                            <td class="text-capitalize">{{student.name}}</td>
                            <td>{{student.reg_no}}</td>
                            <td>{{student.stream}}</td>
                            <td class="text-capitalize">{{student.description}}</td>
                            <td>{{student.joindate}}</td>
                            <td>
                                <a role="button" class="btn btn-sm btn-outline-success"
                                    href="{% url 'std_detail' reg=student.reg_no %}">View</a>
                            </td>
                            <td>
                                <a role="button" class="btn btn-sm btn-outline-danger" href="{% url 'delete' id=student.id %}">Delete</a>
                                <!-- <button class="btn btn-sm btn-outline-danger">Delete</button></td> -->
                        </tr>
                        {% empty %}
                        <span class="text-center">No students to show</span>
                        {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
</body>
Enter fullscreen mode Exit fullscreen mode

As mentioned above, we want to view a specific student.
To achieve this, we need to create another view.
We are going to fetch a student from the database by using their reg_no as used in our Student model.

This same view will be used to update a student instance, hence passing the student instance will pre-populate the form.

def GetStudent(request, **kwargs):
    reg = kwargs.get('reg')
    student = get_object_or_404(Student, reg_no=reg)

    if request.method == "POST":
        form = CreateStudentForm(request.POST, instance=student)
        if form.is_valid():
            form.save()
    else:
        form = CreateStudentForm(instance=student)

    context = {'student':student, 'form': form}
    return render(request, 'std_detail.html', context )
Enter fullscreen mode Exit fullscreen mode

Our std_detail.html will look like this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>

    <title>Good Schools | Student Detail | {{student.reg_no}}</title>
  </head>
  <body>
    <div class="big-box container-fluid d-flex justify-content-center align-items-center">
        <div class="container mt-4 mb-5">
            <h4 class="text-center text-capitalize">{{student.name}}'s Profile</h4>
            <form class="mt-3" method="post">
                {% csrf_token %}
                  <div class="form-group">
                      <div class="row">
                          <div class="col">
                            <label>Name:</label>
                              {{form.name}}
                          </div>
                      </div>
                  </div>
                  <div class="form-group">
                      <div class="row">
                          <div class="col">
                            <label>Reg No.</label>
                              {{form.reg_no}}
                          </div>
                          <div class="col">
                            <label>Stream:</label>
                              {{form.stream}}
                          </div>
                      </div>
                  </div>
                  <div class="form-group">
                    <label>Description:</label>
                      {{form.description}}
                  </div>
                  <div class="form-group">
                      <div class="row">
                        <div class="col d-flex justify-content-center">
                          <button class="btn btn-warning btn-block text-white w-50">Update</button>
                        </div>
                        <div class="col d-flex justify-content-center">
                          <a href="{% url 'delete' id=student.id %}" role="button" class="btn btn-danger btn-block text-white w-50">Delete</a>
                        </div>
                      </div>
                  </div>
            </form>
        </div>
    </div>
    <div class="container d-flex justify-content-center">
      <a href="{% url 'create_student' %}" role="button" class="btn btn-outline-primary btn-block w-25">All Students</a>
    </div>
  </body>
</html>

Enter fullscreen mode Exit fullscreen mode

To delete a student, we will also use their reg_no to fetch them, then proceed to delete them.
Here is the view:

def DeleteStudent(request, **kwargs):
    reg = kwargs.get('reg')
    student = Student.objects.get(reg_no=reg)
    student.delete()
    return redirect('home')
Enter fullscreen mode Exit fullscreen mode

We now need to define our urls so that we can view and access what we have done.
Create a urls.py file in your app and include the following:

from django.urls import path
from .views import CreateStudent,GetStudent, Delete

urlpatterns = [
    path('', CreateStudent, name='create_student'),
    path('std_detail/<str:reg>/', GetStudent, name='std_detail'),
    path('delete/<int:id>', Delete, name='delete'),
Enter fullscreen mode Exit fullscreen mode

Head to your project's url.py and add the following:


from django.urls import path,include
urlpatterns = [
    path('', include("home.urls")),
    path('admin/', admin.site.urls),
]

Enter fullscreen mode Exit fullscreen mode

That's it! Migrate your project and run your server.
You now have your simple CRUD application.

Top comments (0)