#books/urls.py
from django.urls import path
app_name = 'books'
urlpatterns = [
 
]
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('books.urls', namespace='books'))
]
    
- Next we create a models for book:
from django.contrib.auth.models import User
from django.db import models
from taggit.managers import TaggableManager
from cloudinary.models import CloudinaryField
class Book(models.Model):
    title = models.CharField(max_length=255)
    image = CloudinaryField('image')
    description = models.CharField(max_length=1000)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    tags = TaggableManager()
    updated = models.DateTimeField(auto_now_add=True)
    def __str__(self):
        return self.title
#books/views.py 
from django.shortcuts import get_object_or_404, render, redirect
from taggit.models import Tag
from books.models import Book
from .forms import BookForm
def home(request, pk=None):
    tag_obj = None
    if not pk:
        books = Book.objects.all()
    else:
        tag_obj = get_object_or_404(Tag, pk=pk)
        books = Book.objects.filter(tags__in=[tag_obj])
    return render(request, 'home.html', {
        'tag': tag_obj,
        'books': books
    })
def create(request, *args, **kwargs):
    if request.method == 'POST':
        form = BookForm(request.POST, request.FILES)
        if form.is_valid():
            book = form.save(commit=False)
            book.author = request.user
            form.save()
            return redirect('books:home')
    else:
        form = BookForm()
        return render(request, 'create.html', {
            "form": form
        })
#books/urls.py
from django.urls import path
from .views import home, create
app_name = 'books'
urlpatterns = [
  path('', home, name='home'),
  path('tag/<str:pk>', home, name="books_tag"),
  path('create', create, name="create" )
]
- Now we setup templates and config cloudinary api in settings
Template Setup:
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Hello Bulma!</title>
    <link rel="stylesheet"  
href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
    <script defer 
 src="https://use.fontawesome.com/releases/v5.14.0/js/all.js"></script>
   <style type="text/css" media="screen">
      body {
        display: flex;
        min-height: 100vh;
        flex-direction: column;
        background-color: info
      }
      #wrapper {
        flex: 1;
      }
    </style>
  </head>
  <body class="has-background-light">
  {% include 'nav.html' %}
  <section class="section">
    <div class="container is-link">
      {% block content %}
            
      {% endblock content %}
    </div>
  </section>
  </body>
</html>
{% extends 'base.html' %}
    {% load cloudinary %} 
 {% block content %}
<h1 class="title">Tag-Me</h1>
<p>Books tagged with <strong>{{ tag.name }}</strong></p>
<div class="columns is-mobile mt-5">
  <div class="column is-half is-offset-one-quarter">
    {% for book in books %}
    <div class="card mt-3">
    
      <div class="card-content">
        <div class="media">
          <div class="media-left">
            <figure class="image is-128x128">
              <img
                src={{book.image.url}}
                alt="Placeholder image"
              />
            </figure>
          </div>
          <div class="media-content">
            {% if book.author%}
            <p class="title is-4">{{ book.author }}</p>
            <p class="subtitle">{{ book.title }}</p>
            {% endif %}
          </div>
        </div>
        <div class="content">
          {{ book.description }} {% if book.tags %}
          <div class="tags">
            {% for tag in book.tags.all %}
            <a href="{% url 'books:books_tag' tag.pk %}">{{ tag }}   
</a>
            {% endfor %}
          </div>
          {% endif %}
          <br />
          <time datetime="2016-1-1"
            ><p>{{ book.updated|date:"M j, Y" }}</p></time
          >
        </div>
      </div>
    </div>
    <p></p>
    {% endfor %}
  </div>
</div>
{% endblock content %}
{% extends 'base.html' %} {% block content %}
<div class="columns is-mobile mt-5">
  <div class="column is-half is-offset-one-quarter ">
    <form
      action="{% url 'books:create' %}"
      method="post"
      enctype="multipart/form-data"
    >
    <p class="title">CREATE BOOK</p>
      <div class="box">
        {% csrf_token %}
      <div class="field">
        <label class="label">Title</label>
        <div class="control">
          <input
            class="input"
            type="text"
            name="title"
            placeholder="Book Title"
          />
        </div>
        {% for err in form.title.errors %}
        <small class="is-danger">{{err}}</small>
        {% endfor %}
      </div>
      <div class="field">
        <label class="label">Description</label>
        <div class="control">
          <input
            class="input"
            name="description"
            type="text"
            placeholder="Book Descriptions"
          />
        </div>
        {% for err in form.description.errors %}
        <small class="is-danger">{{err}}</small>
        {% endfor %}
      </div>
      <div class="field">
        <label class="label">Tags</label>
        <div class="control">
          <input
            class="input"
            type="text"
            name="tags"
            placeholder="Book Tags"
          />
        </div>
        {% for err in form.tags.errors %}
        <small class="is-danger">{{err}}</small>
        {% endfor %}
      </div>
      <div class="field">
        <div class="file is-centered is-boxed is-success has-name">
          <label class="file-label">
            <input class="file-input" type="file" name="image" />
            <span class="file-cta">
              <span class="file-icon">
                <i class="fas fa-upload"></i>
              </span>
              <span class="file-label"> Image Upload </span>
            </span>
            <span class="file-name">
              
            </span>
          </label>
        </div>
      </div>
      <div class="control">
        <button class="button is-primary" type="submit">Submit</button>
      </div>
      </div>
    </form>
  </div>
</div>
{% endblock content %}
<nav class="navbar is-info" role="navigation" aria-label="main navigation">
  <div class="navbar-brand">
    <a class="navbar-item" href="https://bulma.io">
      <img src="https://bulma.io/images/bulma-logo.png" width="112" 
 height="28">
    </a>
    <a role="button" class="navbar-burger" aria-label="menu" 
 aria-expanded="false" data-target="navbarBasicExample">
      <span aria-hidden="true"></span>
      <span aria-hidden="true"></span>
      <span aria-hidden="true"></span>
    </a>
  </div>
  <div id="navbarBasicExample" class="navbar-menu">
    <div class="navbar-start">
      <a class="navbar-item" href={% url 'books:home' %}>
        Home
      </a>
       <a class="navbar-item" href={% url 'books:create' %}>
        Create
      </a>
      <a class="navbar-item"> 
      </a>
      </div>
    </div>
  </div>
</nav>
 
Still there are lots of improve can be done like update, delete , permission, login, signup so its your turn guys to make it happen. I won't be doing here ...
- Here, is link for this app demo : Tagme
- You can access amin panel to but access are limit:
- username: heroku
- password: hero@123  
|  | 
| Create page 
 |