不知不觉,在一家公司工作了5年,主要从事Google SEO 方面工作,最近突然想制作一个自己的博客,对自己平时工作一个总结,恰巧最近学习了python语法,以及django框架,就尝试这写一个自己的博客
https://gitee.com/chenglulu/djangoblog.git
git clone https://gitee.com/chenglulu/djangoblog.git
H:\djangoblog>python -m venv venv
F:\DjangoWeb>venv\Scripts\activate.bat
(venv) H:\djangoblog>
pip install django==2.2
django-admin startproject blog
至此,django开发环境已经搭建完毕
pip install mysqlclient
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'NAME': 'name', # 数据库名,先前创建的
'USER': 'root', # 用户名,可以自己创建用户
'PASSWORD': 'root', # 密码
'HOST': '127.0.0.1', # mysql服务所在的主机ip
'PORT': '3306', # mysql服务端口
}
}
修改后需要手动建立对应数据库
# 把英文改为中文
LANGUAGE_CODE = 'zh-hans'
# 把国际时区改为中国时区
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static"), ]
# specify media root for user uploaded files,
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
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',
],
},
},
]
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
至此,django配置文件配置完毕
python3 manage.py startapp article
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'article',
]
编写博客使用markdown
pip install markdown
在后台可以使用markdown编辑文章
pip install django-mdeditor
可以支持中文转拼音,有利于seo
pip install django-uuslug
import re
import os
import uuid
import markdown
from mdeditor.fields import MDTextField
from uuslug import slugify
from django.urls import reverse
from django.db import models
from django.contrib.auth.models import User
def articleimage_directory_path(instance, filename):
ext = filename.split('.')[-1]
filename = '{}.{}'.format(uuid.uuid4().hex[:10], ext)
return os.path.join("articleimage", filename)
# 文章关键字
class Keyword(models.Model):
name = models.CharField('文章关键词', max_length=150)
class Meta:
verbose_name = '关键词'
verbose_name_plural = verbose_name
ordering = ['name']
def __str__(self):
return self.name
# 文章标签
class Tag(models.Model):
name = models.CharField('文章标签', max_length=100)
slug = models.SlugField(unique=True, max_length=255)
description = models.TextField('描述', max_length=250,
help_text='用来作为SEO中description,长度参考SEO标准', blank=True, null=True)
def save(self, *args, **kwargs):
if not self.id or not self.slug:
self.slug = slugify(self.name)
super().save(*args, **kwargs)
class Meta:
verbose_name = '标签'
verbose_name_plural = verbose_name
ordering = ['id']
def __str__(self):
return self.name
# 文章分类
class Category(models.Model):
name = models.CharField('文章分类', max_length=20)
slug = models.SlugField(unique=True, max_length=255)
description = models.TextField('描述', max_length=255,
help_text='用来作为SEO中description,长度参考SEO标准', blank=True, null=True)
def save(self, *args, **kwargs):
if not self.id or not self.slug:
self.slug = slugify(self.name)
super().save(*args, **kwargs)
class Meta:
verbose_name = '分类'
verbose_name_plural = verbose_name
ordering = ['name']
def __str__(self):
return self.name
# 文章
class Article(models.Model):
# IMG_LINK = '/static/blog/img/summary.png'
author = models.ForeignKey(User, verbose_name='作者', on_delete=models.CASCADE)
title = models.CharField(max_length=150, verbose_name='文章标题')
slug = models.SlugField(max_length=255, unique=True)
summary = models.TextField('文章摘要', max_length=230, default='文章摘要等同于网页description内容,请务必填写...')
body = MDTextField(verbose_name='文章内容')
image = models.ImageField('图片', upload_to=articleimage_directory_path)
create_date = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
update_date = models.DateTimeField(verbose_name='修改时间', auto_now=True)
views = models.IntegerField('阅览量', default=0)
# 新增点赞数统计
likes = models.PositiveIntegerField(default=0)
is_top = models.BooleanField('置顶', default=False)
category = models.ForeignKey(Category, verbose_name='文章分类', on_delete=models.PROTECT)
tags = models.ManyToManyField(Tag, verbose_name='标签')
keywords = models.ManyToManyField(Keyword, verbose_name='文章关键词',
help_text='文章关键词,用来作为SEO中keywords,最好使用长尾词,3-4个足够')
def save(self, *args, **kwargs):
if not self.id or not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
class Meta:
verbose_name = '文章'
verbose_name_plural = verbose_name
ordering = ['-create_date']
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:article_detail', kwargs={'slug': self.slug})
def body_to_markdown(self):
return markdown.markdown(self.body, extensions=[
'markdown.extensions.extra',
'markdown.extensions.codehilite',
])
def update_views(self):
self.views += 1
self.save(update_fields=['views'])
def get_pre(self):
return Article.objects.filter(id__lt=self.id).order_by('-id').first()
def get_next(self):
return Article.objects.filter(id__gt=self.id).order_by('id').first()
# 幻灯片
class Carousel(models.Model):
number = models.IntegerField('编号', help_text='编号决定图片播放的顺序,图片不要多于5张')
title = models.CharField('标题', max_length=20, blank=True, null=True, help_text='标题可以为空')
content = models.CharField('描述', max_length=80)
image = models.ImageField('轮播图', upload_to='banner/%Y%m')
# img_url = models.CharField('图片地址', max_length=200)
url = models.CharField('跳转链接', max_length=255, default='#', help_text='图片跳转的超链接,默认#表示不跳转')
class Meta:
verbose_name = '图片轮播'
verbose_name_plural = verbose_name
# 编号越小越靠前,添加的时间约晚约靠前
ordering = ['number', '-id']
def __str__(self):
return self.title
python manage.py makemigrations
这里会报错,需要安装其他以来
pip install six
pip install pillow
安装成功后重新执行
python manage.py makemigrations
python manage.py migrate
至此,文章模型创建完毕
修改bolg下urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('article/', include('article.urls', namespace='article')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
修改article下urls.py
# 引入path
from django.urls import path
# 正在部署的应用的名称
app_name = 'article'
urlpatterns = [
# 目前还没有urls
]
python manage.py createsuperuser
修改article 下admin.py
from django.contrib import admin
# 别忘了导入ArticlerPost
from .models import Article, Category, Carousel, Tag, Keyword
# 注册ArticlePost到admin中
admin.site.register(Article)
admin.site.register(Category)
admin.site.register(Carousel)
admin.site.register(Tag)
admin.site.register(Keyword)
至此,启动项目,登录后台,添加测试文章,但是会报错,原因是我们没有注册django-mdeditor
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'mdeditor'
'article',
]
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('mdeditor/', include('mdeditor.urls')),
path('article/', include('article.urls', namespace='article')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
{% load static %}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>{% block head_title %}{% endblock %}_{{ site_end_title }}</title>
{% block metas %}
<meta name="description" content="{{ site_description }}">
<meta name="keywords" content="{{ site_keywords }}">
{% endblock %}
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{% static 'css/adminlte.min.css' %}">
<link rel="stylesheet" href="{% static 'plugins/fontawesome-free/css/all.min.css' %}">
</head>
<body class="hold-transition sidebar-mini layout-fixed">
<div class="wrapper">
<!-- Navbar -->
<nav class="main-header navbar navbar-expand navbar-white navbar-light">
<!-- Left navbar links -->
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" data-widget="pushmenu" href="#" role="button"><i class="fa fa-bars"></i></a>
</li>
<li class="nav-item d-none d-sm-inline-block">
<a href="login.html" class="nav-link">登录页</a>
</li>
<li class="nav-item d-none d-sm-inline-block">
<a href="dashboard.html" class="nav-link">后台主页</a>
</li>
</ul>
<!-- SEARCH FORM -->
<form class="form-inline ml-3">
<div class="input-group input-group-sm">
<input class="form-control form-control-navbar" type="search" placeholder="博客搜索..." aria-label="Search">
<div class="input-group-append">
<button class="btn btn-navbar" type="submit">
<i class="fa fa-search"></i>
</button>
</div>
</div>
</form>
</nav>
<!-- /.navbar -->
<!-- Main Sidebar Container -->
<aside class="main-sidebar sidebar-dark-primary elevation-4">
<!-- Brand Logo -->
<h1>
<a href="index.html" class="brand-link">
<img src="{% static 'upload/avatar.jpg' %}" class="brand-image img-circle elevation-3">
<span class="brand-text font-weight-light">ZengZK's Blog</span>
</a>
</h1>
<!-- Sidebar -->
<div class="sidebar">
<!-- Sidebar Menu -->
<nav class="mt-2">
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu"
data-accordion="false">
<!-- Add icons to the links using the .nav-icon class
with font-awesome or any other icon font library -->
<li class="nav-header">读万卷书</li>
<li class="nav-item">
<a href="index.html" class="nav-link active">
<i class="fa fa-home nav-icon"></i>
<p>首页</p>
</a>
</li>
<li class="nav-item">
<a href="category.html" class="nav-link">
<i class="fa fa-bookmark nav-icon"></i>
<p>分类</p>
</a>
</li>
<li class="nav-item">
<a href="tag.html" class="nav-link">
<i class="fa fa-tags nav-icon"></i>
<p>标签</p>
</a>
</li>
<li class="nav-header">行万里路</li>
<li class="nav-item">
<a href="archive.html" class="nav-link">
<i class="fa fa-archive nav-icon"></i>
<p>归档</p>
</a>
</li>
<li class="nav-header">点滴记录</li>
<li class="nav-item">
<a href="guestbook.html" class="nav-link">
<i class="fa fa-comments nav-icon"></i>
<p>留言</p>
</a>
</li>
</ul>
</nav>
<!-- /.sidebar-menu -->
</div>
<!-- /.sidebar -->
</aside>
{% block base_content %}{% endblock %}
<footer class="main-footer">
<p class="text-center mb-1">
Copyright © 2020 ZengZK Designed by ZengZK Powered by AdminLTE
</p>
<p class="text-center">
<a href="">粤ICP备20040058号</a>
</p>
</footer>
</div>
<!-- ./wrapper -->
<!-- jQuery -->
<script src="{% static 'plugins/jquery/jquery.min.js' %}"></script>
<!-- Bootstrap 4 -->
<script src="{% static 'plugins/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<!-- AdminLTE App -->
<script src="{% static 'js/adminlte.min.js' %}"></script>
<script src="{% static 'js/tooltip.init.js' %}"></script>
</body>
</html>
{% extends "base.html" %}
{% load static %}
{% block head_title %}博客首页{% endblock %}
{% block base_content %}
<div class="content-wrapper mt-3">
<!-- Main content -->
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-md-8">
<div class="card card-teal card-outline mb-5">
<div class="card-header">
<h3 class="card-title float-right">
共 <span class="text-teal text-xl">1</span> 篇博客
</h3>
</div><!-- /.card-header -->
<div class="card-body bg-hover-gray">
<div class="mb-1">
<a href="detail.html" target="_blank" class="text-lg text-bold link-title">我是一只猫,快乐的星猫,一起喵喵喵</a>
<span class="badge badge-info">原创</span>
</div>
<p>
Lorem ipsum represents a long-held tradition for designers,
typographers and the like. Some people hate it and argue for
its demise, but others ignore the hate as they create awesome
tools to help create filler text for everyone from bacon lovers
to Charlie Sheen fans.
</p>
<p>
<span class="text-sm mr-2"><i class="far fa-calendar-alt mr-1"></i> 2019-01-01 10:08</span>
<span class="text-sm"><i class="far fa-eye mr-1"></i> 10</span>
</p>
<p class="mb-0">
<button class="btn btn-outline-success btn-xs">分类</button>
<button class="btn btn-outline-primary btn-xs">标签1</button>
<button class="btn btn-outline-primary btn-xs">标签2</button>
</p>
</div><!-- /.card-body -->
<hr class="m-0">
<div class="card-body bg-hover-gray">
<div class="mb-1">
<a href="detail.html" target="_blank" class="text-lg text-bold link-title">我是一只猫,快乐的星猫,一起喵喵喵</a>
<span class="badge badge-info">原创</span>
</div>
<p>
Lorem ipsum represents a long-held tradition for designers,
typographers and the like. Some people hate it and argue for
its demise, but others ignore the hate as they create awesome
tools to help create filler text for everyone from bacon lovers
to Charlie Sheen fans.
</p>
<p>
<span class="text-sm mr-2"><i class="far fa-calendar-alt mr-1"></i> 2019-01-01 10:08</span>
<span class="text-sm"><i class="far fa-eye mr-1"></i> 10</span>
</p>
<p class="mb-0">
<button class="btn btn-outline-success btn-xs">分类</button>
<button class="btn btn-outline-primary btn-xs">标签1</button>
<button class="btn btn-outline-primary btn-xs">标签2</button>
</p>
</div><!-- /.card-body -->
<hr class="m-0">
<div class="card-body bg-hover-gray">
<div class="mb-1">
<a href="detail.html" target="_blank" class="text-lg text-bold link-title">我是一只猫,快乐的星猫,一起喵喵喵</a>
<span class="badge badge-info">原创</span>
</div>
<p>
Lorem ipsum represents a long-held tradition for designers,
typographers and the like. Some people hate it and argue for
its demise, but others ignore the hate as they create awesome
tools to help create filler text for everyone from bacon lovers
to Charlie Sheen fans.
</p>
<p>
<span class="text-sm mr-2"><i class="far fa-calendar-alt mr-1"></i> 2019-01-01 10:08</span>
<span class="text-sm"><i class="far fa-eye mr-1"></i> 10</span>
</p>
<p class="mb-0">
<button class="btn btn-outline-success btn-xs">分类</button>
<button class="btn btn-outline-primary btn-xs">标签1</button>
<button class="btn btn-outline-primary btn-xs">标签2</button>
</p>
</div><!-- /.card-body -->
<hr class="m-0">
<div class="card-body bg-hover-gray">
<div class="mb-1">
<a href="detail.html" target="_blank" class="text-lg text-bold link-title">我是一只猫,快乐的星猫,一起喵喵喵</a>
<span class="badge badge-info">原创</span>
</div>
<p>
Lorem ipsum represents a long-held tradition for designers,
typographers and the like. Some people hate it and argue for
its demise, but others ignore the hate as they create awesome
tools to help create filler text for everyone from bacon lovers
to Charlie Sheen fans.
</p>
<p>
<span class="text-sm mr-2"><i class="far fa-calendar-alt mr-1"></i> 2019-01-01 10:08</span>
<span class="text-sm"><i class="far fa-eye mr-1"></i> 10</span>
</p>
<p class="mb-0">
<button class="btn btn-outline-success btn-xs">分类</button>
<button class="btn btn-outline-primary btn-xs">标签1</button>
<button class="btn btn-outline-primary btn-xs">标签2</button>
</p>
</div><!-- /.card-body -->
<hr class="m-0">
<div class="card-body bg-hover-gray">
<div class="mb-1">
<a href="detail.html" target="_blank" class="text-lg text-bold link-title">我是一只猫,快乐的星猫,一起喵喵喵</a>
<span class="badge badge-info">原创</span>
</div>
<p>
Lorem ipsum represents a long-held tradition for designers,
typographers and the like. Some people hate it and argue for
its demise, but others ignore the hate as they create awesome
tools to help create filler text for everyone from bacon lovers
to Charlie Sheen fans.
</p>
<p>
<span class="text-sm mr-2"><i class="far fa-calendar-alt mr-1"></i> 2019-01-01 10:08</span>
<span class="text-sm"><i class="far fa-eye mr-1"></i> 10</span>
</p>
<p class="mb-0">
<button class="btn btn-outline-success btn-xs">分类</button>
<button class="btn btn-outline-primary btn-xs">标签1</button>
<button class="btn btn-outline-primary btn-xs">标签2</button>
</p>
</div><!-- /.card-body -->
<hr class="m-0">
<div class="card-body bg-hover-gray">
<div class="mb-1">
<a href="detail.html" target="_blank" class="text-lg text-bold link-title">我是一只猫,快乐的星猫,一起喵喵喵</a>
<span class="badge badge-info">原创</span>
</div>
<p>
Lorem ipsum represents a long-held tradition for designers,
typographers and the like. Some people hate it and argue for
its demise, but others ignore the hate as they create awesome
tools to help create filler text for everyone from bacon lovers
to Charlie Sheen fans.
</p>
<p>
<span class="text-sm mr-2"><i class="far fa-calendar-alt mr-1"></i> 2019-01-01 10:08</span>
<span class="text-sm"><i class="far fa-eye mr-1"></i> 10</span>
</p>
<p class="mb-0">
<button class="btn btn-outline-success btn-xs">分类</button>
<button class="btn btn-outline-primary btn-xs">标签1</button>
<button class="btn btn-outline-primary btn-xs">标签2</button>
</p>
</div><!-- /.card-body -->
<hr class="m-0">
<div class="card-body bg-hover-gray">
<div class="mb-1">
<a href="detail.html" target="_blank" class="text-lg text-bold link-title">我是一只猫,快乐的星猫,一起喵喵喵</a>
<span class="badge badge-info">原创</span>
</div>
<p>
Lorem ipsum represents a long-held tradition for designers,
typographers and the like. Some people hate it and argue for
its demise, but others ignore the hate as they create awesome
tools to help create filler text for everyone from bacon lovers
to Charlie Sheen fans.
</p>
<p>
<span class="text-sm mr-2"><i class="far fa-calendar-alt mr-1"></i> 2019-01-01 10:08</span>
<span class="text-sm"><i class="far fa-eye mr-1"></i> 10</span>
</p>
<p class="mb-0">
<button class="btn btn-outline-success btn-xs">分类</button>
<button class="btn btn-outline-primary btn-xs">标签1</button>
<button class="btn btn-outline-primary btn-xs">标签2</button>
</p>
</div><!-- /.card-body -->
<hr class="m-0">
<div class="card-footer clearfix">
<ul class="pagination m-0 float-right">
<li class="page-item"><a class="page-link" href="#"><i class="fa fa-angle-left"></i></a>
</li>
<li class="page-item active"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#"><i
class="fa fa-angle-right"></i></a></li>
</ul>
</div><!-- /.card-footer -->
</div>
<!-- /.nav-tabs-custom -->
</div>
<!-- /.col -->
<div class="col-md-4">
<!-- Profile Image -->
<div class="card widget-user sticky-top">
<!-- Add the bg color to the header using any of the bg-* classes -->
<div class="widget-user-header bg-info">
<h3 class="widget-user-username">ZengZK</h3>
<h5 class="widget-user-desc">Student & Coder</h5>
</div>
<div class="widget-user-image">
<img class="img-circle elevation-2" src="{% static 'upload/avatar.jpg' %}"
alt="User Avatar">
</div>
<div class="card-body pt-5">
<p class="text-muted">
一个Java初学者,一个热爱编程的人,希望能在0与1的世界与您相遇,结伴而行!
</p>
<ul class="list-group list-group-unbordered">
<li class="list-group-item">
<strong><i class="far fa-bookmark mr-2"></i>推荐文章</strong>
<a href="" class="d-block link-title text-truncate">Java学习路线Java学习路线Java学习路线Java学习路线</a>
<a href="" class="d-block link-title">Java学习路线</a>
<a href="" class="d-block link-title">Java学习路线</a>
</li>
<li class="list-group-item">
<strong><i class="fa fa-map-marker-alt mr-2"></i>位置</strong>
<div class="text-muted">Malibu, California</div>
</li>
<li class="list-group-item">
<strong><i class="fa fa-pencil-alt mr-2"></i>技能</strong>
<div class="text-muted">
<span class="badge badge-success">UI Design</span>
<span class="badge badge-success">Coding</span>
<span class="badge badge-success">Javascript</span>
<span class="badge badge-success">PHP</span>
<span class="badge badge-success">Node.js</span>
</div>
</li>
<li class="list-group-item">
<strong><i class="fa fa-lightbulb mr-2"></i>爱好</strong>
<div class="text-muted">
<span class="badge badge-warning">编程</span>
<span class="badge badge-warning">学习</span>
</div>
</li>
<li class="list-group-item text-center">
<button class="btn btn-success btn-sm rounded-circle" data-toggle="tooltip"
data-placement="top"
title="939234206">
<i class="fab fa-qq"></i>
</button>
<button class="btn btn-success btn-sm rounded-circle" data-toggle="tooltip"
data-placement="top"
title="939234206">
<i class="fab fa-weixin"></i>
</button>
<a href="http://www.baidu.com" target="_blank"
class="btn btn-success btn-sm rounded-circle" data-toggle="tooltip"
data-placement="top"
title="github">
<i class="fab fa-github text-white"></i>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<!-- /.col -->
<!-- /.row -->
</div><!-- /.container-fluid -->
</section>
<!-- /.content -->
</div>
{% endblock %}