漫天飞雪

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
BBS需求分析: 
  • 基于用户认证组件auth和Ajax实现登录验证(图片验证码)
  • 基于forms组件和Ajax实现注册功能
  • 设计博客系统首页(文章列表渲染)
  • 设计个人站点页面
  • 文章详情页
  • 实现文章点赞功能
  • 实现文章的评论
  • 文章的评论
  • 评论的子评论
  • 富文本编辑框以及csrf攻击

 

技术栈(BBS未做前后端分离,未使用vue框架)

  • python 3.0
  • django 1.11.7
  • jquery 3.3.1
  • bootstrap 3.3.7

模块安装(项目中使用到常见模块可自行安装)

  • jinjia2 2.1.0
  • pymysql 0.9.2
  • pillow 5.3.0
  • beautifulsoup4 4.6.3
  • mysql数据库(使用Navicat Premium工具进行数据库的操作)
    • pycharm操作mysql时,使用pymysql模块,需要在__init__文件中进行配置(详情见下面_init__文件配置)

 pc系统环境

  • win10

完整BBS项目

  _init__文件配置

import pymysql
pymysql.install_as_MySQLdb()
__init__

  setting配置文件

"""
Django settings for BBS project.

Generated by 'django-admin startproject' using Django 1.11.9.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
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/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '4ko*)y@ov6np97g)o!v@jf!yuc@bm_5q0!r2u1&aef&nn64p+q'

# 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.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.wsgi.application'

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

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'bbs',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': '123',
    }
}

# Password validation
# https://docs.djangoproject.com/en/1.11/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/1.11/topics/i18n/

# LANGUAGE_CODE = 'en-us'
# 后台管理界面变成中文
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/1.11/howto/static-files/

STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

AUTH_USER_MODEL = 'blog.UserInfo'

random_color = 255

MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_BBS = os.path.join(BASE_DIR, "BBS")

LOGIN_URL = '/login/'

EMAIL_HOST = 'smtp.qq.com'
EMAIL_PORT = 465
EMAIL_HOST_USER = 'QQ邮箱'
EMAIL_HOST_PASSWORD = 'tpxhuavskui'#已做修改,请获取自己的qq邮箱验证信息
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
EMAIL_USE_SSL = True
setting配置文件

  static(静态文件,在setting里配置完成后,手动创建目录名为static的目录,用户放置一些js框架和第三方库,且不经常变动的文件)

  media(media目录是放置用户头像,博客图片等)

  url路由配置

"""BBS URL Configuration

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

urlpatterns = [
    url(r'^$', views.index),
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
    url(r'^login/', views.login),
    url(r'^logout/', views.logout),
    url(r'^get_code/', views.get_code),
    url(r'^check_username/', views.check_username),
    url(r'^register/', views.register),
    # 后台管理
    url(r'^m/', views.background_management),
    url(r'^add_article/', views.add_article),
    url(r'^update_article/(?P<pk>\d+)', views.update_article),
    url(r'^delete_article/', views.delete_article),


    url(r'^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
    # 点赞评论
    url(r'^diggit/', views.diggit),
    url(r'^commit_content/$', views.commit_content),
    url(r'^upload_img/', views.upload_img),

    url(r'^(?P<username>[\w]+)/(?P<condition>category|tag|archive)/(?P<param>.*)', views.user_blog),
    url(r'^(?P<username>[\w]+)/article/(?P<id>\d+)', views.article_detail),

    url(r'^(?P<username>[\w]+)$', views.user_blog),

]
url路由配置文件

  admin文件配置

from django.contrib import admin
from blog import models

# Register your models here.
admin.site.register(models.UserInfo)
admin.site.register(models.Blog)
admin.site.register(models.Article)
admin.site.register(models.Tag)
admin.site.register(models.Category)
admin.site.register(models.Commit)
admin.site.register(models.UpAndDown)
admin.site.register(models.ArticleTOTag)
admin文件配置

  dataforms组件

from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError
from blog import models


class UserRegForm(forms.Form):
    username = forms.CharField(max_length=18, min_length=3, label='请输入用户名',
                               widget=widgets.TextInput(attrs={'class': 'form-control'}),
                               error_messages={"min_length": "输入过短,最少4个字符", "max_length": "输入过长,最多4个字符",
                                               "required": "必填"}, required=True)
    password = forms.CharField(max_length=18, min_length=3, label='请输入密码',
                               widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
                               error_messages={"min_length": "输入过短,最少5个字符", "required": "必填"}, required=True)
    re_password = forms.CharField(max_length=18, min_length=3, label='请再次输入密码',
                                  widget=widgets.PasswordInput(attrs={'class': 'form-control'}),
                                  error_messages={"min_length": "输入过短,最少5个字符", "required": "必填"}, required=True)
    email = forms.EmailField(max_length=18, min_length=3, label='请输入邮箱',
                             widget=widgets.TextInput(attrs={'class': 'form-control'}),
                             error_messages={"min_length": "输入过短,最少5个字符", "required": "必填"}, required=True)

    # 局部钩子函数
    def clean_username(self):
        name = self.cleaned_data.get('username')
        user = models.UserInfo.objects.filter(username=name).first()
        if user:
            raise ValidationError('用户名已存在,请重新输入')
        return name

    # 全局钩子函数
    def clean(self):
        pwd = self.cleaned_data.get('password')
        re_pwd = self.cleaned_data.get('re_password')
        if pwd == re_pwd:
            return self.cleaned_data
        else:
            raise ValidationError('两次密码不一致,请从新输入')
dataforms组件

  models(表模型)

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

class UserInfo(AbstractUser):
    nid = models.AutoField(primary_key=True)
    phone = models.CharField(max_length=32, null=True, blank=True)
    avatar = models.FileField(upload_to='avatar/', default='avatar/default.png')
    blog = models.OneToOneField(to='Blog', to_field='nid', null=True)



class Blog(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=64)
    site_name = models.CharField(max_length=32)
    theme = models.CharField(max_length=64)
    def __str__(self):
        return self.site_name


class Category(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=64)
    blog = models.ForeignKey(to='Blog', to_field='nid', null=True)
    def __str__(self):
        return self.title


class Tag(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=64)
    blog = models.ForeignKey(to='Blog', to_field='nid', null=True)


class Article(models.Model):
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=64)
    desc = models.CharField(max_length=255)
    content = models.TextField()
    create_time = models.DateTimeField(auto_now_add=True)
    commit_num = models.IntegerField(default=0)
    up_num = models.IntegerField(default=0)
    down_num = models.IntegerField(default=0)
    blog = models.ForeignKey(to='Blog', to_field='nid', null=True)
    category = models.ForeignKey(to='Category', to_field='nid', null=True)
    tag = models.ManyToManyField(to='Tag', through='ArticleTOTag', through_fields=('article', 'tag'))

    def __str__(self):
        return self.title + '----' + self.blog.userinfo.username


class ArticleTOTag(models.Model):
    nid = models.AutoField(primary_key=True)
    article = models.ForeignKey(to='Article', to_field='nid')
    tag = models.ForeignKey(to='Tag', to_field='nid')


class Commit(models.Model):
    nid = models.AutoField(primary_key=True)
    user = models.ForeignKey(to='UserInfo', to_field='nid')
    article = models.ForeignKey(to='Article', to_field='nid')
    content = models.CharField(max_length=255)
    create_time = models.DateTimeField(auto_now_add=True)
    parent = models.ForeignKey(to='self', to_field='nid', null=True, blank=True)


class UpAndDown(models.Model):
    nid = models.AutoField(primary_key=True)
    user = models.ForeignKey(to='UserInfo', to_field='nid')
    article = models.ForeignKey(to='Article', to_field='nid')
    is_up = models.BooleanField()

    class Meta:
        unique_together = (('user', 'article'),)
orm表模型

  views视图函数

import os
import json
import random
from io import BytesIO
from django.core.mail import send_mail
from django.shortcuts import render, redirect, reverse, HttpResponse
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.db import transaction
from django.db.models import F
from bs4 import BeautifulSoup
from PIL import Image, ImageDraw, ImageFont
from blog import models
from blog import dataforms
from BBS import settings


# 主页
def index(request):
    articles = models.Article.objects.all()
    return render(request, 'index.html', {'article_list': articles})


# 验证码
# random_color是在settings里设置的变量
def random_color():
    return (
        random.randint(0, settings.random_color),
        random.randint(0, settings.random_color),
        random.randint(0, settings.random_color)
    )


def get_code(request):
    img = Image.new('RGB', (140, 34), color=random_color())
    img_draw = ImageDraw.Draw(img)
    font = ImageFont.truetype('static/font/ziti.TTF', size=25)
    random_code = ''
    for i in range(5):
        char_num = random.randint(0, 9)
        char_lower = chr(random.randint(97, 122))
        char_upper = chr(random.randint(65, 90))
        char_str = str(random.choice([char_num, char_lower, char_upper]))
        img_draw.text((i * 24 + 18, 0), char_str, random_color(), font=font)
        random_code += char_str
    request.session['valid_code'] = random_code
    # width = 140
    # height = 34
    # for i in range(10):
    #     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=random_color())

    # for i in range(100):
    #     # # 画点
    #     img_draw.point([random.randint(0, width), random.randint(0, height)], fill=random_color())
    #     x = random.randint(0, width)
    #     y = random.randint(0, height)
    #     # 画弧形
    #     img_draw.arc((x, y, x + 4, y + 4), 0, 90, fill=random_color())

    f = BytesIO()
    img.save(f, 'png')
    data = f.getvalue()
    return HttpResponse(data)


# 登录
def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    elif request.is_ajax():
        # 登录完成后返回信息
        login_response = {'user': None, 'msg': None}
        # 获取ajax提交的name和pwd数据
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        input_valid_code = request.POST.get('valid_code')
        print(input_valid_code)
        # 获取session中的valid_code
        if input_valid_code.upper() == request.session.get('valid_code').upper():
            # auth验证模块,进行登录用户验证
            user = auth.authenticate(request, username=name, password=pwd)
            if user:
                # 使用auth模块进行登录
                auth.login(request, user)
                login_response['user'] = name
                login_response['msg'] = '登陆成功'
                login_response['url'] = '/index/'
                print(login_response)
            else:
                login_response['msg'] = '用户名或密码错误'
        else:
            login_response['msg'] = '验证码错误'
        return JsonResponse(login_response)


# 注销
def logout(request):
    auth.logout(request)
    return redirect('/index/')


# 注册
def register(request):
    if request.method == 'GET':
        my_form = dataforms.UserRegForm()
        return render(request, 'register.html', {'my_form': my_form})
    elif request.is_ajax():
        response = {'status': 100, 'msg': None}
        print(request.POST)
        print(request.POST.get('username'))
        my_form = dataforms.UserRegForm(request.POST)
        if my_form.is_valid():
            dic = my_form.cleaned_data
            # 移除掉确认密码字段
            dic.pop('re_password')
            # 取出上传的文件对象
            my_file = request.FILES.get('my_file')
            # 如果上传的文件为空,这个字段不传,数据库里存默认值
            if my_file:
                # 放到字典中
                dic['avatar'] = my_file
            # 存数据的时候,多肯定不行,少,可以能行(null=True),它是可以的
            user = models.UserInfo.objects.create_user(**dic)
            '''
            models.FileField 有了这个字段,存文件,以及往数据库放文件路径,统统不需要自己做了
            只需要把文件对象赋给它就可以了
            '''
            print(user.username)
            # 注册成功后跳转的路径
            response['url'] = '/login/'
        else:
            # 返回错误信息
            response['status'] = 101
            response['msg'] = my_form.errors
        return JsonResponse(response)


# 注册校验
def check_username(request):
    response = {'status': 100, 'msg': None}
    name = request.POST.get('name')
    pwd = request.POST.get('pwd')
    user = models.UserInfo.objects.filter(username=name).first()
    if user:
        response['status'] = 101
        response['msg'] = '用户名已被占用,请重新输入'
    return JsonResponse(response)


# 后台管理
# @login_required(login_url='/login/')
def background_management(request):
    if request.method == 'GET':
        blog = request.user.blog
        article_list = models.Article.objects.filter(blog=blog)
        return render(request, 'background_management/m.html', {"article_list": article_list})


# 文章增删改查
def add_article(request):
    if request.method == 'GET':
        return render(request, 'background_management/add_article.html', )
    elif request.method == 'POST':
        title = request.POST.get('title')
        content = request.POST.get('content')
        soup = BeautifulSoup(content, 'html.parser')
        tags = soup.find_all()
        for tag in tags:
            if tag.name == 'script':
                tag.decompose()
        desc = soup.text[0:150]
        ret = models.Article.objects.create(title=title, desc=desc, content=str(soup), blog=request.user.blog)
        return redirect('/m/')


def delete_article(request):
    if request.method == 'GET':
        nid = request.GET.get('id')
        models.Article.objects.filter(nid=nid).delete()
        return redirect('/m/')


def update_article(request, pk):
    # 使用有名分组
    if request.method == 'GET':
        article = models.Article.objects.get(pk=pk)
        print(article.title)
        print('----------------')
        return render(request, 'background_management/update_article.html', {'article': article})
    elif request.method == 'POST':
        title = request.POST.get('title')
        content = request.POST.get('content')
        soup = BeautifulSoup(content, 'html.parser')
        tags = soup.find_all()
        for tag in tags:
            if tag.name == 'script':
                tag.decompose()
        desc = soup.text[0:150]
        print(desc)
        ret = models.Article.objects.filter(nid=pk).update(title=title, desc=desc, content=str(soup),
                                                           blog=request.user.blog)
        print(ret)
        return redirect('/m/')


# 个人博客主页
def user_blog(request, username, *args, **kwargs):
    user = models.UserInfo.objects.filter(username=username).first()
    if not user:
        return render(request, 'error.html')
    blog = user.blog
    article_list = blog.article_set.all()
    condition = kwargs.get('condition')
    param = kwargs.get('param')
    if 'tag' == condition:
        article_list = article_list.filter(tag__pk=param)
    elif 'category' == condition:
        article_list = article_list.filter(category__pk=param)
    elif 'archive' == condition:
        archive_list = param.split('-')
        article_list = article_list.filter(create_time__year=archive_list[0], create_time__month=archive_list[1])
    return render(request, 'blog_site/user_blog.html', locals())


# 文章详情
def article_detail(request, username, id):
    username = username
    user = models.UserInfo.objects.filter(username=username).first()
    if not user:
        return render(request, 'error.html')
    blog = user.blog
    article = models.Article.objects.filter(pk=id).first()
    content_list = article.commit_set.all().order_by('pk')
    return render(request, 'blog_site/article_detail.html', locals())


# 点赞和点踩
def diggit(request):
    response = {'status': 100, 'msg': None}
    if request.user.is_authenticated():
        article_id = request.POST.get('article_id')
        is_up = request.POST.get('is_up')
        is_up = json.loads(is_up)
        user = request.user
        ret = models.UpAndDown.objects.filter(user_id=user.pk, article_id=article_id).exists()
        if ret:
            response['msg'] = '您已经点过了'
            response['status'] = 101
        else:
            with transaction.atomic():
                models.UpAndDown.objects.create(user=user, article_id=article_id, is_up=is_up)
                article = models.Article.objects.filter(pk=article_id)
                if is_up:
                    article.update(up_num=F('up_num') + 1)
                    response['msg'] = '点赞成功'
                else:
                    article.update(down_num=F('down_num') + 1)
                    response['msg'] = '反对成功'
    else:
        response['msg'] = '请先登录'
        response['status'] = 102
    return JsonResponse(response)


# 评论
def commit_content(request):
    response = {'status': 100, 'msg': None}
    if request.is_ajax():
        if request.user.is_authenticated():
            user = request.user
            article_id = request.POST.get('article_id')
            content = request.POST.get('content')
            pid = request.POST.get('pid')
            with transaction.atomic():
                ret = models.Commit.objects.create(user=user, article_id=article_id, content=content, parent_id=pid)
                models.Article.objects.filter(pk=article_id).update(commit_num=F('commit_num') + 1)
            response['msg'] = '评论成功'
            response['content'] = ret.content
            response['time'] = ret.create_time.strftime('%Y-%m-%d %X')
            response['user_name'] = ret.user.username
            if pid:
                response['parent_name'] = ret.parent.user.username
            from BBS import settings
            article_name = ret.article.title
            user_name = request.user.username
            from threading import Thread
            thread = Thread(target=send_mail, args=(
                '用户%s已经评论了%s文章' % (user_name, article_name), '评论内容如下:%s' % content, settings.EMAIL_HOST_USER,
                ['334147577@qq.com']))
            thread.start()
        else:
            response['status'] = 101
            response['msg'] = '您没有登录'
    else:
        response['status'] = 101
        response['msg'] = '您请求非法'
    return JsonResponse(response)


# 图片上传
def upload_img(request):
    print(request.FILES)
    uploadFile = request.FILES.get('uploadFile')
    path = os.path.join(settings.BASE_DIR, 'media', 'img')
    if not os.path.isdir(path):
        os.mkdir(path)
    file_path = os.path.join(path, uploadFile.name)
    with open(file_path, 'wb') as f:
        for line in uploadFile:
            f.write(line)
    dic = {
        'error': 0,
        'url': '/media/img/%s' % uploadFile.name,
    }
    return JsonResponse(dic)
Views视图函数

  templates模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>404错误</title>
    <script src="../static/jquery-3.3.1.js"></script>
    <script src="../static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
    <link rel="stylesheet" href="../static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <style>
        #box_404 {
            margin-top: 200px;
        }
    </style>
</head>
<body>

<div class="container-fluid">
    <div class="row">
        <div class="col-md-3 col-md-offset-5" id="box_404">
            <a href="http://www.cnblogs.com/"><img src="/static/img/admin_logo.gif" alt="cnblogs"></a>
            <p class="d">请确认您输入的网址是否正确,如果问题持续存在,请发邮件至contact@cnblogs.com与我们联系。</p>
            <p><b>404.</b> 抱歉! 您访问的资源不存在!</p>
            <p><a href="http://www.cnblogs.com/">返回网站首页</a></p>
        </div>

    </div>
</div>
</body>
</html>
error.html
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
    <script src="/static/jquery-3.3.1.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
    <link rel="stylesheet" href="../static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        #bbs {
            height: 60px;
            margin-top: 4px;
            border: #9d9d9d 1px solid;
            border-radius: 10px;
        }

        #bbs2 {
            margin: 0;
            padding: 0;
            color: #9d9d9d;
            font-size: 10px;
        }

        #master {
            margin: 0 10px;
        }

        .article_bottom span {
            margin-right: 5px;
        }

        #pull-right {
            height: 40px;
        }

        #touxiang {
            display: block;
            width: 37px;
            height: 37px;
            border-radius: 50%;
            background: url("/media/{{ request.user.avatar }}") no-repeat;
            background-size: 37px;
            margin-right: 20px;
        }
    </style>
</head>
<body>
<div id="master">
    <nav class="navbar navbar-default">
        <div class="container-fluid" id="bbs2">
            <div class="pull-left">代码改变世界</div>
            <div class="pull-right " id="pull-right">
                <ul class="nav navbar-nav navbar-right">
                    {% if request.user.is_authenticated %}
                        <li id="touxiang"><a href="/{{ request.user.username }}"></a></li>
                        <li><a href="/{{ request.user.username }}">{{ request.user.username }}</a></li>
                        <li class="dropdown">
                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
                               aria-haspopup="true" aria-expanded="false">个人中心 <span class="caret"></span></a>
                            <ul class="dropdown-menu">
                                <li><a href="#">修改密码</a></li>
                                <li><a href="#">修改头像</a></li>
                                <li><a href="http://127.0.0.1:8000/m/">后台管理</a></li>
                                <li role="separator" class="divider"></li>
                                <li><a href="/logout/">注销</a></li>
                            </ul>
                        </li>
                    {% else %}
                        <li><a href="/login/">登录</a></li>
                        <li><a href="/register/">注册</a></li>
                    {% endif %}
                </ul>
            </div>
        </div>
        <div class="container-fluid" id="bbs">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div>
                <div class="navbar-header">
                    <div><a href="https://www.cnblogs.com"><img src="/static/img/bbs_logo_.gif" alt=" " id="img"></a>
                    </div>
                </div>
            </div>
        </div>
    </nav>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-2" style="background-color:#eeeeff">
                <div>
                    <div class="list-group">
                        <a href="#" class="list-group-item disabled">
                            网站分类
                        </a>
                        <a href="#" class="list-group-item">网站分类</a>
                        <a href="#" class="list-group-item">net技术</a>
                        <a href="#" class="list-group-item">编程语言</a>
                        <a href="#" class="list-group-item">软件设计</a>
                    </div>
                </div>
                <div>
                    <div class="list-group">
                        <a href="#" class="list-group-item disabled">
                            Cras justo odio
                        </a>
                        <a href="#" class="list-group-item">网站分类</a>
                        <a href="#" class="list-group-item">net技术</a>
                        <a href="#" class="list-group-item">编程语言</a>
                        <a href="#" class="list-group-item">软件设计</a>
                    </div>
                </div>
                <div>
                    <div class="list-group">
                        <a href="#" class="list-group-item disabled">
                            Cras justo odio
                        </a>
                        <a href="#" class="list-group-item">网站分类</a>
                        <a href="#" class="list-group-item">net技术</a>
                        <a href="#" class="list-group-item">编程语言</a>
                        <a href="#" class="list-group-item">软件设计</a>
                    </div>
                </div>
            </div>


            <div class="col-md-7">
                {% for article in article_list %}
                    <div>
                        <h4>
                            <a href="/{{ article.blog.userinfo.username }}/article/{{ article.pk }}">{{ article.title }}</a>
                        </h4>
                        <div class="media">
                            <div class="media-left">
                                <a href="#">
                                    <img class="media-object" src="/media/{{ article.blog.userinfo.avatar }}"
                                         height="70" width="70">
                                </a>
                            </div>
                            <div class="media-body">

                                {{ article.desc }}
                            </div>
                        </div>
                        <div style="margin-top: 10px " class="article_bottom">
                            <span><a
                                    href="/{{ article.blog.userinfo.username }}">{{ article.blog.userinfo.username }}</a></span>
                            <span>发布于 {{ article.create_time|date:'Y-m-d H:i:s' }}</span>
                            <span><i class="glyphicon glyphicon-heart-empty" aria-hidden="true"><a
                                    href="">评论({{ article.commit_num }})</a></i></span>
                            <span class="glyphicon glyphicon-thumbs-up"><a href="">点赞({{ article.up_num }})</a></span>
                        </div>
                        <hr>
                    </div>
                {% endfor %}
            </div>


            <div class="col-md-3" style="background-color: #eeeeff">
                <div>
                    <div class="list-group">
                        <a href="#" class="list-group-item disabled">
                            Cras justo odio
                        </a>
                        <a href="#" class="list-group-item">网站分类</a>
                        <a href="#" class="list-group-item">net技术</a>
                        <a href="#" class="list-group-item">编程语言</a>
                        <a href="#" class="list-group-item">软件设计</a>
                    </div>
                </div>
                <div>
                    <div class="list-group">
                        <a href="#" class="list-group-item disabled">
                            Cras justo odio
                        </a>
                        <a href="#" class="list-group-item">网站分类</a>
                        <a href="#" class="list-group-item">net技术</a>
                        <a href="#" class="list-group-item">编程语言</a>
                        <a href="#" class="list-group-item">软件设计</a>
                    </div>
                </div>
                <div>
                    <div class="list-group">
                        <a href="#" class="list-group-item disabled">
                            网站分类
                        </a>
                        <a href="#" class="list-group-item">网站分类</a>
                        <a href="#" class="list-group-item">net技术</a>
                        <a href="#" class="list-group-item">编程语言</a>
                        <a href="#" class="list-group-item">软件设计</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

</body>
</html>
index.html
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>用户登陆</title>
    <script src="../static/jquery-3.3.1.js"></script>
    <script src="../static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
    <link rel="stylesheet" href="../static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <style>
        .box {
            margin-top: 70px;
        }

        body {
            background-color: grey;
        }

        #img-code-parent {
            position: relative;
        }

        #valid_img {
            position: absolute;
            right: 15px;
            bottom: 0;
        }
    </style>
</head>
<body>
<div class="container-fluid ">
    <div class="row">
        <div class="col-md-3 col-md-offset-4 box">
            <h2>用户登陆</h2>
            <form action="">
                {% csrf_token %}
                <div class="form-group">
                    <label for="name">用户名</label>
                    <input type="text" id="name" class="form-control" placeholder="输入用户名">
                </div>
                <div class="form-group">
                    <label for="pwd">密码</label>
                    <input type="password" class="form-control" id="pwd" placeholder="输入密码">
                </div>
                <div class="form-group">
                    <div class="row" id="img-code-parent">
                        <div class="col-md-6 ">
                            <label for="valid_code">验证码</label>
                            <input type="text" class="form-control" id="valid_code" placeholder="输入验证吗">
                        </div>
                        <img src="/get_code/" alt="获取验证码" width="140" height="34" id="valid_img">
                    </div>
                </div>
                <p><span class="error"></span></p>
                <input type="button" value="登陆" class="btn btn-info " id="login_btn">
            </form>
        </div>
    </div>
</div>
</body>

<script>
    {#验证码刷新#}
    $('#valid_img').click(function () {
        $(this)[0].src += '?'
    });
    $('#login_btn').click(function () {
        $.ajax({
            url: "/login/",
            type: "post",
            data: {
                "name": $("#name").val(),
                "pwd": $("#pwd").val(),
                "valid_code": $("#valid_code").val(),
                //属性选择器
                'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()
                {#'csrfmiddlewaretoken': '{{csrf_token}}',#}
            },
            success: function (data) {
                if (data.user) {
                    location.href = data.url
                } else {
                    $('.error').html(data.msg)
                }
            }
        })
    })
</script>
</html>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="/static/jquery-3.3.1.js"></script>
    <title>用户注册</title>
    <style>
        #my_file{
            {#display: none;#}
        }
    </style>

</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-4 col-md-offset-4">
            <h1>用户注册</h1>
            <form id="form">
                {% csrf_token %}

                {% for foo in my_form %}
                    <div class="form-group">
                        <label for="{{ foo.auto_id }}">{{ foo.label }}</label>
                        {{ foo }} <span class="error pull-right" style="color: red">{{ foo.errors.0 }}</span>
                    </div>
                {% endfor %}
                <div class="form-group">
                    <label for="my_file">头像上传
                        <img src="/media/avatar/default.jpg" id="img_file" alt="" width="80" height="80"
                             style="margin-left: 10px">
                    </label>

                    <input accept="avatar/*" type="file" id="my_file">
                </div>


                <input type="button" value="注册" class="btn btn-primary " id="btn"><span class="error"></span>
            </form>

        </div>

    </div>

</div>
</body>
<script>
    //控件值发生变化的事件
    $("#my_file").change(function () {
        //先取出文件(图片)
        var file_obj = $("#my_file")[0].files[0];
        //通过文件阅读器,把图片放到img标签上
        //生成一个文件阅读器对象
        var filereader = new FileReader()
        //把图片对象,读到filereader对象中
        filereader.readAsDataURL(file_obj)
        //等加载完成,在操作
        filereader.onload=function () {
            $("#img_file").attr('src', filereader.result)
        }


    })

    $("#btn").click(function () {
        //生成formdata对象
        var formdata=new FormData()
        formdata.append('username',$("#id_username").val())
        formdata.append('password',$("#id_password").val())
        formdata.append('re_password',$("#id_re_password").val())
        formdata.append('email',$("#id_email").val())
        formdata.append('csrfmiddlewaretoken',$('[name="csrfmiddlewaretoken"]').val())
       //把文件放到formdata中
        formdata.append('my_file',$('#my_file')[0].files[0])
        $.ajax({
            url:'/register/',
            type:'post',
            processData:false,
            contentType:false,
            data:formdata,
            success:function (data) {
                if(data.status==100){
                    location.href=data.url
                }else{
                    //在之前清除
                    $(".form-group").removeClass('has-error')
                     $(".error").html("")
                    $.each(data.msg,function (key,value) {
                        console.log(key,value)
                        if(key=='__all__'){
                            $("#id_re_password").next().html(value[0])
                        }
                        $("#id_"+key).next().html(value[0]).parent().addClass('has-error')

                    })

                }

            }
        })

    })
//注册用户校验,ok
    $("#id_username").blur(function () {
        $.ajax({
            url:'/check_username/',
            type:'post',
            data:{name:$(this).val(),'csrfmiddlewaretoken':'{{ csrf_token }}'},
            success:function (data) {
                console.log(data)
                if(data.status==101){
                    $('#id_username').next().html(data.msg).parent().addClass('has-error')
                }
            }

        })
    })


</script>
</html>
register.html

 

    backgroud_management(目录下的模板) 

{% extends 'background_management/base.html' %}

{% block home %}


    <div>
        <p>添加文章</p>
        <form action="" method="post">
            {% csrf_token %}
            <p>标题</p>
            <p><input type="text" name="title" class="form-control"></p>
            <p>添加内容 (注:KindEdit编辑器,不支持拖放/粘贴上传图片)</p>
            <p>
             <textarea name="content" id="editor_id" cols="30" rows="10">
             </textarea>
            </p>
            <input type="submit" class="btn btn-danger" value="提交">
        </form>
    </div>



    <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: '500px',
                resizeType: 0,
                uploadJson: '/upload_img/',
                extraFileUploadParams: {
                    'csrfmiddlewaretoken': '{{ csrf_token }}',
                    'article_id': '1'
                },
                filePostName: 'uploadFile'

            })
        });
    </script>
{% endblock %}
add_article.html
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>后台管理</title>
    <script src="../../static/jquery-3.3.1.js"></script>
    <script src="../../static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
    <link rel="stylesheet" href="../../static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <style>
        #bbs {
            border: #9d9d9d 1px solid;
            border-radius: 10px;
        }

        #bbs2 {
            margin: 0;
            padding: 0;
            color: #9d9d9d;
            font-size: 10px;
        }

        #master {
            margin: 0 10px;
        }
        #touxiang {
            display: block;
            width: 37px;
            height: 37px;
            border-radius: 50%;
            background: url("/media/{{ request.user.avatar }}") no-repeat;
            background-size: 37px;
            margin-right: 20px;
        }

        #bbs2 {
            border-radius: 10px;
            text-align: center;
            height: 40px;
            line-height: 40px;
        }
    </style>
</head>
<body>
<div id="master">
    <nav class="navbar navbar-default">
        <div class="container-fluid" id="bbs2">
            <p class="pull-left"><<<a href=""> 网站首页</a></p>
{#            <p class="pull-right">#}
{#                <a href="http://127.0.0.1:8000/127.0.0.1/user_info/">[ 个人中心-</a>#}
{#                <a href="http://127.0.0.1:8000/127.0.0.1/logout/">退出 ]</a>#}
{#            </p>#}
             <ul class="nav navbar-nav navbar-right">
                {% if request.user.is_authenticated %}
                    <li id="touxiang"><a href="/{{ request.user.username }}"></a></li>
                    <li><a href="/{{ request.user.username }}">{{ request.user.username }}</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
                           aria-haspopup="true" aria-expanded="false">个人中心 <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li><a href="#">修改密码</a></li>
                            <li><a href="#">修改头像</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="/logout/">注销</a></li>
                        </ul>
                    </li>
                {% endif %}
            </ul>
        </div>
        <div class="container-fluid" id="bbs">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div>
                <div class="navbar-header">
                    <div><a href="https://www.cnblogs.com"><img src="/static/img/admin_logo.gif" alt=""></a></div>
                </div>
            </div>
        </div>
    </nav>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-2">
                <div>
                    <div class="list-group">
                        <a href="#" class="list-group-item active">
                            操作
                        </a>
                        <a href="/add_article/" class="list-group-item">添加文章</a>
                        <a href="#" class="list-group-item">添加新随笔</a>
                    </div>
                </div>
                <div>
                    <div class="list-group">
                        <a href="#" class="list-group-item active">
                            分类
                        </a>
                        <a href="#" class="list-group-item">1</a>
                        <a href="#" class="list-group-item">2</a>
                        <a href="#" class="list-group-item">3</a>
                        <a href="#" class="list-group-item">4</a>
                    </div>
                </div>
            </div>
            <div class="col-md-10">
                <div>
                    <ul class="nav nav-tabs">
                        <li role="presentation" class="active"><a href="http://127.0.0.1:8000/m/">文章</a></li>
                        <li role="presentation"><a href="#">随笔</a></li>
                        <li role="presentation"><a href="#">评论</a></li>
                        <li role="presentation"><a href="#">点赞</a></li>
                        <li role="presentation"><a href="#">相册</a></li>
                    </ul>
                </div>
                <div class="tab-content">
                    <div role="tabpanel" class="tab-pane active" id="home">
                        {% block home %}
                        {% endblock %}
                    </div>
                    <div role="tabpanel" class="tab-pane" id="profile">随笔页面</div>
                    <div role="tabpanel" class="tab-pane" id="messages">日志页面</div>
                    <div role="tabpanel" class="tab-pane" id="settings">链接页面</div>
                </div>

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

</body>
</html>
base.html
{% extends 'background_management/base.html' %}

{% block home %}

 <table class="table table-hover table-striped">
        <thead>
        <tr>
            <th>文章标题</th>
            <th>发布时间</th>
            <th>评论数</th>
            <th>点赞数</th>
            <th>修改</th>
            <th>删除</th>
        </tr>
        </thead>
        <tbody>
        {% for article in article_list %}
            <tr>
                <td><a href="/{{ request.user.username }}/article/{{ article.pk }}">{{ article.title }}</a></td>
                <td>{{ article.create_time|date:'Y-m-d H:i:s' }}</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/?id={{ article.pk }}">删除</a></td>
            </tr>

        {% endfor %}

        </tbody>

    </table>
{% endblock %}
m.html
{% extends 'background_management/base.html' %}




{% block home %}

    <div>
        <p>修改文章</p>
        <form action="" method="post">
            {% csrf_token %}

            <p>标题</p>
            <p><input type="text" name="title" class="form-control" value="{{ article.title }}"></p>
            <p>内容(KindEdit编辑器,不支持拖放/粘贴上传图片)</p>
            <p>
             <textarea name="content" id="editor_id" cols="30" rows="10">
                {{ article.content }}
                </textarea>
            </p>
            <input type="submit" class="btn btn-danger" value="提交">
        </form>
    </div>

    <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: '500px',
                resizeType: 0,
                uploadJson: '/upload_img/',
                extraFileUploadParams: {
                    'csrfmiddlewaretoken': '{{ csrf_token }}',
                    'article_id': '1'
                },
                filePostName: 'uploadFile'

            })
        });
    </script>

{% endblock %}
update_article.html

    blog_site(目录下的模板)

{% extends 'blog_site/base.html' %}




{% block content %}

    <div>
        <p><h4 class="text-center">{{ article.title }}</h4></p>
        <div>
            {{ article.content|safe }}
        </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>
            <ul class="list-group cotent_ul">
                {% for content in content_list %}
                    <li class="list-group-item">
                        <p><span>#{{ forloop.counter }}楼</span>
                            <span>{{ content.create_time|date:'Y-m-d H:i:s' }}</span>
                            <span><a href="/{{ content.user.username }}">{{ content.user.username }}</a></span>
                            <span class="pull-right replay" username="{{ content.user.username }}"
                                  content_id="{{ content.pk }}">回复</span>
                        </p>
                        {% if content.parent %}
                            <p class="well">@{{ content.parent.user.username }}</p>

                        {% endif %}
                        {{ content.content }}
                    </li>
                {% endfor %}


            </ul>
        </div>
        <div>
            <p>发表评论</p>
            <p>
                昵称:<input type="text" id="tbCommentAuthor" class="author" disabled="disabled" size="50" value="{{ request.user.username }}">
            </p>
            <p>评论内容:</p>
            <p>
                <textarea name="" id="content" cols="60" rows="10">


            </textarea>
            </p>
            <button class="btn btn-primary submit">提交</button>


        </div>
    </div>

    <script>
        var pid = '';
        $('.submit').click(function () {
            var content = $("#content").val()
            $("#content").val("")

            if (pid) {
                var index = content.indexOf('\n') + 1
                content = content.slice(index)
            }

            $.ajax({
                url: '/commit_content/',
                type: 'post',
                data: {
                    'article_id': '{{ article.pk }}',
                    'content': content,
                    'pid': pid,
                    'csrfmiddlewaretoken': '{{ csrf_token }}'
                },
                success: function (data) {
                    var time = data.time;
                    var content = data.content;
                    var user_name = data.user_name;
                    var ss = '';
                    if (pid) {

                        pid = '';
                        var parent_name = data.parent_namel;
                        ss = `
                         <li class="list-group-item">
                         <p>
                         <span>${ user_name }</span>
                            <span>${ time }</span>
                        </p>
                            <p class="well">@${parent_name }</p>
                        ${content}
                    </li>
                        `
                    } else {
                        ss = `
                      <li class="list-group-item">
                        <p>
                            <span>${ user_name }</span>:
                            <span>${ time }</span>
                        </p>
                         ${content}
                    </li>
                    `
                    }

                    $(".cotent_ul").append(ss)

                }
            })
        })
        $(".replay").click(function () {
            var username = $(this).attr('username');
            $('#content').val('@' + username + '\n');
            $('#content').focus();
            pid = $(this).attr('content_id')


        })
        $(".action").click(function () {
            var is_up = $(this).hasClass('diggit')

            var obj = $(this).children('span')

            $.ajax({
                url: '/diggit/',
                type: 'post',
                data: {article_id: '{{ article.pk }}', is_up: is_up, 'csrfmiddlewaretoken': '{{ csrf_token }}'},
                success: function (data) {
                    $("#digg_tips").html(data.msg)
                    if (data.status == 100) {
                        obj.text(Number(obj.text()) + 1)

                    }

                    setTimeout(function () {
                        $("#digg_tips").html("")
                    }, 3000)

                }
            })

        });

    </script>

{% endblock %}
article_detail.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ blog.userinfo.username }}-的个人博客</title>
    {% block mytitle %}
    {% endblock %}
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css">
    <link rel="stylesheet" href="/static/css/{{ blog.theme }}">
    <link rel="stylesheet" href="/static/css/blog.css">
    <script src="/static/jquery-3.3.1.js"></script>
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
    {% block blog %}

    {% endblock %}
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        #bbs2 {
            border: #9d9d9d 1px solid;
            border-radius: 10px;
            text-align: center;
            height: 40px;
            line-height: 40px;
        }

        #touxiang {
            display: block;
            width: 37px;
            height: 37px;
            border-radius: 50%;
            background: url("/media/{{ request.user.avatar }}") no-repeat;
            background-size: 37px;
            margin-right: 20px;
        }

    </style>
</head>
<body>
<nav class="navbar navbar-default">
    <div class="container-fluid" id="bbs2">
        <div class="pull-left">{{ blog.title }}</div>
        <div class="pull-right " id="pull-right">
            <ul class="nav navbar-nav navbar-right">
                {% if request.user.is_authenticated %}
                    <li id="touxiang"><a href="/{{ request.user.username }}"></a></li>
                    <li><a href="/{{ request.user.username }}">{{ request.user.username }}</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
                           aria-haspopup="true" aria-expanded="false">个人中心 <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li><a href="#">修改密码</a></li>
                            <li><a href="#">修改头像</a></li>
                            <li><a href="http://127.0.0.1:8000/m/">后台管理</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="/logout/">注销</a></li>
                        </ul>
                    </li>
                {% else %}
                    <li><a href="/login/">登录</a></li>
                    <li><a href="/register/">注册</a></li>
                {% endif %}
            </ul>
        </div>
    </div>
</nav>

<div class="container-fluid">
    <div class="row">
        <div class="col-md-3">
            {% load my_tag %}
            {% classify username %}
        </div>
        <div class="col-md-9">
            {% block content %}

            {% endblock %}

        </div>
    </div>
</div>
</div>
</body>
</html>
base.html
<div>
    <div class="panel panel-primary">
        <div class="panel-heading">我的标签</div>
        <div class="panel-body">
            {% for foo in tag_num %}
                <p><a href="/{{ username }}/tag/{{ foo.2 }}">{{ foo.0 }}({{ foo.1 }})</a></p>
            {% endfor %}
        </div>
    </div>

    <div class="panel panel-primary">
        <div class="panel-heading">我的分类</div>
        <div class="panel-body">
            {% for foo in category_num %}
                <p><a href="/{{ username }}/category/{{ foo.2 }}">{{ foo.0 }}({{ foo.1 }})</a></p>
            {% endfor %}

        </div>
    </div>

    <div class="panel panel-primary">
        <div class="panel-heading">随笔档案</div>
        <div class="panel-body">
            {% for foo in y_m_num %}
                <p><a href="/{{ username }}/archive/{{ foo.0|date:"Y-m" }}">{{ foo.0|date:"Y-m" }}({{ foo.1 }})</a></p>
            {% endfor %}

        </div>
    </div>
</div>
classify.html
{% extends 'blog_site/base.html' %}
{% block content %}

    {% for article in article_list %}
        <h4><a href="/{{ username }}/article/{{ article.pk }}">{{ article.title }}</a></h4>

        <div>
            {{ article.desc }}
        </div>

        <div class="clearfix">
            <div style="margin-top: 10px " class="article_bottom small pull-right">
                <span>posted @ {{ article.create_time|date:'Y-m-d H:i:s' }}</span>
                <span>{{ article.blog.userinfo.username }}</span>
                <span><i class="fa fa-comment" aria-hidden="true"><a
                        href="">评论({{ article.commit_num }})</a></i></span>
                <span class="glyphicon glyphicon-thumbs-up"><a href="">点赞({{ article.up_num }})</a></span>
                <span><a href="">编辑</a></span>
            </div>
        </div>
        <hr>
    {% endfor %}

{% endblock %}
user_blog

 

注:

  由于系统环境和工具版本,模块版本的诸多因素的限制,会导致您按照本人的配置的bbs系统无法启动,请不要着急,本人给出仅仅是供大家学习参考,也许您写的比本人的更完善。错误之处请指正,共勉之。

 

posted on 2018-12-27 22:50  漫天飞雪世情难却  阅读(169)  评论(0编辑  收藏  举报