使用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構建Blog

    現在運行django開發服務器並在本地主機中打開端口8000

    #運行python開發服務器
    python3 manage.py runserver

    默認的Django頁面

    現在,停止服務器並進入我們的gfgblog django應用程序目錄中的gfgblog目錄,並使用代碼編輯器打開urls.py文件。您可以從下圖查看gfgblog目錄的樹
    django應用程序目錄樹結構

    在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屏幕截圖:
    blog

    樣本帖子頁面:

    A

    使用Django Admin進行帖子管理:
    Posts

    通過Django Admin進行用戶管理

    User