Django手擼一個部落格專案

我可是小老虎發表於2020-11-10

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 %}

相關文章