How to Build a Book Review App Using Django

How to Build a Book Review App Using Django

Project setup

To first begin we need to create our Django project. To do so run the command below in your terminal.

django-admin startproject django_book_review

The above command creates a folder called django_book_review , now cd into the directory and run the command below to create our application.

python3 manage.py startapp book_review

Now let’s register our application to our project, to do so go to the settings.py file in the installed_apps and add the following code.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'book_review',
]

Create models

Now in the book_review folder create the following models in the models.py file.

from django.db import models
from django.utils import timezone


class Book(models.Model):
    title = models.CharField(max_length=50)
    description = models.TextField(max_length=5000)
    upload_date = models.DateTimeField(default=timezone.now)
    book_cover = models.FileField(upload_to='')


    def __str__(self):
        return self.title 



class Review(models.Model):
    user = models.CharField(max_length=40)
    review_date = models.DateTimeField(default=timezone.now)
    rate_choices = (
        (1,1),
        (2,2),
        (3,3),
        (4,4),
        (5,5)
    )
    stars = models.IntegerField(choices=rate_choices)
    comment = models.TextField(max_length=4000)
    book = models.ForeignKey(Book, on_delete=models.CASCADE)
    
    def __str__(self):
        return self.book.title
    
    

Our application has two models one for the book and review , since our book model will need a photo to be uploaded we need to configure our settings.py file as shown below.

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

Create views

Now let’s create our views inside the views.py file as shown below.

from django.shortcuts import render, redirect
from . models import Review ,Book


def list_books(request):
    items = Book.objects.all()
    context = {
        'items':items
    }
    return render(request, "book_review/home.html",context)


def review_book(request,id):
    post = Book.objects.get(id=id)
    if request.method == "POST":
        user = request.POST.get('user')
        stars = request.POST.get('stars')
        comment = request.POST.get('comment')
        review = Review(user=user, stars=stars,comment=comment,book=post)
        review.save()
        return redirect('success')

    return render(request, 'book_review/index.html')


def success(request):
    return render(request, "book_review/success.html")

Now in the view above we create a view to list all the books available in our catalogue for review. Next, we create a view to review the book, for this, we first get the user, the star rating, and a comment, and then we are redirected to a success page if the review was successful.

Register models to the admin dashboard

Now we need to register our models to the admin dashboard, to do so go to the admin.py file and add the following code below.

from django.contrib import admin
from . models import Book,Review 




class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'description', 'upload_date','book_cover')


class ReviewAdmin(admin.ModelAdmin):
    list_display = ('user', 'review_date', 'stars','comment')

admin.site.register(Book, BookAdmin)
admin.site.register(Review, ReviewAdmin)

Create templates

Now we need templates for our project. To do so let’s create a folder called templates and inside it create a folder called book_review and inside it create the following files. home.html , index.html and success.html

Inside the home.html insert the code below.

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Book List</title>
</head>
<body>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body {
            background-color: #f1f1f1;
            font-family: Arial, sans-serif;
        }

        .container {
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }

        h1 {
            margin-bottom: 20px;
            text-align: center;
        }

        ul {
            list-style: none;
        }

        .book {
            background-color: #fff;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
            margin-bottom: 20px;
            display: flex;
            align-items: center;
            padding: 20px;
        }

        .book-cover {
            max-width: 200px;
            margin-right: 20px;
        }

        .book-info h2 {
            font-size: 24px;
            margin-bottom: 10px;
        }

        .book-info p {
            font-size: 14px;
            margin-bottom: 5px;
            line-height: 1.5;
        }
        .rate_button {
            text-decoration: none;
            color: green;
        }

    </style>
    <div class="container">
        <h1>Book List</h1>
        <ul>
            {% for book in items %}
                <li class="book">
                    <img src="{{ book.book_cover.url }}" alt="{{ book.title }}" class="book-cover">
                    <div class="book-info">
                        <h2>{{ book.title }}</h2>
                        <p>{{ book.description }}</p>
                        <p>Uploaded: {{ book.upload_date }}</p>
                        <button class="rate_button"><a href="{% url 'review_book' book.id %}">RATE NOW</a></button>
                    </div>
                </li>
            {% endfor %}
        </ul>
    </div>
</body>
</html>

Next let’s create our review template, inside the index.html file insert the following.

<!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>Document</title>
</head>
<body>
    <style>
        .container {
            text-align: center;
        }
        fieldset.rating {
        border: none;
        margin: 0;
        padding: 0;
        display: inline;
        }

        .rating input[type="radio"] {
        display: none;
        }

        .rating label:before {
        content: "\f005";
        font-family: FontAwesome;
        font-size: 1.5em;
        color: #ccc;
        cursor: pointer;
        }

        .rating label:hover:before,
        .rating label:hover ~ label:before,
        .rating input[type="radio"]:checked ~ label:before {
        color: #FFD700;
        }

        button[type="submit"] {
        margin-top: 10px;
        background-color: #4CAF50;
        color: white;
        padding: 10px 20px;
        border: none;
        border-radius: 3px;
        cursor: pointer;
        }

    </style>
    <div class="container">
        <form method="POST">
            {% csrf_token %}
            <div>
                <h3>Book Review</h3>
                <input type="text" name="user" id="user" placeholder="Enter your name" required>
            </div>
            <fieldset class="rating">
                <input type="radio" id="star5" name="stars" value="5" /><label for="star5" title="5 stars"></label>
                <input type="radio" id="star4" name="stars" value="4" /><label for="star4" title="4 stars"></label>
                <input type="radio" id="star3" name="stars" value="3" /><label for="star3" title="3 stars"></label>
                <input type="radio" id="star2" name="stars" value="2" /><label for="star2" title="2 stars"></label>
                <input type="radio" id="star1" name="stars" value="1" /><label for="star1" title="1 star"></label>
            </fieldset>
            <div>
                <textarea name="comment" id="comment" cols="30" rows="10" placeholder="Enter your comment here" required></textarea>
            </div>
            <button type="submit">Submit</button>
        </form>
    </div>
</body>
</html>

Lastly is our success page, insert the code below in the success.html file.

<!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>Document</title>
</head>
<body>
    <style>
        div{
            text-align: center;
        }
    </style>
    <div>
        <h1>Success</h1>
        <p>Thanks for reviewing this book</p>
    </div>
</body>
</html>

Create app routes

Now let’s create routes for our application, inside the book_review folder create a file called urls.py and insert the code below.

from django.urls import path
from . import views



urlpatterns = [
    path('',views.list_books, name="list-bokos"),
    path('review_book/<int:id>',views.review_book,name="review_book"),
    path('success',views.success, name="success"),
]

Create project routes

Now let’s make our application visible to our project, to do so add the following code to the urls.py file inside the django_book_review folder.

from django.contrib import admin
from django.conf import settings
from  django.conf.urls.static import static 
from django.urls import path,include 

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



if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Create database

Now we need to create a database for our application, to do so run the following commands in your terminal.

python3 manage.py makemigrations

Next, run the following command to migrate the data.

python3 manage.py migrate.

This should make all the necessary databases. Next we need to create our admin profile. Now run the command below to create the admin profile where you will be asked to create a username,email and password.

python3 manage.py createsuperuser

After creating the admin start the server as shown below.

python3 manage.py runserver

Upload books

Now open the admin page at the address [ http://127.0.0.1:8000/admin ] and log in with the credentials you created and then upload the book you need for review as shown below.

Our book is now available for review as shown below.

There you have it, Thanks for reading. Happy Coding.

Leave a Comment

Your email address will not be published. Required fields are marked *