Django手撸一个博客项目

1、settings.py

import os


BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '$!td*pims7bsnb%&jhfov9x3pq7vrh2)is*8@9+uxpwlrz4de-'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog.apps.BlogConfig',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'BBS_11_09.urls'

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',
            ],
        },
    },
]

WSGI_APPLICATION = 'BBS_11_09.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = False


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

AUTH_USER_MODEL = 'blog.User'

LOGIN_URL = '/login/'

2、urls.py

"""BBS_11_09 URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, re_path
from blog import views
from django.views.static import serve
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('register/', views.register, name='register'),
    path('login/', views.login, name='login'),
    path('logout/', views.logout, name='logout'),
    path('get_valid_code/', views.get_valid, name='get_valid'),
    path('home/', views.home, name='home'),
    path('comment_content/', views.comment_content, name='comment_content'),
    path('diggit/', views.diggit, name='diggit'),
    path('backend/', views.backend, name='backend'),
    path('change_pwd/', views.change_pwd, name='change_pwd'),
    path('add_article/', views.add_article, name='add_article'),
    path('update_head/', views.update_head, name='update_head'),
    re_path('^check_user/', views.check_user, name='check_user'),
    re_path('^delete/(?P<id>\d+)', views.delete, name='delete'),
    re_path('^update_article/(?P<id>\d+)', views.update_article, name='update_article'),
    re_path(r'^blogsite/(?P<name>\w+)/(?P<query>category|tag|archive)/(?P<condition>.*?).html$', views.blogsite),
    re_path(r'^blogsite/(?P<name>\w+)/$', views.blogsite,),
    re_path(r'^(?P<name>\w+)/article_detail/(?P<id>\d+).html', views.article_detail),
    re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT})

]

3、templatags.py

from django.template import library
from blog import models
from django.db.models import Count
from django.db.models.functions import TruncMonth

register = library.Library()


@register.inclusion_tag('left.html')
def left(name):
    user = models.User.objects.filter(username=name).first()
    category_list = models.Category.objects.filter(blog=user.blog).annotate(num=Count('article__id')).values_list(
        'name',
        'num',
        'id')
    tag_list = models.Tag.objects.filter(blog=user.blog).annotate(num=Count('article__id')).values_list('name', 'num',
                                                                                                        'id')
    month_list = models.Article.objects.filter(blog=user.blog).annotate(month=TruncMonth('create_time')).values(
        'month').annotate(num=Count('pk')).order_by('-month').values_list('month', 'num')
    return {'name': name, 'category_list': category_list, 'tag_list': tag_list, 'month_list': month_list}


@register.inclusion_tag('backend/backleft.html')
def backleft(request):
    res_category = models.Category.objects.filter(blog=request.user.blog).annotate(num=Count('article__id')).values_list(
        'name', 'num', 'id')
    name = request.user.username
    return {'res_category': res_category, 'name': name}

4、blogform.py

from django import forms
from django.forms import widgets


class UserForm(forms.Form):
    username = forms.CharField(max_length=18, min_length=3, label='用户名',
                               widget=widgets.TextInput(attrs={'class': 'form-control'}), error_messages={
            'max_length': '最长18位', 'min_length': '最短3位', 'required': '该字段必填'
        })
    password = forms.CharField(max_length=18, min_length=3, label='密码',
                               widget=widgets.PasswordInput(attrs={'class': 'form-control'}), error_messages={
            'max_length': '最长18位', 'min_length': '最短3位', 'required': '该字段必填'
        })
    re_password = forms.CharField(max_length=18, min_length=3, label='确认密码',
                                  widget=widgets.PasswordInput(attrs={'class': 'form-control'}), error_messages={
            'max_length': '最长18位', 'min_length': '最短3位', 'required': '该字段必填'
        })
    email = forms.EmailField(label='邮箱', widget=widgets.EmailInput(attrs={'class': 'form-control'}),
                             error_messages={'required': '该字段必填', 'invalid': '格式不正确'})
    phone = forms.CharField(max_length=18, min_length=3, label='手机号',
                            widget=widgets.TextInput(attrs={'class': 'form-control'}), error_messages={
            'max_length': '最长18位', 'min_length': '最短3位', 'required': '该字段必填'
        })

    def clean(self):
        password = self.cleaned_data.get('password')
        re_password = self.cleaned_data.get('re_password')
        if password != re_password:
            self.add_error('re_password', '两次密码不一致')
        return self.cleaned_data

5、models.py

from django.db import models
from django.contrib.auth.models import AbstractUser


# Create your models here.


class User(AbstractUser):
    phone = models.CharField(max_length=15, verbose_name='电话号码')
    head = models.FileField(default='head/default.png', upload_to='head/', verbose_name='头像')
    blog = models.OneToOneField(to='Blog', verbose_name='关联博客', on_delete=models.CASCADE, null=True)


class Blog(models.Model):
    site_title = models.CharField(max_length=32, verbose_name='站点标题')
    site_name = models.CharField(max_length=32, verbose_name='站点名称')
    site_style = models.CharField(max_length=32, verbose_name='站点样式')

    def __str__(self):
        return self.site_title


class Category(models.Model):
    name = models.CharField(max_length=32, verbose_name='分类名称')
    blog = models.ForeignKey(to='Blog', verbose_name='关联博客', on_delete=models.CASCADE)

    def __str__(self):
        return self.name


class Tag(models.Model):
    name = models.CharField(max_length=32, verbose_name='标签名称')
    blog = models.ForeignKey(to='Blog', verbose_name='关联博客', on_delete=models.CASCADE)

    def __str__(self):
        return self.name


class Article(models.Model):
    name = models.CharField(max_length=32, verbose_name='文章名称')
    description = models.CharField(max_length=128, verbose_name='文章描述')
    content = models.TextField(verbose_name='文章内容')
    create_time = models.DateTimeField(auto_now_add=True, null=True)
    up_num = models.IntegerField(verbose_name='点赞数', default=0)
    down_num = models.IntegerField(verbose_name='点踩数', default=0)
    commit_num = models.IntegerField(verbose_name='评论数', default=0)
    blog = models.ForeignKey(to='Blog', verbose_name='关联博客', on_delete=models.CASCADE, null=True)
    category = models.ForeignKey(to='Category', verbose_name='关联分类', on_delete=models.CASCADE)
    tag = models.ManyToManyField(to='Tag', verbose_name='关联标签')

    def __str__(self):
        return self.name


class Commit(models.Model):
    content = models.CharField(max_length=128, verbose_name='评论内容')
    create_time = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(to='User', verbose_name='关联用户', on_delete=models.CASCADE)
    article = models.ForeignKey(to='Article', verbose_name='关联文章', on_delete=models.CASCADE)
    commit_self = models.ForeignKey(to='self', verbose_name='子评论', on_delete=models.CASCADE, null=True)


class UpAndDown(models.Model):
    user = models.ForeignKey(to='User', verbose_name='关联用户', on_delete=models.CASCADE)
    article = models.ForeignKey(to='Blog', verbose_name='关联文章', on_delete=models.CASCADE)
    is_up = models.BooleanField(verbose_name='点赞点踩')

6、utils.py

class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        封装分页相关数据
        :param current_page: 当前页
        :param all_count:    数据库中的数据总条数
        :param per_page_num: 每页显示的数据条数
        :param pager_count:  最多显示的页码个数
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        if current_page < 1:
            current_page = 1

        self.current_page = current_page

        self.all_count = all_count
        self.per_page_num = per_page_num

        # 总页码
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager

        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num

    def page_html(self):
        # 如果总页码 < 11个:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 总页码  > 11
        else:
            # 当前页如果<=页面上最多显示11/2个页码
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # 当前页大于5
            else:
                # 页码翻到最后
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []
        # 添加前面的nav和ul标签
        page_html_list.append('''
                    <nav aria-label='Page navigation>'
                    <ul class='pagination'>
                ''')
        first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)

        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加标签
        page_html_list.append('''
                                           </nav>
                                           </ul>
                                       ''')
        return ''.join(page_html_list)

7、views.py

import random
import json
import os
from django.shortcuts import render, HttpResponse, redirect, reverse
from blog import blogform, models, utils
from django.http import JsonResponse
from PIL import Image, ImageFont, ImageDraw
from io import BytesIO
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.db.models import Count, F
from django.db import transaction
from bs4 import BeautifulSoup
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings


# Create your views here.
def check_user(request):
    dic = {'code': 100, 'msg': '用户名合格'}
    username = request.GET.get('name')
    print(username)
    user = models.User.objects.filter(username=username).count()
    if user:
        dic['code'] = 101
        dic['msg'] = '该用户已存在'
    return JsonResponse(dic)


def register(request):
    if request.method == 'GET':
        form = blogform.UserForm()
        return render(request, 'register.html', {'form': form})
    else:
        dic = {'code': 100, 'msg': '创建成功'}
        form = blogform.UserForm(request.POST)
        if form.is_valid():
            data = form.cleaned_data
            file = request.FILES.get('head')
            user = models.User.objects.filter(username=data.get('username')).count()
            if user:
                dic['code'] = 102
                dic['msg'] = '用户已存在'
            else:
                if file:
                    data['head'] = file
                data.pop('re_password')
                models.User.objects.create_user(**data)
                dic['url'] = reverse('login')
        else:
            dic['code'] = 101
            dic['error'] = form.errors
        return JsonResponse(dic)


def get_rgb():
    return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))


def get_valid(request):
    img = Image.new('RGB', (160, 50), (255, 255, 255))
    img_draw = ImageDraw.Draw(img)
    img_font = ImageFont.truetype('./static/font/stratum2black.otf', 40)
    valid_code = ''
    for i in range(5):
        low_chr = chr(random.randint(97, 122))
        num = random.randint(0, 9)
        upper_chr = chr(random.randint(65, 90))
        res = str(random.choice([low_chr, num, upper_chr]))
        valid_code += res
        img_draw.text((i * 30 + 10, 8), res, get_rgb(), img_font)
    #  随机验证码存到session里
    request.session['valid_code'] = valid_code
    # 画线和点圈
    width = 160
    height = 50
    for i in range(3):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        # 在图片上画线
        img_draw.line((x1, y1, x2, y2), fill=get_rgb())

    for i in range(50):
        # 画点
        img_draw.point([random.randint(0, width), random.randint(0, height)], fill=get_rgb())
        x = random.randint(0, width)
        y = random.randint(0, height)
        # 画弧形
        img_draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_rgb())
    # 验证码写到内存,不写到硬盘
    f = BytesIO()
    img.save(f, 'png')
    #  读取内存中图片的二进制,传到前端
    data = f.getvalue()
    return HttpResponse(data)


def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        dic = {'code': 100, 'msg': ''}
        username = request.POST.get('username')
        password = request.POST.get('password')
        valid_code = request.POST.get('valid_code')
        print(valid_code)
        if valid_code.lower() == request.session.get('valid_code').lower():
            user = auth.authenticate(username=username, password=password)
            if user:
                auth.login(request, user)
                dic['url'] = reverse('home')
            else:
                dic['code'] = 101
                dic['msg'] = '用户名或密码错误'
        else:
            dic['code'] = 102
            dic['msg'] = '验证码错误'
        return JsonResponse(dic)


def logout(request):
    if request.user.is_authenticated:
        auth.logout(request)
        return redirect(reverse('home'))


def change_pwd(request):
    dic = {'code': 100, 'message': ''}
    if request.is_ajax():
        old_pwd = request.POST.get('old_pwd')
        new_pwd = request.POST.get('new_pwd')
        re_new_pwd = request.POST.get('re_new_pwd')
        if request.user.check_password(old_pwd):
            if new_pwd == re_new_pwd:
                request.user.set_password(new_pwd)
                dic['message'] = '修改成功'
                dic['url'] = reverse('login')
            else:
                dic['code'] = 101
                dic['message'] = '两次密码不一致'
        else:
            dic['code'] = 102
            dic['message'] = '旧密码不正确'
        return JsonResponse(dic)


def home(request):
    if request.method == 'GET':
        ll = [{'url': 'http://www.baidu.com',
               'img_url': '/static/img/banner1.jpg',
               'message': '火热广告招商'},
              {'url': 'http://www.bilibili.com',
               'img_url': '/static/img/banner2.jpg',
               'message': '体验游戏人生'},
              {'url': 'http://www.xiaomi.com',
               'img_url': '/static/img/banner3.jpg',
               'message': '点我有你好看'},
              ]
        article_list = models.Article.objects.all().order_by('-create_time')
        current_page = request.GET.get('page', 1)
        all_count = article_list.count()
        page_obj = utils.Pagination(current_page=current_page, all_count=all_count, per_page_num=2)
        page_queryset = article_list[page_obj.start:page_obj.end]
        return render(request, 'home.html', {'page_obj': page_obj, 'page_queryset': page_queryset, 'll': ll})


def blogsite(request, name, **kwargs):
    if request.method == 'GET':
        user = models.User.objects.filter(username=name).first()
        if user:
            article_list = models.Article.objects.filter(blog=user.blog)
            query = kwargs.get('query')
            condition = kwargs.get('condition')
            if query == 'category':
                article_list = models.Article.objects.filter(category_id=condition)
            elif query == 'tag':
                article_list = models.Article.objects.filter(tag__id=condition)
            elif query == 'archive':
                year, month = kwargs.get('condition').split('/')
                article_list = models.Article.objects.filter(create_time__year=year, create_time__month=month)
            current_page = request.GET.get('page', 1)
            all_count = article_list.count()
            page_obj = utils.Pagination(current_page=current_page, all_count=all_count, per_page_num=2)
            page_queryset = article_list[page_obj.start:page_obj.end]
            return render(request, 'blogsite.html', locals())
        else:
            return HttpResponse('404')


def article_detail(request, name, id):
    if request.method == 'GET':
        user = models.User.objects.filter(username=name).first()
        if user:
            article = models.Article.objects.get(id=id)
            commit_list = models.Commit.objects.filter(user_id=user.id)
            return render(request, 'article_detail.html',
                          {'user': user, 'article': article, 'commit_list': commit_list})


def diggit(request):
    if request.is_ajax():
        dic = {'code': 100, 'msg': ''}
        if request.user.is_authenticated:
            is_up = json.loads(request.POST.get('is_up'))
            article_id = request.POST.get('article_id')
            user = request.user
            res = models.UpAndDown.objects.filter(article_id=article_id, user_id=user.id).count()
            if res:
                dic['code'] = 102
                dic['msg'] = '已评论,无法再次评论'
            else:
                with transaction.atomic():
                    models.UpAndDown.objects.create(is_up=is_up, article_id=article_id, user_id=user.id)
                    if is_up:
                        models.Article.objects.filter(id=article_id).update(up_num=F('up_num') + 1)
                        dic['msg'] = '点赞成功'
                    else:
                        models.Article.objects.filter(id=article_id).update(down_num=F('down_num') + 1)
                        dic['msg'] = '点踩成功'
        else:
            dic['code'] = 101
            dic['msg'] = '请先<a href="/login/">登录</a>'
        return JsonResponse(dic)


def comment_content(request):
    dic = {'code': 100, 'msg': ''}
    if request.is_ajax():
        if request.user.is_authenticated:
            content = request.POST.get('commit')
            article_id = request.POST.get('article_id')
            parent_id = request.POST.get('parent_id')
            # if not parent_id:
            #     parent_id = 'Null'
            user = request.user
            with transaction.atomic():
                if parent_id:
                    commits = models.Commit.objects.create(article_id=article_id, user_id=user.id, content=content,
                                                       commit_self_id=parent_id)
                else:
                    commits = models.Commit.objects.create(article_id=article_id, user_id=user.id, content=content)
                models.Article.objects.filter(id=article_id).update(commit_num=F('commit_num') + 1)
            dic['content'] = commits.content
            dic['msg'] = '评论成功'
            dic['username'] = user.username
            if parent_id:
                dic['parent_name'] = commits.commit_self.user.username
    else:
        dic['code'] = 101
        dic['msg'] = '请先<a href="/login/">登录</a>'
    return JsonResponse(dic)


@login_required
def backend(request):
    if request.method == 'GET':
        if request.user.is_authenticated:
            article_list = models.Article.objects.filter(blog=request.user.blog)
            current_page = request.GET.get('page', 1)
            all_count = article_list.count()
            page_obj = utils.Pagination(current_page=current_page, all_count=all_count, per_page_num=2)
            page_queryset = article_list[page_obj.start:page_obj.end]
            return render(request, 'backend/backend.html', locals())


@login_required
def add_article(request):
    if request.method == 'GET':
        category_list = models.Category.objects.filter(blog=request.user.blog)
        tag_list = models.Tag.objects.filter(blog=request.user.blog)
        return render(request, 'backend/add_article.html', locals())
    else:
        name = request.POST.get('name')
        content = request.POST.get('content')
        category_id = request.POST.get('category')
        description = content[:20]
        tag_list = request.POST.getlist('tag')
        soup = BeautifulSoup(content, 'html.parser')
        description = soup.text[:30]
        res_script = soup.find_all('script')
        for script in res_script:
            script.decompose()
        article = models.Article.objects.create(name=name, content=str(soup), category_id=category_id,
                                                blog=request.user.blog,
                                                description=description)
        article.tag.add(tag_list)
        return redirect(reverse('backend'))


@csrf_exempt
def upload_img(request):
    dic = {'error': 0}
    try:
        file = request.FILES.get('myfile')
        path = os.path.join(settings.BASE_DIR, 'media', 'img', file.name)
        with open(path, 'wb') as f:
            for line in file.chunks():
                f.write(line)
        dic['url'] = '/media/img' + file.name
    except Exception as e:
        dic['error'] = 1
        dic['message'] = str(e)
    return JsonResponse(dic)


@login_required
def update_head(request):
    if request.method == 'GET':
        return render(request, 'backend/update_head.html')
    else:
        file = request.FILES.get('myhead')
        models.User.objects.filter(id=request.user.id).update(head=file)
        return redirect(reverse('backend'))


@login_required
def delete(request, id):
    models.Article.objects.filter(id=id).delete()
    return redirect(reverse('backend'))


@login_required
def update_article(request, id):
    article = models.Article.objects.get(id=id)
    if request.method == 'GET':
        category_list = models.Category.objects.filter(blog=request.user.blog)
        tag_list = models.Tag.objects.filter(blog=request.user.blog)
        return render(request, 'backend/update_article.html', locals())
    else:
        name = request.POST.get('name')
        content = request.POST.get('content')
        category_id = request.POST.get('category')
        description = content[:20]
        tag_list = request.POST.getlist('tag')
        if len(tag_list) < 2:
            tag_list = request.POST.get('tag')
        soup = BeautifulSoup(content, 'html.parser')
        description = soup.text[:30]
        res_script = soup.find_all('script')
        for script in res_script:
            script.decompose()
        article.name = name
        article.content = content
        article.category_id = category_id
        article.description = str(soup)
        article.tag.clear()
        article.tag.add(*tag_list)
        article.save()
        return redirect(reverse('backend'))

8、register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册界面</title>
    {% load static %}
    <script src="{% static 'jquery-3.3.1/jquery-3.3.1.min.js' %}"></script>
    <link href="{% static 'bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
    <link href="{% static '/font-awesome-4.7.0/font-awesome-4.7.0/css/font-awesome.css' %}" rel="stylesheet">
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <h2 class="text-center">注册界面</h2>
        <div class="col-md-6 col-md-offset-3">
            <form action="" enctype="multipart/form-data" id="form" novalidate>
                {% csrf_token %}
                {% for foo in form %}
                    <div class="form-group">
                        {{ foo.label }}
                        {{ foo }}
                        <span class="text-danger pull-right"></span>
                    </div>
                {% endfor %}
                <div class="form-group">
                    <label for="head">头像<img src="/static/img/default.png" width="80" height="80" alt="" id="head_img"></label>
                    <input type="file" id="head" style="display: none">
                </div>
                <div class="text-center">
                    <button class="btn-lg btn btn-success " type="button" id="btn">提交</button>
                </div>
            </form>
        </div>
    </div>
</div>
<script>
    $('#head').change(function () {
        let fileread = new FileReader()
        fileread.readAsDataURL(this.files[0])
        fileread.onload = function () {
            console.log(fileread.result)
            $('#head_img').attr('src', fileread.result)
        }
    })
    $('#btn').click(function () {
        let formdata = new FormData()
        formdata.append('head', $('#head')[0].files[0])
        let formlist = $('#form').serializeArray()
        $.each(formlist, function (k, v) {
            formdata.append(v.name, v.value)
        })
        $.ajax({
            url: '',
            method: 'post',
            data: formdata,
            processData: false,
            contentType: false,
            success: function (data) {
                if (data.code === 100) {
                    location.href = data.url
                } else {
                    $.each(data.error, function (k, v) {
                        console.log(k, v)
                        $('#id_' + k).next().text(v)
                        setTimeout(function () {
                            $('#id_' + k).next().text('')
                        }, 3000)
                    })
                }
            }
        })
    })
    $('#id_username').blur(function () {
        let name = $(this).val()
        $.ajax({
            url: '/check_user/?name=' + name,
            method: 'get',
            success: function (data) {
                $(this).next().text(data.msg)
                setTimeout(function () {
                    $(this).next().text('')
                }, 3000)
            }
        })
    })
</script>
</body>
</html>

9、login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录界面</title>
    {% load static %}
    <script src="{% static 'jquery-3.3.1/jquery-3.3.1.min.js' %}"></script>
    <link href="{% static 'bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3 ">
            <h1 class="form-signin-heading" style="color: palevioletred">用户登录</h1>
            <form action="" id="form">
                {% csrf_token %}
                <br>
                <div class="form-group">
                    <label style="font-size: 20px; color: darkturquoise" for="username">账号</label>
                    <input type="text" class="form-control" name="username" id="username">
                </div>
                <div class="form-group">
                    <label style="font-size: 20px; color: darkturquoise" for="password">密码</label>
                    <input type="password" class="form-control" name="password" id="password">
                </div>
                <br>
                <div class="form-group">
                    <label style="font-size: 20px; color: darkturquoise" for="valid_code">验证码</label>
                    <input type="text" class="f" name="valid_code" id="valid_code">
                    <img src="/get_valid_code/" id="valid_img" style="height: 50px;width: 160px" class="pull-right">
                </div>
                <br>
                <div class="text-center">
                    <span class="text-danger" id="span_error"></span>
                    <br>
                    <button type="button" class="btn btn-success btn-lg" id="btn">登录</button>
                </div>
            </form>
        </div>
    </div>
</div>


<script>
    $('#btn').click(function () {
        $.ajax({
            url: '/login/',
            method: 'post',
            data: {
                'username': $('#username').val(),
                'password': $('#password').val(),
                'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val(),
                'valid_code': $('#valid_code').val()
            },
            success: function (data) {
                if (data.code !== 100) {
                    $('#span_error').text(data.msg)
                    setTimeout(function () {
                        $('span').text('')
                    }, 3000)
                } else {
                    location.href = data.url
                }
            }
        })
    })
    $('#valid_img').click(function () {
        var path_img = $(this).attr('src') + '?'
        $(this).attr('src', path_img)
    })
</script>
</body>
</html>

10、left.html

<!--个人博客左侧-->
<div class="text-center">
    <div class="panel panel-danger">
        <div class="panel-heading">
            <h3 class="panel-title">我的标签</h3>
        </div>
        <div class="panel-body">
            {% for tag in tag_list %}
                <p><a href="/blogsite/{{ name }}/tag/{{ tag.2 }}.html">{{ tag.0 }}&nbsp;({{ tag.1 }})</a></p>
            {% endfor %}
        </div>
    </div>
    <div class="panel panel-info">
        <div class="panel-heading">
            <h3 class="panel-title">随笔分类</h3>
        </div>
        <div class="panel-body">
            {% for category in category_list %}
                <p><a href="/blogsite/{{ name }}/category/{{ category.2 }}.html">{{ category.0 }}&nbsp;({{ category.1 }})</a>
                </p>
            {% endfor %}
        </div>
    </div>
    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">随笔档案</h3>
        </div>
        {% for month in month_list %}
            <p><a href="/blogsite/{{ name }}/archive/{{ month.0|date:'Y/m' }}.html">
                {{ month.0|date:'Y年m月' }}&nbsp;({{ month.1 }})</a></p>
        {% endfor %}
    </div>
</div>

11、home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>博客园首页</title>
    {% load static %}
    <script src="{% static 'jquery-3.3.1/jquery-3.3.1.min.js' %}"></script>
    <link href="{% static 'bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</head>
<body>
<!--顶部导航条-->
<div class="navbar-wrapper">
    <div class="">
        <nav class="navbar navbar-inverse navbar-static-top">
            <div id="navbar" class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="#">博客园首页</a></li>
                    <li class="active"><a href="/home/">首页</a></li>
                    <li><a href="#">历史记录</a></li>
                    <!--搜索框-->
                    <li style="margin-left: 100px">
                        <form class="navbar-form navbar-left" role="search">
                            <div class="form-group">
                                <input type="text" class="form-control" placeholder="输入关键词">
                            </div>
                            <button type="submit" class="btn btn-default btn-warning">搜索</button>
                        </form>
                    </li>
                    <!--右侧登录等按钮-->
                    {% if request.user.is_authenticated %}
                        <li>
                            <button type="button" class="btn btn-primary" data-toggle="modal"
                                    style="margin-top: 10px;margin-left: 450px"
                                    data-target="#exampleModal" data-whatever="@mdo">修改密码
                            </button>

                        </li>
                        <li>
                            <button id="logout" type="button" class="btn btn-info"
                                    style="margin-top: 10px;margin-left: 10px">注销
                            </button>
                        </li>
                        <li>
                            <button id="backend" type="button" class="btn btn-success"
                                    style="margin-top: 10px;margin-left: 10px">后台管理
                            </button>
                        </li>
                    {% else %}
                        <li>
                            <button id="register" type="button" class="btn btn-success"
                                    style="margin-top: 10px;margin-left: 450px">注册
                            </button>
                        </li>
                        <li>
                            <button id="login" type="button" class="btn btn-info"
                                    style="margin-top: 10px;margin-left: 10px">登录
                            </button>
                        </li>
                    {% endif %}
                </ul>

            </div>
        </nav>
    </div>
</div>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog"
     aria-labelledby="exampleModalLabel">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title" id="exampleModalLabel">修改密码</h4>
            </div>
            <!--修改密码的模态框-->
            <div class="modal-body">
                <form id="form_pwd">
                    {% csrf_token %}
                    <div class="form-group">
                        <label for="old_pwd" class="control-label">旧密码:
                        </label>
                        <input type="password" id="old_pwd" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="new_pwd" class="control-label">新密码:</label>
                        <input type="password" id="new_pwd" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="re_new_pwd" class="control-label">确认新密码:
                        </label>
                        <input type="password" id="re_new_pwd" class="form-control">
                    </div>
                </form>
            </div>
            <div class="text-center" style="height: 10px">
                <sapn class="text-danger"></sapn>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">取消修改
                </button>
                <button type="button" class="btn btn-primary" id="btn_pwd">提交修改</button>
            </div>
        </div>
    </div>
</div>

<div class="container-fluid">
    <div class="row">
        <div class="col-md-2" id="blog_right">
            <div class="panel panel-danger">
                <div class="panel-heading">
                    <h3 class="panel-title">关注</h3>
                </div>
                <div class="panel-body">
                    详情点击:<a href="">我评</a>
                    <hr>
                    详情点击:<a href="">我赞</a>
                </div>
            </div>
            <div class="panel panel-info">
                <div class="panel-heading">
                    <h3 class="panel-title">精华</h3>
                </div>
                <div class="panel-body">
                    详情点击:<a href="">候选</a>
                    <hr>
                    详情点击:<a href="">订阅</a>
                </div>
            </div>
            <div class="panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">广告招商</h3>
                </div>
                <div class="panel-body">
                    详情点击:<a href="">百度</a>
                    <hr>
                    详情点击:<a href="">腾讯</a>
                </div>
            </div>
            <div class="panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">广告招商</h3>
                </div>
                <div class="panel-body">
                    详情点击:<a href="">百度</a>
                    <hr>
                    详情点击:<a href="">腾讯</a>
                </div>
            </div>
            <div class="panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">广告招商</h3>
                </div>
                <div class="panel-body">
                    详情点击:<a href="">百度</a>
                    <hr>
                    详情点击:<a href="">腾讯</a>
                </div>
            </div>
        </div>
        <!--博客中部-->
        <div class="col-md-7" id="blog_middle">
            <!--顶部轮播图-->
            <div class="lbt">
                <div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
                    <!-- 图片翻页 -->
                    <ol class="carousel-indicators">
                        <li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
                        <li data-target="#carousel-example-generic" data-slide-to="1"></li>
                        <li data-target="#carousel-example-generic" data-slide-to="2"></li>
                    </ol>
                    <!-- 轮播图片 -->
                    <div class="carousel-inner" role="listbox">
                        <div class="item active">
                            <a href="{{ ll.0.url }}" class="a"><img
                                    src="{{ ll.0.img_url }}"
                                    alt="..." class="img"></a>
                            <div class="carousel-caption" style="font-size: 25px">
                                火热广告招商
                            </div>
                        </div>
                        <div class="item">
                            <a href="{{ ll.1.url }}" class="a"><img
                                    src="{{ ll.1.img_url }}"
                                    alt="..." class="img"></a>
                            <div class="carousel-caption" style="font-size: 25px">
                                体验游戏人生
                            </div>
                        </div>
                        <div class="item">
                            <a href="{{ ll.2.url }}" class="a"><img
                                    src="{{ ll.2.img_url }}"
                                    alt="..." class="img"></a>
                            <div class="carousel-caption" style="font-size: 25px">
                                点我有你好看
                            </div>
                        </div>
                    </div>
                    <!-- 左右翻页 -->
                    <a class="left carousel-control" href="#carousel-example-generic" role="button"
                       data-slide="prev">
                        <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
                        <span class="sr-only">上一页</span>
                    </a>
                    <a class="right carousel-control" href="#carousel-example-generic" role="button"
                       data-slide="next">
                        <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
                        <span class="sr-only">下一页</span>
                    </a>
                </div>
            </div>
            <!--各个文章摘要-->
            <hr>
            <div class="article">
                {% for article in page_queryset %}
                    <div class="media">
                        <h4 class="media-heading"><a
                                href="/{{ article.blog.user.username }}/article_detail/{{ article.id }}.html">{{ article.name }}</a>
                        </h4>
                        <div class="media-left">
                            <a href="/blogsite/{{ article.blog.user.username }}/">
                                <img class="media-object" src="/media/{{ article.blog.user.head }}" alt="..."
                                     width="60"
                                     height="60">
                            </a>
                        </div>
                        <div class="media-body">
                            {{ article.description }}
                        </div>
                        <div class="article_bottom "><span><a
                                href="/blogsite/{{ article.blog.user.username }}/">{{ article.blog.user.username }}</a></span>
                            &nbsp;<span>{{ article.create_time|date:'Y-m-d H-i-s' }}</span>
                            &nbsp;<span><i class="fa fa-thumbs-up fa-lg"></i>&nbsp;{{ article.up_num }}</span>
                            <span class=""><i
                                    class="fa fa-commenting-o fa-lg"></i>&nbsp;{{ article.commit_num }}</span>
                        </div>
                    </div>
                {% endfor %}
                <div class="text-center">{{ page_obj.page_html|safe }}</div>
            </div>
        </div>
        <!--博客右侧-->
        <div class="col-md-3" id="blog_left">
            <div class="panel panel-info">
                <div class="panel-heading">
                    <h3 class="panel-title">关注</h3>
                </div>
                <div class="panel-body">
                    详情点击:<a href="">我评</a>
                    <hr>
                    详情点击:<a href="">我赞</a>
                </div>
            </div>
            <div class="panel panel-success">
                <div class="panel-heading">
                    <h3 class="panel-title">精华</h3>
                </div>
                <div class="panel-body">
                    详情点击:<a href="">候选</a>
                    <hr>
                    详情点击:<a href="">订阅</a>
                </div>
            </div>
            <div class="panel panel-warning">
                <div class="panel-heading">
                    <h3 class="panel-title">广告招商</h3>
                </div>
                <div class="panel-body">
                    详情点击:<a href="">百度</a>
                    <hr>
                    详情点击:<a href="">腾讯</a>
                </div>
            </div>
        </div>
    </div>
</div>


<script>
    $("#register").click(function () {
        window.open('/register/', "_self")
    })
    $("#login").click(function () {
        window.open('/login/', "_self")
    })
    $("#backend").click(function () {
        window.open('/backend/', "_self")
    })
    $("#logout").click(function () {
        window.open('/logout/', "_self")
    })

    $('#btn_pwd').click(function () {
        $(this).prop('disabled', true)
        $.ajax({
            url: '/change_pwd/',
            method: 'post',
            data: {
                'old_pwd': $('#old_pwd').val(),
                'new_pwd': $('#new_pwd').val(),
                're_new_pwd': $('#re_new_pwd').val(),
                'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()
            },
            success: function (data) {
                $('#btn_pwd').prop('disabled', false)
                if (data.code === 100) {
                    $('.text-danger').text(data.message)
                    setTimeout(function () {
                        location.href = data.url
                    }, 5000)
                } else {
                    $('.text-danger').text(data.message)
                    $(':password').val('')
                    setTimeout(function () {
                        $('.text-danger').text('')
                    }, 3000)
                }

            }
        })
    })
</script>

</body>
</html>

12、blogsite.html

{% extends 'base.html' %}
{% block title %}
    {{ user.username }}的博客
{% endblock %}
{% block style %}
    <style>
        body {
            background-color: rgba(0,191,255,0.31);
        }
    </style>
{% endblock %}
{% block core %}
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-2">
                {% load blogsiteleft %}
                {% left user.username %}
            </div>
            <div class="col-md-9 col-md-offset-1">
                <!--文章头部-->
                <div class="page-header">
                    <h1>{{ user.username }}<small></small></h1>
                </div>
                <!--各个文章摘要-->
                <div class="article">
                    {% for article in page_queryset %}
                        <div class="media">
                            <h4 class="media-heading"><a
                                    href="/{{ user.username }}/article_detail/{{ article.id }}.html/">{{ article.name }}</a>
                            </h4>
                            <div class="media-body">
                                {{ article.description }}
                            </div>
                            <div class="article_bottom "><span><a
                                    href="/blogsite/{{ article.blog.user.username }}/">{{ article.blog.user.username }}</a></span>
                                &nbsp;<span>{{ article.create_time|date:'Y-m-d H-i-s' }}</span>
                                &nbsp;<span><i class="fa fa-thumbs-up fa-lg"></i>&nbsp;{{ article.up_num }}</span>
                                <span class=""><i
                                        class="fa fa-commenting-o fa-lg"></i>&nbsp;{{ article.commit_num }}</span>
                                <span><a href=""><i class="fa fa-eraser fa-lg"></i>&nbsp;编辑</a></span>
                            </div>
                        </div>
                        <hr>
                    {% endfor %}
                    <div class="text-center">{{ page_obj.page_html|safe }}</div>
                </div>

            </div>
        </div>
    </div>

{% endblock %}

13、base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
        {% block title %}

        {% endblock %}
    </title>
    {% load static %}
    <script src="{% static 'jquery-3.3.1/jquery-3.3.1.min.js' %}"></script>
    <link href="{% static 'bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
    <link href="{% static 'font-awesome-4.7.0/font-awesome-4.7.0/css/font-awesome.css' %}" rel="stylesheet">
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
    {% block css %}

    {% endblock %}
    {% block style %}

    {% endblock %}
</head>
<body>
<!--顶部导航条-->
<div class="navbar-wrapper">
    <div class="">
        <nav class="navbar navbar-inverse navbar-static-top">
            <div id="navbar" class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a href="#">
                        {% block innertitle %}

                        {% endblock %}
                    </a></li>
                    <li class="active"><a href="/home/">首页</a></li>
                    <li><a href="#">历史记录</a></li>
                    <!--搜索框-->
                    <li style="margin-left: 100px">
                        <form class="navbar-form navbar-left" role="search">
                            <div class="form-group">
                                <input type="text" class="form-control" placeholder="输入关键词">
                            </div>
                            <button type="submit" class="btn btn-default btn-warning">搜索</button>
                        </form>
                    </li>
                    <!--右侧登录等按钮-->
                    {% if request.user.is_authenticated %}
                        <li>
                            <button type="button" class="btn btn-primary" data-toggle="modal"
                                    style="margin-top: 10px;margin-left: 450px"
                                    data-target="#exampleModal" data-whatever="@mdo">修改密码
                            </button>

                        </li>
                        <li>
                            <button id="logout" type="button" class="btn btn-info"
                                    style="margin-top: 10px;margin-left: 10px">注销
                            </button>
                        </li>
                        <li>
                            <button id="backend" type="button" class="btn btn-success"
                                    style="margin-top: 10px;margin-left: 10px">后台管理
                            </button>
                        </li>
                    {% else %}
                        <li>
                            <button id="register" type="button" class="btn btn-success"
                                    style="margin-top: 10px;margin-left: 450px">注册
                            </button>
                        </li>
                        <li>
                            <button id="login" type="button" class="btn btn-info"
                                    style="margin-top: 10px;margin-left: 10px">登录
                            </button>
                        </li>
                    {% endif %}
                </ul>

            </div>
        </nav>
    </div>
</div>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog"
     aria-labelledby="exampleModalLabel">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title" id="exampleModalLabel">修改密码</h4>
            </div>
            <!--修改密码的模态框-->
            <div class="modal-body">
                <form id="form_pwd">
                    {% csrf_token %}
                    <div class="form-group">
                        <label for="old_pwd" class="control-label">旧密码:
                        </label>
                        <input type="password" id="old_pwd" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="new_pwd" class="control-label">新密码:</label>
                        <input type="password" id="new_pwd" class="form-control">
                    </div>
                    <div class="form-group">
                        <label for="re_new_pwd" class="control-label">确认新密码:
                        </label>
                        <input type="password" id="re_new_pwd" class="form-control">
                    </div>
                </form>
            </div>
            <div class="text-center" style="height: 10px">
                <span class="text-danger"></span>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">取消修改
                </button>
                <button type="button" class="btn btn-primary" id="btn_pwd">提交修改</button>
            </div>
        </div>
    </div>
</div>

{% block core %}

{% endblock %}


<script>
    $("#register").click(function () {
        window.open('/register/', "_self")
    })
    $("#login").click(function () {
        window.open('/login/', "_self")
    })
    $("#backend").click(function () {
        window.open('/backend/', "_self")
    })
    $("#logout").click(function () {
        window.open('/logout/', "_self")
    })

    $('#btn_pwd').click(function () {
        $(this).prop('disabled', true)
        $.ajax({
            url: '/change_pwd/',
            method: 'post',
            data: {
                'old_pwd': $('#old_pwd').val(),
                'new_pwd': $('#new_pwd').val(),
                're_new_pwd': $('#re_new_pwd').val(),
                'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()
            },
            success: function (data) {
                $('#btn_pwd').prop('disabled', false)
                if (data.code === 100) {
                    $('.text-danger').text(data.message)
                    setTimeout(function () {
                        location.href = data.url
                    }, 5000)
                } else {
                    $('.text-danger').text(data.message)
                    $(':password').val('')
                    setTimeout(function () {
                        $('.text-danger').text('')
                    }, 3000)
                }

            }
        })
    })
</script>

{% block js %}

{% endblock %}
</body>
</html>

14、articledetail.html

{% extends 'base.html' %}
{% block title %}
    {{ user.username }}的博客
{% endblock %}
{% block css %}
    <link rel="stylesheet" href='/static/css/mycss.css'>
{% endblock %}
{% block style %}
    <style>
        body {
            background-color: rgba(0, 191, 255, 0.31);
        }
    </style>
{% endblock %}
{% block core %}
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-2">
                {% load blogsiteleft %}
                {% left user.username %}
            </div>
            <div class="col-md-9 col-md-offset-1">
                <!--文章头部-->
                <div class="page-header">
                    <h1>{{ article.name }}<small></small></h1>
                </div>
                <!--文章内容-->
                <div>
                    {{ article.content }}
                </div>
                <!--点赞点踩-->
                <div>
                    <div class="clearfix">
                        <div id="div_digg">
                            <div class="diggit action">
                                <span class="diggnum" id="digg_count">{{ article.up_num }}</span>
                            </div>
                            <div class="buryit action">
                                <span class="burynum" id="bury_count">{{ article.down_num }}</span>
                            </div>
                            <div class="clear"></div>
                            <div class="diggword" id="digg_tips" style="color: red;">
                            </div>
                        </div>
                    </div>
                </div>
                <!--点赞点踩-->
                <hr>
                <!--评论列表-->
                <div>
                    <p>评论列表</p>
                    <ul class="list-group">
                        {% for commit in commit_list %}
                            <li class="list-group-item">
                                <div>
                                    <span>#{{ forloop.counter }}楼</span>
                                    <span>{{ commit.create_time|date:'Y-m-d H-i' }}</span>
                                    <span><a
                                            href="/blogsite/{{ commit.user.username }}/">{{ commit.user.username }}</a></span>
                                    <span class="pull-right id_replay" username="{{ commit.user.username }}"
                                          parent_id="{{ commit.id }}"><a>回复</a></span>
                                </div>
                                <div>
                                    {% if commit.commit_self_id %}
                                        <p>@{{ commit.commit_self.user.username }}</p>
                                        <p>{{ commit.content }}</p>
                                    {% else %}
                                        <p>{{ commit.content }}</p>
                                    {% endif %}
                                </div>
                            </li>
                        {% endfor %}
                    </ul>
                </div>
                <!--评论区-->
                <hr>
                <div>
                    {% if request.user.is_authenticated %}
                        <p>评论区</p>
                        <textarea name="" id="commit" cols="80" rows="5" style="resize: none"></textarea>
                        <p>
                            <button class="btn btn-success" type="button" id="btn">评论</button>
                        </p>
                    {% else %}
                        <p>请先<a href="/login/">登录</a></p>
                    {% endif %}
                </div>
            </div>
        </div>
    </div>
{% endblock %}
{% block js %}
    <script>
        let parent_id = ''
        $('.action').click(function () {
            let is_up = $(this).hasClass('diggit')
            let span = $(this).children()
            $.ajax({
                url: '/diggit/',
                method: 'post',
                data: {
                    'is_up': is_up,
                    'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val(),
                    'article_id': {{ article.id }}
                },
                success: function (data) {
                    $('#digg_tips').html(data.msg)
                    if (data.code === 100) {
                        $(span).html(Number($(span).text()) + 1)
                    }
                }
            })
        })

        $('#btn').click(function () {
            let content = $('#commit').val()
            if (parent_id) {
                let i = content.indexOf('\n') + 1
                content = content.slice(i)
            }
            $.ajax({
                url: '/comment_content/',
                method: 'post',
                data: {
                    commit: content,
                    article_id: {{ article.id }},
                    csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val(),
                    parent_id: parent_id
                },
                success: function (data) {
                    if (data.code === 100) {
                        let username = data.username
                        let res_content = data.content
                        let parent_name = data.parent_name
                        let ss = ``
                        if (parent_id) {
                            ss = `<li class="list-group-item">
                                <div>
                                    <span><i class="fa fa-commenting-o fa-lg"></i> ${username}</span>
                                </div>
                                <div>
                                <p>@${parent_name}</p>
                                    ${res_content}
                                </div>
                            </li>`
                        } else {
                            ss = `<li class="list-group-item">
                                <div>
                                    <span><i class="fa fa-commenting-o fa-lg"></i> ${username}</span>
                                </div>
                                <div>
                                    ${res_content}
                                </div>
                            </li>`
                        }
                        $('#commit').val('')
                        $('.list-group').append(ss)
                        parent_id = ''
                    }
                }
            })
        })
        $('.id_replay').click(function () {
            $('#commit').val('@' + $(this).attr('username') + '\n').focus()
            parent_id = $(this).attr('parent_id')
        })
    </script>
{% endblock %}

15、update_head.html

{% extends 'backend/backbase.html' %}

{% block head %}
    <form action="" method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <div class="form-group">
            <label for="">原头像</label>
            <img src="/media/{{ request.user.head }}" height="80" width="80">
        </div>
        <div class="form-group">
            <label for="id_myfile">新头像
                <img src="/static/img/default.png" alt="" id="id_img" height="80" width="80"
                     style="margin-left: 10px">
            </label>
            <input type="file" accept="image/*" name="myhead" id="id_myfile" style="display: none">
        </div>
        <div class="text-center">
            <input type="submit" value="修改" id="id_submit" class="btn btn-danger "><span
                class="error text-danger" style="margin-left: 10px"></span>
        </div>
    </form>
{% endblock %}
{% block script %}
    <script>
        $('#id_myfile').change(function () {
            let filereader = new FileReader()
            filereader.readAsDataURL(this.files[0])
            filereader.onload = function () {
                $('#id_img').attr('src', filereader.result)
            }
        })
    </script>
{% endblock %}

16、update_article.html

{% extends 'backend/backbase.html' %}
{% block content %}
    <div>
        <h4>新增文章</h4>
        <form action="" method="post">
            {% csrf_token %}
            <div class="form-group">
                <label for="">标题</label>
                <input type="text" name="name" class="form-control" value="{{ article.name }}">
            </div>
            <div class="form-group">
                <label for="">内容</label>
                <textarea name="content" id="editor_id" cols="80" rows="10"
                          class="form-control">{{ article.content }}</textarea>
            </div>
            <div>
                个人分类:
                {% for category in category_list %}
                    {{ article.category_id }}
                    <div class="radio-inline">
                        <label>
                            {% if article.category_id == category.id %}
                                <input type="radio" name="category" value="{{ category.id }}" checked>
                            {% else %}
                                <input type="radio" name="category" value="{{ category.id }}">
                            {% endif %}
                            {{ category.name }}
                        </label>
                    </div>
                {% endfor %}
            </div>
            <div>
                个人标签:
                {% for tag in tag_list %}
                    <div class="checkbox-inline">
                        <label>
                            {% if tag in article.tag.all %}
                                <input type="checkbox" name="tag" value="{{ tag.id }}" checked>
                            {% else %}
                                <input type="checkbox" name="tag" value="{{ tag.id }}">
                            {% endif %}
                            {{ tag.name }}
                        </label>
                    </div>
                {% endfor %}
            </div>
            <div class="text-center">
                <input type="submit" class="btn btn-success" value="提交">
            </div>
        </form>
    </div>
{% endblock %}
{% block script %}
    <script charset="utf-8" src="/static/kindeditor/kindeditor-all.js"></script>
    <script>
        KindEditor.ready(function (K) {
            window.editor = K.create('#editor_id', {
                width: '100%',
                height: '300px',
                resizeType: 1,
                uploadJson: '/upload_img/',
                filePostName: 'myfile',
                extraFileUploadParams: {
                    csrfmiddlewaretoken: '{{ csrf_token }}',
                }
            });
        });
    </script>
{% endblock %}

17、backleft.html

<div class="left_content col-md-3">
    <div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
        <div class="panel panel-default">
            <div class="panel-heading" role="tab" id="headingOne">
                <h4 class="panel-title">
                    <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne"
                       aria-expanded="true" aria-controls="collapseOne">
                        操作
                    </a>
                </h4>
            </div>
            <div id="collapseOne" class="panel-collapse collapse in" role="tabpanel"
                 aria-labelledby="headingOne">
                <div class="panel-body">
                    <ul class="nav">
                        <li><a href="/add_article/">新增文章</a></li>
                        <li><a href="/update_head/">修改头像</a></li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="panel panel-default">
            <div class="panel-heading" role="tab" id="headingTwo">
                <h4 class="panel-title">
                    <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion"
                       href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
                        分类
                    </a>
                </h4>
            </div>
            <div id="collapseTwo" class="panel-collapse collapse" role="tabpanel"
                 aria-labelledby="headingTwo">
                <div class="panel-body">
                    <div class="panel panel-info">
                        <div class="panel-heading">
                            <h3 class="panel-title">随笔分类</h3>
                        </div>
                        <div class="panel-body">
                            {% for category in res_category %}
                                <p>
                                    <a href="/blogsite/{{ name }}/category/{{ category.2 }}.html">{{ category.0 }}&nbsp;({{ category.1 }})</a>
                                </p>
                            {% endfor %}
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

18、backend.html

{% extends 'backend/backbase.html' %}
{% block content %}
    <div class="container-fluid">
        <div class="row">
            <table class="table table-hover table-striped">
                <thead>
                <tr>
                    <th>标题</th>
                    <th>评论数</th>
                    <th>点赞数</th>
                    <th>操作</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                {% for article in page_queryset %}
                    <tr>
                        <td>
                            <a href="/{{ article.blog.user.username }}/article_detail/{{ article.pk }}.html">{{ article.name|truncatechars:10 }}</a>
                        </td>
                        <td>{{ article.commit_num }}</td>
                        <td>{{ article.up_num }}</td>
                        <td><a href="/update_article/{{ article.pk }}/">编辑</a></td>
                        <td><a href="/delete/{{ article.pk }}">删除</a></td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
            <div class="text-center">{{ page_obj.page_html|safe }}</div>
        </div>
    </div>
{% endblock %}

19、backbase.html

<!DOCTYPE html>
<html lang="en">
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ request.user.username }}的后台管理</title>
    {% load static %}
    <script src="{% static 'jquery-3.3.1/jquery-3.3.1.min.js' %}"></script>
    <link href="{% static 'bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
    <link href="{% static '/font-awesome-4.7.0/font-awesome-4.7.0/css/font-awesome.css' %}" rel="stylesheet">
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div>
    <div class="header">
        <nav class="navbar navbar-default navbar-inverse">
            <div class="container-fluid">
                <div class="navbar-header">
                    <a class="navbar-brand" href="/backend/">后台管理</a>
                </div>
                <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                    <ul class="nav navbar-nav">
                        <li class="active"><a href="/home/">首页 <span class="sr-only">(current)</span></a></li>

                    </ul>
                </div><!-- /.navbar-collapse -->
            </div><!-- /.container-fluid -->
        </nav>
    </div>
    <div class="container-fluid">
        <div class="row">
            {% load blogsiteleft %}
            {% backleft request %}
            <div class="right_content col-md-9">
                <div>
                    <!-- Nav tabs -->
                    <ul class="nav nav-tabs" role="tablist">
                        <li role="presentation" class="active"><a href="#home" aria-controls="home" role="tab"
                                                                  data-toggle="tab">文章</a></li>
                        <li role="presentation"><a href="#profile" aria-controls="profile" role="tab"
                                                   data-toggle="tab">修改头像</a>
                        </li>
                        <li role="presentation"><a href="#messages" aria-controls="messages" role="tab"
                                                   data-toggle="tab">日志</a>
                        </li>
                        <li role="presentation"><a href="#settings" aria-controls="settings" role="tab"
                                                   data-toggle="tab">标签</a>
                        </li>
                    </ul>
                    <!-- Tab panes -->
                    <div class="tab-content">
                        <div role="tabpanel" class="tab-pane active" id="home">
                            {% block content %}

                            {% endblock %}
                        </div>
                        <div role="tabpanel" class="tab-pane" id="profile">
                            {% block head %}
                            {% endblock %}
                        </div>
                        <div role="tabpanel" class="tab-pane" id="messages">
                            日志的内容
                        </div>
                        <div role="tabpanel" class="tab-pane" id="settings">
                            标签的内容
                        </div>
                    </div>

                </div>
            </div>
        </div>
    </div>
</div>

</body>
{% block script %}

{% endblock %}
</html>

20、add_article.html

{% extends 'backend/backbase.html' %}
{% block content %}
    <div>
        <h4>新增文章</h4>
        <form action="" method="post" >
            {% csrf_token %}
            <div class="form-group">
                <label for="">标题</label>
                <input type="text" name="name" class="form-control">
            </div>
            <div class="form-group">
                <label for="">内容</label>
                <textarea name="content" id="editor_id" cols="80" rows="10" class="form-control"></textarea>
            </div>
            <div>
                个人分类:
                {% for category in category_list %}
                    <div class="radio-inline">
                        <label>
                            <input type="radio" name="category" value="{{ category.id }}">
                            {{ category.name }}
                        </label>
                    </div>
                {% endfor %}
            </div>
            <div>
                个人标签:
                {% for tag in tag_list %}
                    <div class="checkbox-inline">
                        <label>
                            <input type="checkbox" name="tag" value="{{ tag.id }}">
                            {{ tag.name }}
                        </label>
                    </div>
                {% endfor %}
            </div>
            <div class="text-center">
                <input type="submit" class="btn btn-success" value="提交">
            </div>
        </form>
    </div>
{% endblock %}
{% block script %}
    <script charset="utf-8" src="/static/kindeditor/kindeditor-all.js"></script>
    <script>
        KindEditor.ready(function (K) {
            window.editor = K.create('#editor_id', {
                width: '100%',
                height: '300px',
                resizeType: 1,
                uploadJson: '/upload_img/',
                filePostName: 'myfile',
                //额外带的参数
                extraFileUploadParams: {
                    csrfmiddlewaretoken: '{{ csrf_token }}',
                }
            });
        });
    </script>
{% endblock %}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值