Django is like a Rambo to me, a powerful framework with lots of weapons. If you know handle just aim and bang bang 💥 💥 💥....
Overview:
So we are using django-taggit
a simpler approach to tagging with Django, and image upload using cloudinary, simply to upload image on cloud. For most of people will be helpful who does not have access to aws (s3 bucket) or an alternative to it.
[Note: if you stuck in the process you can get through my GITHUB}
Tools/Technologies:
[Note: Need to have a cloudinary account which is purely free.]
Basic Setup:
$ mkdir django-tagme && cd django-docker
$ python3 -m venv env
$ source env/bin/activate
(env)$ pip install django cloudinary Pillow django-taggit
(env)$ django-admin startproject tagme
└── src
├── tagme
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
└── requirements.txt
Lets create a new app called books
python manage.py startapp books
└── src
├── books
| |__init__.py
| ├── admin.py
| ├── apps.py
| |── models.py
| ├── views.py
|
├── tagme
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
└── requirements.txt
#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:TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'], #this one
'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',
],
},
},
]
- Registering our apps and 3rd party app:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 3rd party app
'taggit',
'imagekit',
'cloudinary',
# my_app
'books'
]
import cloudinary
cloudinary.config(
cloud_name = 'Your cloud name',
api_key = 'your cloud api key',
api_secret = 'your cloud secret key',
secure = True
)
- Next we create a templates folder in our root directory:
└── src
├── books
| |__init__.py
| ├── admin.py
| ├── apps.py
| |── models.py
| ├── views.py
|
├── tagme
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
├── templates
└── requirements.txt
Next, we create a templates:
- base.html
- create.html
- home.html
- base.html
so i will be using some basic template inheritance, and for css i will use bulma.
<!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
|
Home page or list view page:
 |
click on tags: it will render page according to tag
|
Conclusion: django_taggit is simple addons for django which reduce your time in development process. hope you guys made it to here....
Till then bye bye.....😀😀😀