使用Django構建Blog CMS(內容管理系統)
Django是一個基於python的Web應用程序框架,有助於構建各種Web應用程序。Django還包括一個可擴展的Django-Admin界面,Default SQLIte3數據庫,該數據庫還可以擴展到PostgreSQL,MySQL數據庫和其他一些用於構建高效Web應用程序的組件。
安裝和設置Django
為我們的博客創建目錄,安裝並激活虛擬環境。然後使用以下命令安裝Django
# 為我們的項目創建目錄
mkdir gfgblog && cd gfgblog
# 安裝虛擬環境
pip install virtualenv
python3 -m venv env
# 激活虛擬環境
source env/bin/activate
# 安裝django
pip install django
至此,我們已經安裝了Django,現在我們將創建一個Django項目,該項目將設置一個基本的Django應用
django-admin startproject gfgblog
cd gfgblog
在我們的gfgblog Django應用中,我們將擁有這些文件
- init.py –空文件
- urls.py –用於路由我們的django項目
- settings.py –具有我們的django項目的所有設置
- asgi.py和wsgi –在部署我們的應用程序時很有幫助
我們在Django網絡應用目錄中。現在,我們將對數據庫進行一些遷移,這將是一個SQLite3,它將設置一些默認表以在數據庫中運行我們的應用程序。然後,我們將為我們的應用程序創建一個超級用戶。
# 遷移表
python3 manage.py makemigrations
python3 manage.py migrate
# 創建並輸入超級用戶的詳細信息
python3 manage.py createsuperuser
現在運行django開發服務器並在本地主機中打開端口8000
#運行python開發服務器
python3 manage.py runserver
現在,停止服務器並進入我們的gfgblog django應用程序目錄中的gfgblog目錄,並使用代碼編輯器打開urls.py文件。您可以從下圖查看gfgblog目錄的樹
在Django中創建博客應用
現在,我們將為其創建實際的博客應用程序和數據庫。轉到gfgblog項目目錄。您可以看到我們的SQLite3數據庫gfgblog django應用程序。現在在此目錄中創建一個名為blog的新應用。以下命令將為我們創建一個新應用。
# 創建一個名為Blog的應用
python3 manage.py startapp blog
新的應用程序目錄具有5個默認文件
__init__.py –一個空文件
admin.py –用於管理管理界面
apps.py –用於管理應用程序配置
models.py –用於管理應用程序的數據庫模型
tests.py –用於測試應用程序
views.py –用於管理應用程序的行為和邏輯
在創建應用程序後,我們必須告訴Django應用程序有一個新的in out項目。為此,轉到gfgblog目錄中的settings.py並打開settings.py文件。轉到設置文件的已安裝應用程序部分,添加我們在本例中創建的應用程序的名稱(博客)
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
]
為Blog CMS創建模型
現在,我們將為該應用程序創建Django模型。
要創建Django模型,請在編輯器中打開並添加以下代碼:
# importing django models and users
from django.db import models
from django.contrib.auth.models import User
STATUS = (
(0,"Draft"),
(1,"Publish"),
(2, "Delete")
)
# creating an django model class
class posts(models.Model):
# title field uing charfield constraint with unique constraint
title = models.CharField(max_length=200, unique=True)
# slug field auto populated using title with unique constraint
slug = models.SlugField(max_length=200, unique=True)
# author field populated using users database
author = models.ForeignKey(User, on_delete= models.CASCADE)
# and date time fields automatically populated using system time
updated_on = models.DateTimeField(auto_now= True)
created_on = models.DateTimeField()
# content field to store our post
content = models.TextField()
# meta descrption for SEO benifits
metades = models.CharField(max_length=300, default="new post")
# status of post
status = models.IntegerField(choices=STATUS, default=0)
# meta for the class
class Meta:
ordering = ['-created_on']
# used while managing models from terminal
def __str__(self):
return self.title
保存文件並進行遷移,以便使用以下命令在我們的數據庫中創建字段
# creates migrations for the blog app
python3 manage.py makemigrations blog
# migrates the blog app
python3 manage.py migrate blog
到目前為止,我們擅長創建模型並設置數據庫來存儲帖子,但我們應該將其展示給用戶。幸運的是django帶有自己的模板語言,我們可以使用它來構建動態HTML頁面來為用戶服務。我們還可以使用CSS和JavaScript添加樣式。
為Blog CMS創建模板
要創建模板,請先在博客應用程序中創建模板目錄(您也可以在博客應用程序之外創建模板目錄,但是這樣可以輕鬆管理)。為了以簡單的方式為項目中的每個應用程序管理模板,我們必須對設置進行一些更改。轉到項目設置文件,並用以下代碼替換模板設置
TEMPLATES_DIR = os.path.join(BASE_DIR,'templates')
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATES_DIR],
'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',
],
},
},
]
現在,我們將為博客創建模板。由於django可以動態構建頁面,因此我們將根據它構建模板。現在,我們將創建一個基礎模板,該模板將作為博客中所有頁面的基礎
<!DOCTYPE html>
<html lang="en">
<head>
<!-- will be replaced with meta content -->
{% block metatags %}{% endblock %}
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<style>
html, body {
height: 100%;
}
body {
font-family: sans-serif;
font-size: 18px;
background-color: #fdfdfd;
display: flex;
flex-direction: column;
}
#nofooter {
flex: 1 0 auto;
}
darkbtn {
color: #66ff99; }
.dark-mode {
background-color: black;
color: white;
}
#foot {
flex-shrink: 0;
font-family: sans-serif;
background-color: #BDFFD3; color: #00308F;
bottom: 0px;
width: 100%;
}
.card-group,.card,.card-footer,.card-body {
border: none;
}
</style>
</head>
<body><div id="bodydiv"><div id="nofooter">
<nav class="navbar navbar-expand-lg navbar-light bg-light shadow" id="topnav">
<div class="container-fluid">
<a class="navbar-brand" href="{% url 'home' %}">
<img src="/static/icons/logo.png" width="30" height="30" class="d-inline-block rounded align-top" alt="logo" loading="lazy">
GeeksForGeeks</a>
<div class="nav justify-content-end">
<div class="d-inline"><a class="nav-link text-black font-weight-bold" href="{% url 'posts'%}">Posts</a></div>
</div></div>
</nav>
<!-- will be replaced with post content -->
{% block content %}
{% endblock content %}
</div>
<footer class="footer" id="foot">
<div class="container"><h5 style="text-align:center;">Enjoy the Blog and Stay Updated</h5>
<nav class="navbar navbar-expand-lg">
<div class="container-fluid">
<p>Copyright © GeeksForGeeks</p>
<div class="nav justify-content-center" id="navfooter">
<span><a class="nav-link text-black font-weight-bold" href="{% url 'about' %}">About</a></span>
<span><a class="nav-link text-black font-weight-bold" href="{% url 'privacy' %}">Privacy</a></span>
<span><a class="nav-link text-black font-weight-bold" href="{% url 'tos' %}">Terms</a></span>
<span><a class="nav-link text-black font-weight-bold" href="http://feeds.feedburner.com/hackingandprogramming-news">Feed</a></span>
</div>
</div>
</nav>
</div>
</footer></div>
</body>
</html>
這將是我們的基本模板,您可以將{%block name%} {%endblock%}之類的塊替換為分配給他們的內容,現在,我們將創建一個主頁模板,該模板將成為我們博客的主頁,有最新的帖子。
{% extends "base.html" %}
{% block metatags %}
<title>Home | GeeksForGeeks</title>
<meta name="description" content="A destination for Learning">
<meta property="og:title" content="GeeksForGeeks">
<meta property="og:site_name" content="GeeksForGeeks">
<meta property="og:url" content="https://GeeksForGeeks.org">
<meta property="og:description" content="A destination for Learning">
<meta property="og:type" content="website">
{% endblock %}
{% block content %}
<style type="text/css">
body {
font-family: 'Raleway', sans-serif;}
.head_text {
color: white;
}
.h1, h4 {
font-family: 'Raleway', sans-serif;
}
#mainhome {
text-align: center; }
</style>
<header class="jumbotron" style="background-color: #BDFFD3; color: #00308F;">
<div class="container">
<p class="h1"> Welcome to <strong>GeeksForGeeks</strong></p>
</div>
</header>
<div class="container">
<div class="row">
<div class="col-md-8 mt-3 left">
{% for post in posts_list %}
<div class="shadow-none card mb-4" id="newsfeed">
<div class="card-body">
<h3 class="card-title">{{ post.title }}</h3>
<p class="card-text text-muted h6"><span>{{ post.author.first_name }} {{ post.author.last_name }}</span> | {{ post.created_on}} </p>
<p class="card-text">{{post.metades }}</p>
<span><a href="{% url 'post_detail' post.slug %}" class="btn btn-outline-primary">Read More →</a></span><span><a href="{% url 'post_detail_amp' post.slug %}" class="btn btn-outline-success">AMP page</a></span>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% if is_paginated %}
<nav aria-label="Page navigation conatiner"></nav>
<ul class="pagination justify-content-center">
{% if page_obj.has_previous %}
<li><a href="?page={{ page_obj.previous_page_number }}" class="btn btn-outline-info" style="font-family: sans-serif;">« PREV </a></li>
{% endif %}
{% if page_obj.has_next %}
<li><a href="?page={{ page_obj.next_page_number }}" class="btn btn-outline-info" style="font-family: sans-serif;"> NEXT »</a></li>
{% endif %}
</ul>
{% endif %}
{%endblock%}
我們已經創建了帶有分頁的主頁。帖子將使用for循環顯示。現在,我們將添加最後一個模板以單獨顯示帖子。
{% extends 'base.html' %}
{% block metatags %}
<title>{{ object.title }}</title>
<meta name="description" content="{{ object.metades}}" />
<meta property="og:title" content="{{ object.title }}">
<meta property="og:site_name" content="GeeksForGeeks">
<meta property="og:url" content="{% url 'post_detail' object.slug %}">
<meta property="og:description" content="{{ object.metades }}">
<meta property="og:type" content="article">
{% endblock %}
{% block content %}
<style type="text/css">
#container img {
border-radius: 29px;
width: 100%;
height: 360px;
opacity: 0.7;
align-content: center;
}
#container img {
opacity: 1.0; }
a {text-align: center; text-decoration: none;}
</style>
<script type="application/ld+json">
{
"@context": "https://schema.org/",
"@type": "Post",
"headline": "{{ object.title }}",
"description": "{{ object.metades }}",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "{% url 'post_detail' object.slug %}"
},
"author": {
"@type": "Person",
"name": "{{ post.author.first_name }} {{ post.author.last_name "
},
"publisher": {
"@type": "Organization",
"name": "GeeksForGeeks",
},
"datePublished": "{{ news.created_on }}",
"dateModified": "{{ news.created_on }}",
"mentions": "{{ object.source }}"
}
</script>
<div class="container">
<div class="row">
<div class="col-md-6 left">
<h1 class="card-title">{% block title %} {{ object.title }} {% endblock title %}</h1>
<p class=" text-muted">{{ object.author.first_name }} {{ object.author.last_name }} |{{ object.created_on }}</p>
<p class="card-text">{{ object.content | safe }}</p>
</div>
</div>
</div>
{% endblock content %}
通過擴展基本模板並用存儲在我們數據庫中的數據替換塊,可以構建主頁和發布頁面。兩者都還具有Facebook開放圖以便更好地共享和社交網絡,並且帖子頁還具有結構化架構以更好地實現SEO。我們將在接下來的教程中構建AMP模板。
為Blog CMS創建視圖
現在,在博客目錄中打開views.py文件。該文件具有運行博客應用程序的邏輯。我們將對博客應用程序使用基於類的視圖。基於類的通用視圖是內置視圖的高級集合,用於實現選擇性視圖策略(例如創建,檢索,更新,刪除)。
# importing models and libraries
from django.shortcuts import render
from .models import posts
from django.views import generic
from django.views.decorators.http import require_GET
from django.http import HttpResponse
# class based views for posts
class postslist(generic.ListView):
queryset = posts.objects.filter(status=1).order_by('-created_on')
template_name = 'home.html'
paginate_by = 4
# class based view for each post
class postdetail(generic.DetailView):
model = posts
template_name = "post.html"
為Blog CMS創建路由
對於路由我們的博客應用程序,只需進入博客應用程序目錄並創建文件urls.py即可路由我們的應用程序。見下面的代碼
# importing django routing libraries
from . import views
from django.urls import path, include
from .views import *
from .feeds import blogFeed
urlpatterns = [
# home page
path('', views.postslist.as_view(), name='posts'),
# route for posts
path('<slug:slug>/', views.postdetail.as_view(), name='post_detail'),
]
轉到gfgblog目錄中的urls.py文件並路由我們的博客應用。請參閱下面的代碼以供參考
from django.contrib import admin
from django.urls import path, include, re_path
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# urls handling admin route
path('admin/', admin.site.urls),
# urls handling blog routes
path('', include('blog.urls')),
]
完成,現在讓我們使用
Python manage.py runserver
博客CMS屏幕截圖:
樣本帖子頁面:
使用Django Admin進行帖子管理:
通過Django Admin進行用戶管理