程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

django搭建博客十博客首頁

編輯:Python

文章應用模型建立

編輯\myblog\article\models.py

內容如下:

import logging
import os
from django.db import models
from django.db.models import F
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.conf import settings
from django.utils.html import strip_tags
from django.contrib.auth import get_user_model
from mdeditor.fields import MDTextField
from system.models import BaseModel
logger = logging.getLogger('django')
User = get_user_model()
class Category(BaseModel):
name = models.CharField(verbose_name='類別名稱', max_length=20, unique=True)
slug = models.SlugField(verbose_name="分類slug", unique=True)
level = models.IntegerField(verbose_name="分類層級", default=1)
parent = models.ForeignKey('self', verbose_name='父級導航', related_name='parent_category', null=True, blank=True,
on_delete=models.CASCADE, help_text="父級導航可以為空",
limit_choices_to={
"parent__isnull": True})
show = models.BooleanField(verbose_name="是否顯示", default=True)
icon = models.CharField(verbose_name="導航圖標", max_length=30, help_text="目前導航圖標僅支持font-awesome", null=True,
blank=True)
order = models.IntegerField(verbose_name="序號", help_text="序號越大的越靠前", default=1)
class Meta:
db_table = "article_category"
verbose_name = '文章分類'
verbose_name_plural = verbose_name
ordering = ['-order']
def __str__(self):
return self.name
def save(self, *args, **kwargs):
if self.parent:
self.level = self.parent.level + 1
super(Category, self).save(*args, **kwargs)
class Tag(BaseModel):
name = models.CharField(verbose_name='標簽名', max_length=20, unique=True)
slug = models.SlugField(verbose_name="標簽slug", unique=True)
show = models.BooleanField(verbose_name="是否顯示", default=True)
class Meta:
db_table = "article_tag"
verbose_name = '標簽'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
def get_article_count(self):
return self.tag_article.count()
class Article(BaseModel):
slug = models.SlugField(verbose_name="文章slug", unique=True)
title = models.CharField(max_length=500, verbose_name='文章標題')
summary = models.TextField(verbose_name='文章摘要', help_text="系統自動生成摘要", null=True, blank=True)
content = MDTextField(verbose_name="內容", null=True, blank=True)
cover = models.ImageField(verbose_name="文章封面", null=True, blank=True)
views = models.IntegerField(verbose_name='浏覽數', default=0, editable=False)
loves = models.IntegerField(verbose_name='點贊數', default=0, editable=False)
category = models.ForeignKey(Category, verbose_name='分類', on_delete=models.DO_NOTHING,
related_name="category_article", limit_choices_to={
'level__gt': 1},
db_constraint=False, null=True, blank=True)
tags = models.ManyToManyField(Tag, verbose_name='標簽', related_name='tag_article', blank=True,
db_table="sys_article_tag")
show = models.BooleanField(verbose_name="是否顯示", default=True)
can_comment = models.BooleanField(verbose_name="允許評論", default=True)
auto_summary = models.BooleanField(verbose_name="自動生成摘要", help_text="如果不勾選,則不會自動生成摘要信息", default=True)
place_top = models.BooleanField(verbose_name="是否置頂", default=False)
class Meta:
db_table = "article"
verbose_name = "文章"
verbose_name_plural = verbose_name
ordering = ["-place_top", "-create_time"]
def __str__(self):
return self.title[:20]
def get_previous_article(self):
previous_article = Article.objects.only("id", "slug").filter(id__lt=self.id).last()
return previous_article
def get_next_article(self):
next_article = Article.objects.only("id", "slug").filter(id__gt=self.id).last()
return next_article
def increase_views(self):
Article.objects.filter(id=self.id).update(views=F('views') + 1)
def increase_loves(self):
Article.objects.filter(id=self.id).update(loves=F('loves') + 1)
def get_tag_list(self):
return self.tags.all()
def show_image(self):
url = os.path.join(settings.MEDIA_URL, self.cover.url)
return mark_safe("<img src='{url}' width=75></a>".format(url=url))
show_image.short_description = "封面"
def save(self, *args, **kwargs):
if self.auto_summary:
summary = strip_tags(self.content).replace(" ", "").replace("\n", "").replace("&nbsp;", " ")
self.summary = summary[:200]
super(Article, self).save(*args, **kwargs)

admin後台配置

新增\myblog\article\admin.py

內容如下

from django.contrib.admin import register
from article.models import Article, Tag, Category
from system.admin import BaseModelAdmin
@register(Category)
class CategoryModelAdmin(BaseModelAdmin):
list_display = ['id', 'name', 'slug', 'show', 'parent', 'order']
list_filter = ["show", "level"]
search_fields = ['name', 'slug']
list_editable = ['name', 'slug', 'show', 'order']
@register(Tag)
class TagModelAdmin(BaseModelAdmin):
list_display = ['id', 'name', 'slug', 'show']
search_fields = ['name', 'slug']
list_editable = ['name', 'show']
@register(Article)
class ArticleModelAdmin(BaseModelAdmin):
actions = ["batch_show_action", "batch_hide_action"]
list_display = ['title', 'category', 'views', 'loves', 'can_comment', 'show', 'place_top','show_image']
list_filter = ['title', 'category', 'tags', 'show']
search_fields = ['title', 'content']
list_editable = ['show', 'place_top', 'can_comment']
list_per_page = 10
list_order_field = ["views", "loves"]
filter_horizontal = ("tags",)
preserve_filters = ("category",)
def batch_show_action(self, queryset):
for obj in queryset:
obj.show = True
obj.save()
return None
batch_show_action.short_description = "批量顯示所選的"
def batch_hide_action(self, queryset):
for obj in queryset:
obj.show = False
obj.save()
return None
batch_hide_action.short_description = "批量隱藏所選的"
def queryset(self):
"""控制用戶只能查看自己的文章(除了超級管理員)"""
qs = super().queryset()
if not self.request.user.is_superuser:
qs = qs.filter(creator=self.request.user)
return qs

meditor路由配置

編輯\myblog\myblog\urls.py

由於在Article模型裡面用到了富文本編輯器應用django-meditor,所以這裡需要在urlpatterns列表裡面添加以下內容

path(r'mdeditor/', include('mdeditor.urls')),

後台效果圖

文章分類效果圖

文章標簽效果圖

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ibnEjIsX-1656230280008)(assets/1656127970807.png)]

文章效果圖

文章編輯效果圖

自定義文章模板標簽

新增\myblog\article\templatetags模塊文件夾

新增\myblog\article\templatetags\article_tags.py文件

添加如下內容

from django import template
from article.models import Article, Tag
import logging
logger = logging.getLogger('django')
register = template.Library()
@register.simple_tag
def get_article_date_list():
article_date_list = Article.objects.only("id", "slug", "title").filter(show=True).datetimes('create_time', 'month',
order='DESC')
return article_date_list
@register.simple_tag
def get_article_by_date(year, month):
article_list = Article.objects.only("id", "slug", "title").filter(show=True, create_time__year=year,
create_time__month=month)
return article_list
@register.simple_tag
def get_tag_list():
"""返回標簽列表"""
from django.db.models import Count
tag_list = Tag.objects.annotate(article_nums=Count('tag_article')).filter(article_nums__gt=0).order_by('name')
return tag_list
@register.simple_tag
def get_new_article_list():
return Article.objects.only("id", "slug", "title").filter(show=True).order_by('-create_time')[:5]
@register.simple_tag
def get_hot_article_list():
return Article.objects.only("id", "slug", "title").filter(show=True).order_by('-views')[:5]

自定義模板上下文

編輯\myblog\system\template_context_processors.py

import logging
from system.models import User
logger = logging.getLogger("django")
def template_context(request):
superuser = User.objects.filter(is_superuser=True).first()
context = {
"superuser": superuser}
return context

編輯\myblog\myblog\settings.py,修改TEMPLATES注冊自己定義的上下文處理器

TEMPLATES = [
{

'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'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',
# 把media全局注冊進template模板中
'django.template.context_processors.media',
'system.template_context_processors.template_context',
],
},
},
]

首頁控件

文章分頁控件

編寫\myblog\templates\layout\pagination.html

添加以下內容

{% load system_tags %}
{% if is_paginated %}
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-center my-3 pagination-lg">
{% if page_obj.has_previous %}
<li class="page-item">
<a href="?page={
{ page_obj.previous_page_number }}" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
{% endif %}
{% get_elided_page_range paginator page_obj.number as page_list %}
{% for page in page_list %}
{% ifequal page page_obj.number %}
<li class="page-item active"><span>{
{ page }}</span></li>
{% else %}
{% ifequal page page_obj.paginator.ELLIPSIS %}
<li class="page-item"><span>{
{ page }}</span></li>
{% else %}
<li class="page-item"><a href="?page={
{ page }}&q={
{ query }}">{
{ page }}</a></li>
{% endifequal %}
{% endifequal %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a href="?page={
{ page_obj.next_page_number }}" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}

效果圖

文章列表控件

編寫\myblog\templates\article\article-query-list.html

添加以下內容

{% for article in articles %}
<article class="d-block bg-white hvr-float">
<div class="media d-block">
<div class="article-thumb">
<a href="#"><img src="{
{ MEDIA_URL }}{
{ article.cover }}" class="mr-3"></a>
</div>
<div class="media-body py-3 pl-1 overflow-hidden">
<div class="index-article-header">
<a href="#" class="label ">{
{ article.category.name }}<i class="position-absolute c-arrow"></i></a>
<h2 class="d-inline article-title"><a href="#" class="text-dark">{
{ article.title }}</a></h2>
{% if article.place_top %}<span class="new-icon">置頂</span>{% endif %}
</div>
<div class="article-summary">
<p class="text-wrap text-secondary">
{
{ article.summary|truncatechars:170 }}{% if article.summary|length > 150 %}
...{% endif %}</p>
</div>
</div>
<div class="article-relative-meta">
<span class="float-left">
<a href="#"><i class="fa fa-calendar c4"></i>{
{ article.create_time|date:'Y年m月d日' }}</a>
<a href="#"><i class="fa fa-comments c5"></i>{
{ 0 }}評論</a>
<a href="#"><i class="fa fa-eye c6"></i>{
{ article.views|default:0 }}閱讀</a>
</span>
<span class="visible-xs float-left">
<a href="#"><i class="fa fa-heart c7"></i>{
{ article.loves|default:0 }}喜歡</a>
<a {% if article.creator.link %}href="{
{ article.creator.link }}"{% endif %}><i class="fa fa-user c8"></i>{% firstof article.creator.nickname article.creator.username %}</a>
</span>
<span class="float-right">
<a class="mr-0" href="#" title="閱讀全文">閱讀全文<i class="fa fa-chevron-circle-right"></i></a>
</span>
</div>
</div>
</article>
{% empty %}
<div class="d-block bg-white mb-3 text-center" >暫時還沒有發布的文章!
</div>
{% endfor %}

效果圖

首頁側邊欄控件

編寫\myblog\templates\layout\aside\page_aside.html

添加以下內容

<aside class="col-lg-4 col-xl-4 hidden-xs hidden-sm" id="aside">
<div class="sidebar" id="sidebar">
{% include 'layout/aside/sentence.html' %}
{% include 'layout/aside/aboutme.html' %}
{% include 'layout/aside/recommendation-article.html' %}
{% include 'layout/aside/article-tag.html' %}
</div>
</aside>

側邊欄每日一句控件

編寫\myblog\templates\layout\aside\sentence.html

添加以下內容

{% load system_tags %}
<aside class="mb-2">
<div class="sentence">
<strong>隨機一句</strong>
<h2>{% now "Y年m月d日" %}</h2>
<p>己所不欲,勿施於人。</p>
</div>
</aside>

效果圖

側邊欄關於我控件

編寫\myblog\templates\layout\aside\aboutme.html

添加以下內容

{% load static %}
<aside class="card about mb-2">
<div class="card-bg"></div>
<div class="card-body text-center p-0">
{% if request.user.is_authenticated %}
<img class="xwcms" src="{
{ MEDIA_URL }}{
{ request.user.avatar }}"/>
<h5 class="card-title text-dark mt-2">{% firstof request.user.nickname request.user.username %}</h5></a>
<p class="card-text mb-2" >{
{ request.user.introduction|default:'' }}</p>
<p>
<a href="#" class="text-reset "><i class="fa fa-user-circle"></i>修改資料</a>
<a href="#" class="text-reset "><i class="fa fa-key"></i>修改密碼</a>
<a href="{% url 'sys:logout' %}" class="text-reset "><i class="fa fa-sign-out"></i>退出登錄</a>
</p>
{% else %}
<a href="#"><img class="xwcms" src="{
{ MEDIA_URL }}{
{ superuser.avatar }}"></a>
<a href="#" class=""><h5 class="card-title text-dark mt-2 superuser">{% firstof superuser.nickname superuser.username %}</h5>
</a>
<p class="card-text mb-2" >{
{ superuser.introduction|default:'' }}</p>
<div class="contact-me text-center">
<a id="link_weixin" href="javascript:;" rel="nofollow" data-toggle="popover" data-trigger="hover click" data-html="true" data-title="公眾號" data-content="<img src='{% static '/images/weixin_link.jpg' %}' width='150px' height='150px'>"><i class="fa fa-weixin" aria-hidden="true"></i></a>
<a target="_blank" href="https://github.com/tongyuebin" rel="nofollow"><i class="fa fa-github" aria-hidden="true"></i></a>
<a target="_blank" href="http://mail.qq.com/cgi-bin/qm_share?t=qm_mailme&email={
{ superuser.email }}" rel="nofollow"><i class="fa fa-envelope-o" aria-hidden="true"></i></a>
<a id="link_qq" href="javascript:;" rel="nofollow" data-toggle="popover" data-title="博主QQ" data-trigger="hover click" data-html="true" data-content="<img src='{% static '/images/qq_link.jpg' %}' width='150px' height='150px'>"><i class="fa fa-qq" aria-hidden="true"></i></a>
</div>
</div>
<div class="text-center" >
<a id="bookmark" class="bookmark button--primary button--animated" href="javascript:;" title="加入書簽" target="_self"><i class="fa fa-bookmark" aria-hidden="true"></i><span class="pl-2">加入書簽</span></a>
</div>
{% endif %}
</aside>

未登錄效果圖

登陸後效果圖

側邊欄文章推薦控件

編寫\myblog\templates\layout\aside\recommendation-article.html

添加以下內容

{% load article_tags %}
{% get_new_article_list as newArticles %}
{% get_hot_article_list as hotArticles %}
{% if newArticles or hotArticles %}
<aside class="mb-2 py-2 pl-3 recommendation tab-6">
<ul class="nav nav-tabs" role="tablist">
{% if newArticles %}
<li class="nav-item">
<a class="nav-link border-0 text-center text-dark active" data-toggle="tab" href="#new" role="tab" aria-controls="new">最新文章</a>
</li>
{% endif %}
{% if hotArticles %}
<li class="nav-item">
<a class="nav-link border-0 text-center text-dark" data-toggle="tab" href="#hot" role="tab" aria-controls="hot">最熱文章</a>
</li>
{% endif %}
</ul>
<div class="tab-content">
<div class="tab-pane active" id="new" role="tabpanel">
<ul class="list-group list-group-flush">
{% for newArticle in newArticles %}
<a class="pl-0 list-group-item text-truncate text-dark " title="{
{ newArticle.title }}" href="#">
<i class="fa fa-book"></i>
{
{ newArticle.title }}
</a>
{% endfor %}
</ul>
</div>
<div class="tab-pane" id="hot" role="tabpanel">
<ul class="list-group list-group-flush">
{% for hotArticle in hotArticles %}
<a class="pl-0 list-group-item text-truncate text-dark " title="{
{ hotArticle.title }}" href="#">
<i class="fa fa-book"></i>
{
{ hotArticle.title }}
</a>
{% endfor %}
</ul>
</div>
</div>
</aside>
{% endif %}

效果圖

側邊欄文章標簽控件

新增\myblog\templates\layout\aside\article-tag.html

內容如下

{% load system_tags %}
{% load article_tags %}
{% get_tag_list as tags %}
{% if tags %}
<aside class="mb-2 py-2 pl-3 aside-article-tag tab-6">
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link border-0 text-center text-dark active" data-toggle="tab" href="#aside-article-tag" role="tab" aria-controls="aside-article-tag">標簽雲</a>
</li>
</ul>
<div class="tab-content pt-2">
<div class="tab-pane active" id="aside-article-tag" role="tabpanel">
<!--標簽雲-->
<div class="tags btn-group-sm d-inline-block">
{% for tag in tags %}
<a class="btn btn-sm border rounded-pill" href="{% url 'article:tag' tag.slug %}" data-toggle="tooltip" title="該標簽下有{
{ tag.article_nums }}篇文章">{
{ tag.name }}</a>
{% endfor %}
</div>
</div>
</div>
</aside>
{% endif %}

效果圖

首頁模板

新增\myblog\templates\index.html

{% extends 'base.html' %}
{% load static %}
{% block title %}
{
{ title|default:'首頁' }}
{% endblock %}
{% block main %}
<div class="container">
<div class="row">
<section class="col-sm-12 col-md-12 col-lg-8 index" id="main">
{% include 'article/article-query-list.html' %}
{% include 'layout/pagination.html' %}
</section>
{% include 'layout/page_aside.html' %}
</div>
</div>
{% endblock %}

首頁視圖

編寫\myblog\article\views.py

添加以下內容

from django.http import Http404
import logging
from django.views.generic import ListView
from article.models import Article, Tag, Category
logger = logging.getLogger('django')
class ArticleListView(ListView):
template_name = 'index.html'
context_object_name = 'articles'
paginate_by = 10
page_kwarg = 'page'
http_method_names = ['get']
model = Article
queryset = Article.objects.only("id",
"slug",
"title",
"cover",
"summary",
"category__name",
"category_id",
"place_top",
"create_time",
"views",
"loves",
"creator__username")
def get_queryset(self):
qs = super(ArticleListView, self).get_queryset()
qs = qs.filter(**self.kwargs)
if not self.request.user.is_superuser:
qs = qs.filter(show=True)
return qs
def get_context_data(self, **kwargs):
title = "首頁"
try:
if 'tags__slug' in self.kwargs.keys(): # 按標簽分類文章
slug = self.kwargs.get('tags__slug')
tag = Tag.objects.get(slug=slug)
title = "文章標簽歸檔:" + tag.name
elif 'category__slug' in self.kwargs.keys():
slug = self.kwargs.get('category__slug')
category = Category.objects.get(slug=slug)
title = "文章分類歸檔:" + category.name
elif 'create_time__year' in self.kwargs.keys() and 'create_time__month' in self.kwargs.keys(): # 日期分類文章
title = "文章日期歸檔:" + str(self.kwargs.get("create_time__year")) + "-" + str(
self.kwargs.get("create_time__month"))
kwargs.update({
"title": title})
except Exception as e:
logger.info(e)
raise Http404()
return super(ArticleListView, self).get_context_data(**kwargs)

路由綁定

編輯\myblog\article\urls.py

添加以下內容

from django.urls import path
from article import views
urlpatterns = [
path('category/<slug:category__slug>', views.ArticleListView.as_view(), name='category'),
path('tag/<slug:tags__slug>', views.ArticleListView.as_view(), name='tag'),
path('date/<int:create_time__year>/<int:create_time__month>', views.ArticleListView.as_view(), name='date'),
]

編輯\myblog\myblog\urls.py

添加以下內容

from article.views import ArticleListView
path('', ArticleListView.as_view(), name="index"),

首頁整體效果圖

未登錄效果圖

登陸後效果圖


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved