Django Build a blog application with bootstrap and Automatically Generate slugs
Part 2 Django Build a blog application Part 2 with WYSIWYG Editor Pagination and Comments
In this tutorial, we’ll build a Blog application with Django that allows users to create, edit, and delete posts.
Also Generating slugs automatically like http://127.0.0.1:8000/6-ways-salesforce-gets-things-done-with-python/
Database Table
CREATE TABLE myapp_post (
id INTEGER PRIMARY KEY,
title STRING (255),
slug STRING (200),
author_id INT (11),
updated_on DATETIME,
content TEXT,
created_on DATETIME,
status STRING (200)
);
#models.py
from django.db import models
from django.contrib.auth.models import User
from django.utils.text import slugify
STATUS = (
(0,"Draft"),
(1,"Publish")
)
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete= models.CASCADE,related_name='myapp_post')
updated_on = models.DateTimeField(auto_now= True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
class Meta:
db_table = "myapp_post"
def save(self, *args, **kwargs):
value = self.title
self.slug = slugify(value, allow_unicode=True)
super().save(*args, **kwargs)
#admin.py
from django.contrib import admin
from myapp.models import Post
#admin.site.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'slug', 'status','created_on')
list_filter = ("status",)
search_fields = ['title', 'content']
prepopulated_fields = {'slug': ('title',)}
admin.site.register(Post, PostAdmin)
#urls.py
from django.contrib import admin
from django.urls import path
from myapp import views
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.index),
path('/', views.PostDetail.as_view(), name='post_detail'),
]
#views.py
from django.shortcuts import render, redirect
from django.views import generic
from myapp.models import Post
def index(request):
post_list = Post.objects.filter(status=1).order_by('-created_on')
return render(request, 'index.html', { 'post_list': post_list })
class PostDetail(generic.DetailView):
model = Post
template_name = 'post_detail.html'
//templates/index.html
{% extends 'base.html' %}
{% block content %}
{% for post in post_list %}
<div class="post-preview">
<a href="{% url 'post_detail' post.slug %}">
<h2 class="post-title">
{{ post.title }}
</h2>
<h3 class="post-subtitle">
{{post.content|slice:":200" }}
</h3>
</a>
<p class="post-meta">Posted by {{ post.author }} | {{ post.created_on}} </p>
</div>
<hr>
{% endfor %}
<div class="clearfix">
<a class="btn btn-primary float-right" href="#">Older Posts →</a>
</div>
{% endblock %}
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>Clean Blog - Start Bootstrap Theme</title>
{% load static %}
<!-- Bootstrap core CSS -->
<link href="{% static 'vendor/bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
<!-- Custom fonts for this template -->
<link href="vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
<link href='https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
<!-- Custom styles for this template -->
<link href="{% static 'css/clean-blog.min.css' %}" rel="stylesheet">
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
<div class="container">
<a class="navbar-brand" href="index.html">Start Bootstrap</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
Menu
<i class="fas fa-bars"></i>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="about.html">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="post.html">Sample Post</a>
</li>
<li class="nav-item">
<a class="nav-link" href="contact.html">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- Page Header -->
<header class="masthead" style="background-image: url('{% static 'img/home-bg.jpg' %}')">
<div class="overlay"></div>
<div class="container">
<div class="row">
<div class="col-lg-8 col-md-10 mx-auto">
<div class="site-heading">
<h1>Clean Blog</h1>
<span class="subheading">A Blog Theme by Start Bootstrap</span>
</div>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<div class="container">
<div class="row">
<div class="col-lg-8 col-md-10 mx-auto">
{% block content %}
{% endblock %}
</div>
</div>
</div>
<hr>
<!-- Footer -->
<footer>
<div class="container">
<div class="row">
<div class="col-lg-8 col-md-10 mx-auto">
<ul class="list-inline text-center">
<li class="list-inline-item">
<a href="#">
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x"></i>
<i class="fab fa-twitter fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
<li class="list-inline-item">
<a href="#">
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x"></i>
<i class="fab fa-facebook-f fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
<li class="list-inline-item">
<a href="#">
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x"></i>
<i class="fab fa-github fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
</ul>
<p class="copyright text-muted">Copyright © Your Website 2019</p>
</div>
</div>
</div>
</footer>
<!-- Bootstrap core JavaScript -->
<script src="{% static 'vendor/jquery/jquery.min.js' %}"></script>
<script src="{% static 'vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<!-- Custom scripts for this template -->
<script src="{% static 'js/clean-blog.min.js' %}"></script>
</body>
</html>
//templates/post_detail.html
{% extends 'base.html' %}
{% block content %}
<div class="col-lg-8 col-md-10 mx-auto">
<h1>{% block title %} {{ object.title }} {% endblock title %}</h1>
<p class=" text-muted">{{ post.author }} | {{ post.created_on }}</p>
<p class="card-text ">{{ object.content | safe }}</p>
</div>
{% endblock %}
