博客项目代码整理

目录结构如下:

cnblog

 1 # 修改部分
 2 STATIC_URL = '/static/'
 3 STATICFILES_DIRS = [
 4     os.path.join(BASE_DIR, 'app01', "static")
 5 ]
 6 
 7 AUTH_USER_MODEL = 'app01.UserInfo'
 8 
 9 MEDIA_URL = "/media/"
10 MEDIA_ROOT = os.path.join(BASE_DIR, "app01", "media")
settings
 1 urlpatterns = [
 2     url(r'^admin/', admin.site.urls),
 3 
 4     url(r'^$', views.index),
 5     url(r'^login/', views.log_in),
 6     url(r'^logout/', views.logout),
 7     url(r'^get_valid_img/', views.get_valid_img),
 8     url(r'^index/', views.index),
 9 
10     url(r'^register/', views.register),
11     url(r'^change_pwd/', views.change_pwd),  # 修改密码 未写
12     # blog url的分发
13     url(r'^blog/', include("app01.url")),
14     # media 配置
15     url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
16 
17     # 配置添加文章中的文件上传路径 文本编辑器的指定路径
18     url(r'^upload_file/',views.upload_file),
19 ]
urls
import os
from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cnbolg.settings")

application = get_wsgi_application()
wsgi

app01

 1 from django import template
 2 from app01.models import *
 3 from django.db.models import Count
 4 # from django.utils.safestring import mark_safe
 5 
 6 register = template.Library()  # register的名字是固定的,不能改变
 7 
 8 
 9 @register.inclusion_tag("blog/archive.html")
10 def get_archive_style(username):
11     user = UserInfo.objects.filter(username=username).first()
12     # 当前站点
13     blog = user.blog
14     # 查询当前站点的所有分类
15     # category_list=Category.objects.filter(blog_id=blog.pk)
16     # 查询每一个分类名称以及对应的文章数
17     cate_list = Category.objects.filter(blog=blog).annotate(c=Count("article")).values_list("title", "c")
18 
19     # 查询但当前站点每一个标签名称以及对应的文章数
20     tag_list = Tag.objects.filter(blog=blog).annotate(c=Count("article")).values_list("title", "c")
21 
22     # 日期归档   [["2018-02",5],["2010-9",6]]
23     date_list = Article.objects.filter(user=user) \
24         .extra(select={"create_time_ym": "strftime('%%Y/%%m',create_time)"}) \
25         .values("create_time_ym") \
26         .annotate(c=Count("nid")).values_list("create_time_ym", "c")
27 
28     return {"cate_list": cate_list, "tag_list": tag_list, "date_list": date_list, "username": username}
templatetags/my_tags
 1 import random
 2 
 3 
 4 def get_valid_img(request):
 5     def get_random_color():
 6         return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
 7 
 8     from io import BytesIO
 9     from PIL import Image, ImageDraw, ImageFont
10     f = BytesIO()
11 
12     image = Image.new(mode='RGB', size=(120, 80), color=get_random_color())
13     draw = ImageDraw.Draw(image)
14     font = ImageFont.truetype('app01/static/fonts/kumo.ttf', size=36)
15 
16     temp = []
17     for i in range(5):
18         random_char = random.choice([str(random.randint(0, 9)),
19                                      chr(random.randint(65, 90)),
20                                      chr(random.randint(97, 122))
21                                      ])
22         draw.text((i * 24, 26), random_char, get_random_color(), font=font)
23         temp.append(random_char)
24 
25     # width = 120
26     # height = 80
27     # for i in range(80):
28     #     draw.point((random.randint(0,width),random.randint(0,height)),fill=get_random_color())
29     #
30     # for i in range(10):
31     #     x1=random.randint(0,width)
32     #     x2=random.randint(0,width)
33     #     y1=random.randint(0,height)
34     #     y2=random.randint(0,height)
35     #     draw.line((x1,y1,x2,y2),fill=get_random_color())
36     # for i in range(40):
37     #     draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
38     #     x = random.randint(0, width)
39     #     y = random.randint(0, height)
40     #     draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_color())
41     image.save(f, "png")
42     data = f.getvalue()
43 
44     return data, temp
utils/valid_code
 1 from django.contrib import admin
 2 
 3 # Register your models here.
 4 from .models import *
 5 
 6 admin.site.register(Article)
 7 admin.site.register(UserInfo)
 8 admin.site.register(Blog)
 9 admin.site.register(Tag)
10 admin.site.register(Category)
11 admin.site.register(Comment)
12 admin.site.register(ArticleUpDown)
13 admin.site.register(ArticleDetail)
14 admin.site.register(Article2Tag)
admin
 1 from django import forms
 2 from django.core.exceptions import ValidationError
 3 from django.forms import widgets
 4 from app01.models import *
 5 
 6 
 7 class RegisterForm(forms.Form):
 8     user = forms.CharField(max_length=18,
 9                            min_length=3,
10                            error_messages={
11                                'required': '不能为空',
12                                'max_length': '用户名太长',
13                                'min_length': '用户名太短'
14                            },
15                            widget=widgets.TextInput(attrs={"class": "form-control", "placeholder": "用户名"}))
16     pwd = forms.CharField(max_length=18,
17                           min_length=3,
18                           error_messages={
19                               'required': '不能为空',
20                               'max_length': '密码太长',
21                               'min_length': '密码太短'
22                           },
23                           widget=widgets.PasswordInput(attrs={"class": "form-control", "placeholder": "密码"}))
24     repeat_pwd = forms.CharField(min_length=5, error_messages={"required": "该字段不能为空"},
25                                  widget=widgets.PasswordInput(attrs={"class": "form-control", "placeholder": "确认密码"})
26                                  )
27     email = forms.EmailField(error_messages={"required": "该字段不能为空", "invalid": "格式错误"},
28                              widget=widgets.EmailInput(attrs={"class": "form-control", "placeholder": "邮箱"})
29                              )
30 
31     def clean_user(self):
32         val = self.cleaned_data.get('user')
33         ret = UserInfo.objects.filter(username=val)
34         if not ret:
35             return val
36         else:
37             raise ValidationError('该用户已经被注册!')
38 
39     def clean_tel(self):
40         val = self.cleaned_data.get('tel')
41         import re
42         ret = re.search('1[356789]\d{9}$', val)
43         if ret:
44             return val
45         else:
46             raise ValidationError('手机号格式错误')
47 
48     def clean(self):
49         pwd = self.cleaned_data.get('pwd')
50         repeat_pwd = self.cleaned_data.get('repeat_pwd')
51         if pwd and repeat_pwd:
52             if pwd == repeat_pwd:
53                 return self.cleaned_data
54             else:
55                 raise ValidationError('两次密码不一致')
56         else:
57             return self.cleaned_data
forms
  1 from django.db import models
  2 
  3 # Create your models here.
  4 from django.contrib.auth.models import AbstractUser
  5 
  6 
  7 class UserInfo(AbstractUser):  # 用户信息
  8     nid = models.AutoField(primary_key=True)
  9     nickname = models.CharField(verbose_name='昵称', max_length=32)
 10     telephone = models.CharField(max_length=11, null=True, unique=True)
 11     avatar = models.FileField(upload_to='avatar_dir/', default='/avatar/default.png')
 12     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
 13     blog = models.OneToOneField(to='Blog', to_field='nid', null=True)
 14 
 15     def __str__(self):
 16         return self.username
 17 
 18 
 19 class Blog(models.Model):  # 博客信息
 20     nid = models.AutoField(primary_key=True)
 21     title = models.CharField(verbose_name="个人博客标题", max_length=64)
 22     site = models.CharField(verbose_name="个人博客后缀", max_length=32, unique=True)
 23     theme = models.CharField(verbose_name="博客主题", max_length=32)
 24 
 25     def __str__(self):
 26         return self.title
 27 
 28 
 29 class Category(models.Model):  # 博主个人文章分类表
 30     nid = models.AutoField(primary_key=True)
 31     title = models.CharField(verbose_name='分类标题', max_length=32)
 32     blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field="nid")
 33 
 34     def __str__(self):
 35         return self.title
 36 
 37 
 38 class Tag(models.Model):
 39     nid = models.AutoField(primary_key=True)
 40     title = models.CharField(verbose_name="标签名称", max_length=32)
 41     blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid')
 42 
 43     def __str__(self):
 44         return self.title
 45 
 46 
 47 class Article(models.Model):
 48     nid = models.AutoField(primary_key=True)
 49     title = models.CharField(max_length=50, verbose_name='文章标题')
 50     desc = models.CharField(max_length=255, verbose_name='文章描述')
 51     create_time = models.DateTimeField(verbose_name='创建时间')
 52 
 53     comment_count = models.IntegerField(default=0)
 54     up_count = models.IntegerField(default=0)
 55     down_count = models.IntegerField(default=0)
 56 
 57     Category = models.ForeignKey(to= 'Category', to_field='nid', null=True)
 58     tags = models.ManyToManyField(
 59         to='Tag',
 60         through='Article2Tag',
 61         through_fields=('article', 'tag')
 62     )
 63     user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid')
 64 
 65     def __str__(self):
 66         return self.title
 67 
 68 
 69 class ArticleDetail(models.Model):
 70     nid = models.AutoField(primary_key=True)
 71     content = models.TextField()
 72 
 73     article = models.OneToOneField(to='Article', to_field='nid')
 74 
 75 
 76 class ArticleUpDown(models.Model):
 77     nid = models.AutoField(primary_key=True)
 78     user = models.ForeignKey('UserInfo', null=True)
 79     article = models.ForeignKey('Article', null=True)
 80     is_up = models.BooleanField(default=True)
 81 
 82     class Meta:
 83         unique_together = [('article', 'user'), ]
 84 
 85 
 86 class Article2Tag(models.Model):
 87     nid = models.AutoField(primary_key=True)
 88     article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid')
 89     tag = models.ForeignKey(verbose_name='标签', to='Tag', to_field='nid')
 90 
 91     class Meta:
 92         unique_together = [('article', 'tag'), ]
 93 
 94     def __str__(self):
 95         v = self.article.title + "-----" + self.tag.title
 96         return v
 97 
 98 
 99 class Comment(models.Model):
100     nid = models.AutoField(primary_key=True)
101     article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid')
102     user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid')
103     content = models.CharField(verbose_name='评论内容', max_length=255)
104     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
105 
106     parent_comment = models.ForeignKey('self', null=True)
107 
108     def __str__(self):
109         return self.content
models
 1 from django.conf.urls import url, include
 2 from app01 import views
 3 
 4 urlpatterns = [
 5     #  文章详细页的点赞和评论
 6     url(r'^digg/$', views.digg),
 7     url(r'^comment/$',views.comment),
 8     url(r'^get_comment_tree/(\d+)/$',views.get_comment_tree),
 9 
10 
11     url(r'^(?P<username>\w+)/backend/$',views.backend),
12     url(r'^(?P<username>\w+)/backend_add_article/$',views.backend_add_article),
13 
14     # 个人站点的url配置
15     url(r'^(?P<username>\w+)/articles/(?P<article_id>\d+)\.html/$', views.article_detail),
16     url(r'^(?P<username>\w+)/$', views.home_site),
17     url(r'^(?P<username>\w+)/(?P<condition>cate|tag|date)/(?P<params>(\w+/?\w+))$', views.home_site),
18 ]
url
  1 from django.shortcuts import render, HttpResponse, redirect
  2 from .models import *
  3 from .models import UserInfo
  4 from app01.forms import RegisterForm
  5 from django.contrib import auth
  6 from django.db.models import F
  7 from django.db import transaction
  8 from django.http import JsonResponse
  9 import json
 10 
 11 
 12 # 登录页
 13 def log_in(request):
 14     if request.is_ajax():
 15         user = request.POST.get("user")
 16         pwd = request.POST.get("pwd")
 17         valid_code = request.POST.get("valid_code")
 18         code_str = request.session.get("random_code_str")
 19         # 构造返回给前端的字典
 20         login_response = {"user": None, "error_msg": ""}
 21 
 22         if valid_code.upper() == code_str.upper():
 23             user = auth.authenticate(username=user, password=pwd)
 24             if user:
 25                 login_response["user"] = user.username
 26                 auth.login(request, user)
 27             else:
 28                 login_response["error_msg"] = "username or password error!"
 29         else:
 30             login_response["error_msg"] = "valid code error!"
 31         return HttpResponse(json.dumps(login_response))
 32 
 33     return render(request, "login.html")
 34 
 35 
 36 # 主页
 37 def index(request):
 38     username = request.user
 39     article_list = Article.objects.all()
 40     return render(request, 'index.html', locals())
 41 
 42 
 43 # 退出登录
 44 def logout(request):
 45     auth.logout(request)
 46     # return HttpResponse('OK')
 47     return redirect('/login/')
 48 
 49 
 50 # 注册页
 51 def register(request):
 52     # if request.method == "POST":
 53     if request.is_ajax():
 54         register_form = RegisterForm(request.POST)  # 接收前端ajax传过来的对象
 55         reg_response = {"user": None, "error_msg": None}  # 定义返回给前端的数据格式
 56         if register_form.is_valid():
 57             user = register_form.cleaned_data.get("user")
 58             pwd = register_form.cleaned_data.get("pwd")
 59             email = register_form.cleaned_data.get("email")
 60             avatar_obj = request.FILES.get('avatar')  # 图片对象
 61             if avatar_obj:
 62                 user_obj = UserInfo.objects.create_user(username=user, password=pwd, email=email, avatar=avatar_obj)
 63             else:
 64                 user_obj = UserInfo.objects.create_user(username=user, password=pwd, email=email)
 65             reg_response["user"] = user_obj.username
 66         else:
 67             reg_response["error_msg"] = register_form.errors
 68         return HttpResponse(json.dumps(reg_response))
 69 
 70     register_form = RegisterForm()
 71     return render(request, "register.html", {"register_form": register_form})
 72 
 73 
 74 # 验证码
 75 def get_valid_img(request):
 76     '''
 77     :param request:
 78     :get_valid_img: 生成验证码,返回图片数据
 79     :return:
 80     '''
 81 
 82     from app01.utils.valid_code import get_valid_img
 83     info = get_valid_img(request)
 84 
 85     request.session["random_code_str"] = "".join(info[1])
 86     '''
 87        if cookie.get(sesssion):更新
 88 
 89        1 生成随机字符串
 90        2 响应set_cookie {"sessionId":"123456abc"}
 91        3 在django-session表中插入一条记录
 92           session-key   session-data
 93           123456abc      {"random_code_str":"abc12"}
 94        '''
 95 
 96     return HttpResponse(info[0])
 97 
 98 
 99 # 修改密码
100 def change_pwd(request):
101     if request.method == 'POST':
102         user = request.user.username
103         old_pwd = request.POST.get('old_pwd')
104         new_pwd = request.POST.get('new_pwd')
105 
106         # 构造返回给前端的字典
107         change_response = {"flag": False}
108         user_obj = auth.authenticate(username=user, password=old_pwd)
109         if user_obj:
110             if new_pwd == "":
111                 change_response["error_msg"] = "新密码不能为空"
112             else:
113                 user_obj.set_password(new_pwd)
114                 user_obj.save()
115                 logout(request)
116                 change_response['flag'] = True
117         else:
118             change_response["error_msg"] = "旧密码错误"
119         return HttpResponse(json.dumps(change_response))
120     return render(request, "change_pwd.html")
121 
122 
123 # 个人主页
124 def home_site(request, username, **kwargs):
125     # 判断用户是否存在
126     user = UserInfo.objects.filter(username=username).first()
127     if not user:
128         return render(request, "blog/not_found.html")
129     blog = user.blog  # 当前站点
130 
131     if not kwargs:
132         # 筛选当前站点的所有文章
133         article_list = Article.objects.filter(user=user)
134     else:
135         # 归档跳转标签的请求,对article_list过滤
136         condition = kwargs.get("condition")
137         params = kwargs.get("params")
138         if condition == "cate":
139             article_list = Article.objects.filter(user=user).filter(Category__title=params)
140         elif condition == "tag":
141             article_list = Article.objects.filter(user=user).filter(tags__title=params)
142         else:
143             year, month = params.split("/")
144             article_list = Article.objects.filter(user=user).filter(create_time__year=year, create_time__month=month)
145     return render(request, "blog/home_site.html", locals())
146 
147 
148 # 文章详细页
149 def article_detail(request, username, article_id):
150     article_obj = Article.objects.filter(pk=article_id).first()
151     comment_list = Comment.objects.filter(article_id=article_id)
152     return render(request, "blog/article_detail.html",
153                   {"username": username, "article_obj": article_obj, "comment_list": comment_list})
154 
155 
156 # 点赞
157 def digg(request):
158     article_id = request.POST.get("article_id")
159     is_up = json.loads(request.POST.get("is_up"))
160     user_id = request.user.pk
161     response = {"state": True}
162     try:
163         with transaction.atomic():  # 事务
164             obj = ArticleUpDown.objects.create(user_id=user_id, article_id=article_id, is_up=is_up)
165             if is_up:
166                 Article.objects.filter(pk=article_id).update(up_count=F("up_count") + 1)
167             else:
168                 Article.objects.filter(pk=article_id).update(down_count=F("down_count") + 1)
169     except Exception as e:
170         first_updown = ArticleUpDown.objects.filter(user_id=user_id, article_id=article_id).values("is_up").first().get(
171             "is_up")
172         response["state"] = False
173         response["first_updown"] = first_updown
174 
175     return JsonResponse(response)
176 
177 
178 # 评论
179 def comment(request):
180     content = request.POST.get("content")
181     article_id = request.POST.get("article_id")
182     user_id = request.user.pk
183     pid = request.POST.get("pid")
184 
185     comment_response = {}
186     with transaction.atomic():
187         if pid:  # 子评论
188             comment = Comment.objects.create(content=content, article_id=article_id, user_id=user_id,
189                                              parent_comment_id=pid)
190         else:
191             comment = Comment.objects.create(content=content, article_id=article_id, user_id=user_id)
192         Article.objects.filter(pk=article_id).update(comment_count=F("comment_count") + 1)
193 
194         comment_response["create_time"] = comment.create_time.strftime("%Y-%m-%d %H:%M")
195         comment_response["content"] = comment.content
196     return HttpResponse(json.dumps(comment_response))
197 
198 
199 # 管理
200 def backend(request, username):
201     article_list = Article.objects.filter(user__username=username)
202     return render(request, "blog/backend_index.html", {"username": username, "article_list": article_list})
203 
204 
205 # 管理后台添加文章
206 def backend_add_article(request, username):
207     if request.method == "POST":
208         content = request.POST.get("content")
209 
210         # 用BeautifulSoup过滤content
211         valid_tags_attrs_list = {
212             "div": ["id", "class", "style"],
213             "img": ["src", "width", "height"],
214             "a": ["href"],
215             "p": [],
216         }
217         from bs4 import BeautifulSoup
218         soup = BeautifulSoup(content, "html.parser")
219         tags_list = soup.find_all()
220 
221         for tag in tags_list:
222             if tag.name not in valid_tags_attrs_list:
223                 tag.decompose()
224         print("count:", soup)
225 
226     return render(request, "blog/backend_add_article.html")
227 
228 
229 #  编辑器上传文件
230 def upload_file(request):
231     print(request.FILES)
232     # 保存上传到指定路径
233     obj = request.FILES.get("upload_img")
234 
235     from django.core.files.uploadedfile import InMemoryUploadedFile
236     from cnbolg import settings
237     import os
238     path = os.path.join(settings.MEDIA_ROOT, "article_imgs", obj.name)
239     with open(path, "wb") as f_write:
240         for chunk in obj.chunks():
241             f_write.write(chunk)
242 
243     # 给本文编辑器返回json字符串
244     upload_response = {
245         "error": 0,
246         "url": "/media/article_imgs/%s" % obj.name
247     }
248 
249     return HttpResponse(json.dumps(upload_response))
250 
251 
252 # 评论树
253 def get_comment_tree(request, article_id):
254     comment_list = list(
255         Comment.objects.filter(article_id=article_id).values("nid", "content", "parent_comment_id", "user__username"))
256     return JsonResponse(comment_list, safe=False)
!!! views

templates

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6     <meta name="viewport" content="width=device-width, initial-scale=1">
  7     <title>YueNet</title>
  8     <link rel="stylesheet" href="/static/bs/css/bootstrap.css">
  9     <link rel="stylesheet" href="/static/css/index.css">
 10     <script src="/static/js/jquery-3.2.1.min.js"></script>
 11     <script src="/static/bs/js/bootstrap.js"></script>
 12 </head>
 13 <body>
 14 <!--顶部导航条-->
 15 <nav class="navbar navbar-inverse">
 16     <div class="container">
 17         <!-- Brand and toggle get grouped for better mobile display -->
 18         <div class="navbar-header">
 19             <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
 20                     data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
 21                 <span class="sr-only"></span>
 22                 <span class="icon-bar"></span>
 23                 <span class="icon-bar"></span>
 24                 <span class="icon-bar"></span>
 25             </button>
 26             <a class="navbar-brand" href="#">YueNet</a>
 27         </div>
 28 
 29         <!-- Collect the nav links, forms, and other content for toggling -->
 30         <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
 31             <ul class="nav navbar-nav">
 32             </ul>
 33 
 34             {% if request.user.is_authenticated %}
 35                 <ul class="nav navbar-nav navbar-right">
 36                     <li><a href="#">
 37                         <span class="glyphicon glyphicon-user"></span>&nbsp;&nbsp;{{ request.user.username }}</a></li>
 38                     <li><a href="/logout/">退出</a></li>
 39                     <li class="dropdown">
 40                         <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
 41                            aria-expanded="false">我的博客 <span class="caret"></span></a>
 42                         <ul class="dropdown-menu">
 43                             <li><a href="/change_pwd/">修改密码</a></li>
 44                             <li><a href="#">我的设置</a></li>
 45                             <li><a href="#">我的收藏</a></li>
 46                             <li role="separator" class="divider"></li>
 47                             <li><a href="#">注销账号</a></li>
 48                         </ul>
 49                     </li>
 50                 </ul>
 51             {% else %}
 52                 <ul class="nav navbar-nav navbar-right">
 53                     <li><a href="/login/">登录</a></li>
 54                     <li><a href="/register/">注册</a></li>
 55                 </ul>
 56             {% endif %}
 57         </div><!-- /.navbar-collapse -->
 58     </div><!-- /.container-fluid -->
 59 </nav>
 60 
 61 <!--页面主体开始-->
 62 <div class="container-fluid">
 63     <div class="row">
 64         <!-- 左侧菜单 -->
 65         <div class="col-md-3">
 66             <div class="panel panel-primary">
 67                 <!-- Default panel contents -->
 68                 <div class="panel-heading">文章分类</div>
 69                 <div class="panel-body">
 70                     <p>...</p>
 71                 </div>
 72             </div>
 73             <div class="panel panel-success">
 74                 <!-- Default panel contents -->
 75                 <div class="panel-heading">推荐博客</div>
 76                 <div class="panel-body">
 77                     <p>...</p>
 78                 </div>
 79             </div>
 80             <div class="panel panel-danger">
 81                 <!-- Default panel contents -->
 82                 <div class="panel-heading">统计信息</div>
 83                 <div class="panel-body">
 84                     <p>...</p>
 85                 </div>
 86             </div>
 87         </div>
 88         <!-- 文章列表 -->
 89         <div class="col-md-6">
 90             <div class="article_list">
 91                 {% for article_obj in article_list %}
 92                     <div class="article_item">
 93                         <h4><a href="/blog/{{ article_obj.user.username }}/articles/{{ article_obj.pk }}.html">{{ article_obj.title }}</a></h4>
 94                         <div class="row">
 95                             <div class="col-md-2">
 96                                 <a href="/blog/{{ article_obj.user.username }}">
 97                                     <img src="{{ article_obj.user.avatar.url }}" alt="" width="70" height="70">
 98                                 </a>
 99                             </div>
100                             <div class="desc">
101                                 <p>{{ article_obj.desc }}</p>
102                             </div>
103                         </div>
104                         <div class="small">
105                             <a href="/blog/{{ article_obj.user.username }}">{{ article_obj.user.username }}</a>
106                             <span>发布于</span>
107                             <span>{{ article_obj.create_time|date:'Y-m-d H:i' }}</span>&nbsp;&nbsp;
108                             <span class="glyphicon glyphicon-comment"></span>评论({{ article_obj.comment_count }})&nbsp;&nbsp;
109                             <span class="glyphicon glyphicon-thumbs-up"></span>点赞({{ article_obj.up_count }})
110                         </div>
111                     </div>
112                 {% endfor %}
113             </div>
114             <!-- 广告 -->
115             <div class="col-md-3"></div>
116         </div>
117     </div>
118 
119 
120 </body>
121 </html>
index
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 6     <meta name="viewport" content="width=device-width, initial-scale=1">
 7     <link rel="stylesheet" href="/static/bs/css/bootstrap.css">
 8     <script src="/static/js/jquery-3.2.1.min.js"></script>
 9     <title>登录页</title>
10 </head>
11 
12 <body>
13 <h3>登录页面</h3>
14 <div class="container">
15     <div class="row">
16         <div class="col-md-6 col-md-offset-3">
17             <form>
18                 {% csrf_token %}
19                 <div class="form-group">
20                     <label for="user">用户名</label>
21                     <input type="text" class="form-control" id="user" placeholder="Username">
22                 </div>
23                 <div class="form-group">
24                     <label for="pwd">密码</label>
25                     <input type="password" class="form-control" id="pwd" placeholder="Password">
26                 </div>
27                 <div class="row">
28                     <div class="col-md-6">
29                         <div class="form-group">
30                             <label for="valid_code">验证码</label>
31                             <input type="text" class="form-control" id="valid_code" placeholder="验证码">
32                         </div>
33                     </div>
34                     <div class="col-md-6">
35                         <img id="valid_img" width="260" height="60" src="/get_valid_img/" alt="">
36                     </div>
37                 </div>
38                 <input type="button" value="submit" class="btn btn-primary pull-right login_btn">
39                 <span class="error"> </span>
40             </form>
41         </div>
42     </div>
43 </div>
44 
45 <script>
46     $('.login_btn').click(function () {
47 
48         $.ajax({
49             url: '',
50             type: 'post',
51             data: {
52                 "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(),
53                 'user': $('#user').val(),
54                 'pwd': $('#pwd').val(),
55                 'valid_code': $('#valid_code').val()
56             },
57 
58             success: function (data) {
59                 var login_response = JSON.parse(data);
60                 console.log(login_response);
61                 if (login_response.user) {       // 登录成功
62                     location.href = '/index/'
63                 }
64                 else {          // 登录失败
65                     $('.error').html(login_response.error_msg).css('color', 'red');
66 
67                     setTimeout(function () {
68                         $('.error').html('')
69                     }, 1000)
70                 }
71             }
72         })
73     });
74     // 验证码点击刷新
75     $("#valid_img").click(function () {
76         $(this)[0].src += "?"
77     })
78 
79 
80 </script>
81 </body>
82 </html>
login
  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6     <meta name="viewport" content="width=device-width, initial-scale=1">
  7     <title>注册页</title>
  8     <link rel="stylesheet" href="/static/bs/css/bootstrap.css">
  9     <script src="/static/js/jquery-3.2.1.min.js"></script>
 10 </head>
 11 <body>
 12 <h3>注册页</h3>
 13 
 14 <div class="container">
 15     <div class="row">
 16         <div class="col-md-6 col-md-offset-3">
 17             <form>
 18                 {% csrf_token %}
 19                 <div>
 20                     <label for="id_user">用户名</label>
 21                     {{ register_form.user }}
 22                     <span class="pull-right"></span>
 23                 </div>
 24                 <div class="form-group">
 25                     <label for="id_pwd">密码</label>
 26                     {{ register_form.pwd }}
 27                     <span class="pull-right"></span>
 28                 </div>
 29                 <div class="form-group">
 30                     <label for="id_repeat_pwd">确认密码</label>
 31                     {{ register_form.repeat_pwd }}
 32                     <span class="pull-right"></span>
 33                 </div>
 34                 <div class="form-group">
 35                     <label for="id_email">邮箱</label>
 36                     {{ register_form.email }}
 37                     <span class="pull-right"></span>
 38                 </div>
 39                 <div class="form-group">
 40                     <label for="avatar">
 41                         头像
 42                         <img id="avater_img" src='/static/img/default.png' alt="" width="60" height="60">
 43                     </label>
 44                     <input type="file" style="display: none;" id="avatar">
 45                     <input type="button" value="submit" class="btn btn-primary pull-right reg_btn"> <span
 46                         class="error"></span>
 47                 </div>
 48             </form>
 49         </div>
 50     </div>
 51 </div>
 52 
 53 <script>
 54     // 头像预览功能
 55     $("#avatar").change(function () {
 56         var choose_file = $(this)[0].files[0];
 57         var reader = new FileReader();
 58         reader.readAsDataURL(choose_file);
 59         reader.onload = function () {
 60             $("#avater_img").attr("src", this.result)
 61         }
 62     });
 63 
 64     // ajax提交数据
 65     $(".reg_btn").click(function () {
 66         var formdata = new FormData();
 67         formdata.append("user", $("#id_user").val());
 68         formdata.append("pwd", $("#id_pwd").val());
 69         formdata.append("repeat_pwd", $("#id_repeat_pwd").val());
 70         formdata.append("email", $("#id_email").val());
 71         formdata.append("avatar", $("#avatar")[0].files[0]);
 72         formdata.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
 73 
 74         $.ajax({
 75             url: "",
 76             type: "post",
 77             data: formdata,
 78             contentType: false,
 79             processData: false,
 80             success: function (data) {
 81                 console.log(data);
 82                 data = JSON.parse(data);
 83                 if (data.user) {
 84                     location.href = "/login/"
 85                 }
 86                 else {
 87                     // 清空上次错误信息
 88                     $("form span").html("");
 89                     $(".form-group").removeClass("has-error");
 90 
 91                     // 显示当前错误信息
 92                     $.each(data.error_msg, function (field, error_info) {
 93                         console.log(field, error_info[0]);
 94                         $("#id_" + field).parent().addClass("has-error");
 95                         $("#id_" + field).next().html(error_info[0]).css("color", "red");
 96                         // 判断全局错误
 97                         if (field == "__all__") {
 98                             $("#id_repeat_pwd").next().html(error_info[0]).css("color", "red");
 99                             $("#id_repeat_pwd").parent().addClass("has-error");
100                         }
101                     });
102                 }
103             }
104         })
105     });
106 
107 </script>
108 
109 </body>
110 </html>
register
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 6     <meta name="viewport" content="width=device-width, initial-scale=1">
 7     <title>修改密码</title>
 8     <link rel="stylesheet" href="/static/bs/css/bootstrap.css">
 9     <script src="/static/js/jquery-3.2.1.min.js"></script>
10 </head>
11 <body>
12 <h3>修改密码</h3>
13 <div class="container">
14     <div class="row">
15         <div class="col-md-6 col-md-offset-3">
16             <form>
17                 {% csrf_token %}
18                 <div class="form-group">
19                     <label for="user">当前用户</label>
20                     <input type="text" class="form-control" id="user" placeholder={{ request.user }} disabled>
21                 </div>
22                 <div class="form-group">
23                     <label for="pwd">当前密码</label>
24                     <input type="password" class="form-control" id="old_password" placeholder="Old_Password">
25                 </div>
26                 <div class="form-group">
27                     <label for="pwd">新设密码</label>
28                     <input type="password" class="form-control" id="new_password" placeholder="New_Password">
29                 </div>
30                 <input type="button" value="submit" class="btn btn-primary pull-right change_btn">
31                 <span class="error"> </span>
32             </form>
33         </div>
34     </div>
35 </div>
36 
37 <script>
38     $('.change_btn').click(function () {
39 
40         $.ajax({
41             url: '',
42             type: 'post',
43             data: {
44                 "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val(),
45                 'old_pwd': $('#old_password').val(),
46                 'new_pwd': $('#new_password').val()
47             },
48             success:function (data) {
49                 var change_response=JSON.parse(data);
50                 console.log(change_response);
51                 console.log(change_response.flag);
52                 if (change_response.flag){  // 修改密码成功
53                     location.href = '/index/'
54                 }
55                 else{       // 修改密码失败
56                     $('.error').html(change_response.error_msg).css("color","red");
57                     setTimeout(function () {
58                         $('.error').html('')
59                     },1000)
60                 }
61             }
62         })
63     });
64 </script>
65 </body>
66 </html>
change_pwd

 blog

 1  <div class="left_region">
 2     <div class="panel panel-info">
 3         <!-- Default panel contents -->
 4         <div class="panel-heading">我的分类</div>
 5         <div class="panel-body">
 6             <p>
 7                 {% for category in cate_list %}
 8                     <p><a href="/blog/{{ username }}/cate/{{ category.0 }}">{{ category.0 }}({{ category.1 }})</a></p>
 9                 {% endfor %}
10             </p>
11         </div>
12     </div>
13     <div class="panel panel-success">
14         <!-- Default panel contents -->
15         <div class="panel-heading">标签</div>
16         <div class="panel-body">
17             <p>
18                 {% for tag in tag_list %}
19                     <p><a href="/blog/{{ username }}/tag/{{ tag.0 }}">{{ tag.0 }}({{ tag.1 }})</a></p>
20                 {% endfor %}
21 
22             </p>
23         </div>
24     </div>
25     <div class="panel panel-danger">
26         <!-- Default panel contents -->
27         <div class="panel-heading">日期归档</div>
28         <div class="panel-body">
29             {% for date in date_list %}
30                 <p><a href="/blog/{{ username }}/date/{{ date.0 }}">{{ date.0 }}({{ date.1 }})</a></p>
31             {% endfor %}
32 
33         </div>
34     </div>
35 </div>
blog/archive
 1 {% load my_tags %}
 2 <!DOCTYPE html>
 3 <html lang="en">
 4 <head>
 5     <meta charset="UTF-8">
 6     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 7     <meta name="viewport" content="width=device-width, initial-scale=1">
 8     <link rel="stylesheet" href="/static/bs/css/bootstrap.css">
 9     <link rel="stylesheet" href="/static/css/article_detail.css">
10     <script src="/static/js/jquery-3.2.1.min.js"></script>
11     <script src="/static/bs/js/bootstrap.js"></script>
12     <!--引入访问用户的博客样式-->
13     <link rel="stylesheet" href="/static/css/theme/{{ username }}.css">
14     <title>Title</title>
15     <style>
16         * {
17             margin: 0;
18             padding: 0;
19         }
20 
21         body {
22             margin-bottom: 50px;
23         }
24 
25         .header p.title {
26             color: #ffffff;
27             font-family: 微软雅黑, 华文细黑, 黑体, Arial;
28             font-size: 24px;
29             float: left;
30             margin-left: 15px;
31         }
32 
33         .action {
34             float: right;
35             margin-right: 40px;
36         }
37 
38         .action a {
39             padding: 5px 8px;
40             color: white;
41             background-color: #5ab2ce;
42             font-size: 12px;
43             text-decoration: none;
44             margin-left: 5px;
45         }
46 
47 
48     </style>
49 </head>
50 <body>
51 <div class="header">
52     <p class="title"><a href="/index/">{{ username }}</a></p>
53     <div class="action">
54         <a href="/index/">首页</a>
55         <a href="">文章</a>
56         <a href="">随笔</a>
57         <a href="/blog/{{ request.user.username }}/backend">管理</a>
58     </div>
59 </div>
60 
61 <div class="container">
62     <div class="row">
63         <div class="col-md-3">
64             {% get_archive_style username %}
65         </div>
66         <div class="col-md-8">
67             {% block content %}
68                 <div class="articles_region">
69                     <div class="article_list">
70                         {% for article_obj in article_list %}
71                             <div class="article_item">
72                                 <h4>
73                                     <a href="/blog/{{ username }}/articles/{{ article_obj.pk }}.html">{{ article_obj.title }}</a>
74                                 </h4>
75                                 <div class="row">
76                                     <div class="desc">
77                                         <p>{{ article_obj.desc }}</p>
78                                     </div>
79                                 </div>
80                                 <div class="small pull-right">
81                                     <a href="">{{ article_obj.user.username }}</a>
82                                     <span>发布于</span>
83                                     <span>{{ article_obj.create_time|date:'Y-m-d H:i' }}</span>&nbsp;&nbsp;
84                                     <span class="glyphicon glyphicon-comment"></span>评论({{ article_obj.comment_count }})&nbsp;&nbsp;
85                                     <span class="glyphicon glyphicon-thumbs-up"></span>点赞({{ article_obj.up_count }})
86                                 </div>
87                                 <hr>
88                             </div>
89                         {% endfor %}
90                     </div>
91                 </div>
92             {% endblock %}
93         </div>
94 
95     </div>
96 </div>
97 
98 </body>
99 </html>
blog/home_base
1 {% extends "blog/home_base.html" %}
blog/home_site
  1 <!--引入font-awesome图标-->
  2 <link rel="stylesheet" href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.css">
  3 
  4 {% extends "blog/home_base.html" %}
  5 
  6 {% block content %}
  7     <div class="article_info">
  8         <h4 class="text-center"><a>{{ article_obj.title }}</a></h4>
  9         {{ article_obj.articledetail.content|safe }}
 10     </div>
 11 
 12     <div id="green_channel">
 13         <a>好文要顶</a>
 14         <a>关注我</a>
 15         <a>收藏该文</a>
 16         <a>
 17             <i class="fa fa-weibo"></i>
 18         </a>
 19         <a>
 20             <i class="fa fa-weixin"></i>
 21         </a>
 22     </div>
 23     <!--点赞功能-->
 24     <div id="div_digg">
 25         <div class="diggit digg">
 26             <span class="diggnum" id="digg_count">{{ article_obj.up_count }}</span>
 27         </div>
 28         <div class="buryit digg">
 29             <span class="burynum" id="bury_count">{{ article_obj.down_count }}</span>
 30         </div>
 31         <div class="diggword" id="digg_tips"></div>
 32     </div>
 33 
 34     <p>&nbsp;&nbsp;</p>
 35     <p>&nbsp;&nbsp;</p>
 36     <p>&nbsp;&nbsp;</p>
 37     <!--评论树功能-->
 38     <p class="show_tree">评论树:</p>
 39     <div class="comment_tree">
 40     </div>
 41 
 42 
 43     <hr>
 44     <!--评论楼功能-->
 45     <div class="comment_show">
 46         <p>评论楼:</p>
 47         <ul class="comment_list list-group">
 48             {% for comment in comment_list %}
 49                 <li class="comment_item list-group-item">
 50                     <!--评论内容顶部-->
 51                     <div class="row">
 52                         <div style="margin-left:20px;">
 53                             <a>#{{ forloop.counter }}楼</a>
 54                             <span>{{ comment.create_time|date:'Y-m-d H:i' }}</span>
 55                             <span>{{ comment.user.username }}</span>
 56                             <div class="pull-right">
 57                                 <a class="reply_btn" comment_id="{{ comment.pk }}"
 58                                    comment_user="{{ comment.user.username }}">回复</a>
 59                             </div>
 60                         </div>
 61                     </div>
 62                     <!--若为子评论时显示的内容-->
 63                     {% if comment.parent_comment_id %}
 64                         <div class="row">
 65                             <div class="parent_comment_info col-md-offset-1 well">
 66                                 <a href="">@{{ comment.parent_comment.user.username }}</a>
 67                                 <span>{{ comment.parent_comment.content }}</span>
 68                             </div>
 69                         </div>
 70                     {% endif %}
 71 
 72                     <!--评论内容-->
 73                     <div class="row">
 74                         <div class="col-md-offset-1">
 75                             <p>{{ comment.content }}</p>
 76                         </div>
 77                     </div>
 78                 </li>
 79             {% endfor %}
 80         </ul>
 81     </div>
 82 
 83     <!--评论框-->
 84     <div class="comment">
 85         <p>
 86             昵称:<input type="text" id="tbCommentAuthor" class="author" disabled size="50"
 87                       value="{{ request.user.username }}">
 88         </p>
 89         <label for="">评论内容:</label>
 90         <p>
 91             <textarea name="" id="comment_area" cols="60" rows="10"></textarea>
 92         </p>
 93         <input type="button" class="btn btn-default" value="提交" id="comment_submit_btn">
 94     </div>
 95     <div class="login_user_info" username="{{ request.user.usernaame }}"></div>
 96 
 97 
 98 
 99 
100     {% csrf_token %}
101     <script>
102         // 绑定提交点赞事件
103         $(".digg").click(function () {
104             if ("{{ request.user.username }}") {
105                 var is_up = $(this).hasClass("diggit");
106                 $.ajax({
107                     url: "/blog/digg/",
108                     type: "post",
109                     data: {
110                         article_id:{{ article_obj.pk }},
111                         csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
112                         is_up: is_up
113                     },
114                     success: function (data) {
115                         var error_info;
116                         if (data.state) {
117                             if (is_up) {
118                                 var val = parseInt($("#digg_count").text()) + 1;
119                                 $("#digg_count").text(val);
120                             }
121                             else {
122                                 var val = parseInt($("#bury_count").text()) + 1;
123                                 $("#bury_count").text(val);
124                             }
125                         }
126                         else {
127                             if (data.first_updown) {
128                                 error_info = "已经点赞过"
129                             } else {
130                                 error_info = "已经反对过"
131                             }
132                             $("#digg_tips").html(error_info).css('color', "red");
133                             setTimeout(function () {
134                                 $("#digg_tips").html("")
135                             }, 1000)
136                         }
137                     }
138                 })
139             } else {
140                 alert("请登录")
141             }
142         });
143 
144         // 基于ajax绑定 提交评论 事件
145         $("#comment_submit_btn").click(function () {
146             // parent_comment_pk 区分 根评论和子评论
147             var content = $("#comment_area").val();
148 
149             if (parent_comment_pk) {
150                 var index = content.indexOf("\n");
151                 content = content.slice(index + 1);
152             } else {
153                 content = $("#comment_area").val();
154             }
155             // 清空输入框的内容
156             $("#comment_area").val("");
157 
158             $.ajax({
159                 url: "/blog/comment/",
160                 type: "post",
161                 data: {
162                     content: content,
163                     article_id: "{{ article_obj.pk }}",
164                     csrfmiddlewaretoken: $("[name='csrfmiddlewaretoken']").val(),
165                     pid: parent_comment_pk
166                 },
167                 success: function (data) {
168                     // Ajax生成评论内容并显示
169                     var data = JSON.parse(data);
170 
171                     var floor_count = $(".comment_list .comment_item").length + 1;
172                     var create_time = data.create_time;
173                     var username = $(".login_user_info").attr("username");
174                     var content = data.content;
175 
176 
177                     s = '<li class="comment_item list-group-item"><div class="row"> <div class="col-md-offset-1"> <a href="">#' + floor_count + '楼</a>&nbsp;&nbsp;<span>' + create_time + '</span>&nbsp;&nbsp;<span>' + username + '</span> <div class="pull-right"></div></div></div> <div class="row"> <div class="col-md-offset-1"> <p>' + content + '</p> </div> </div> </li>';
178                     $(".comment_list").append(s)
179                 }
180             })
181         });
182 
183 
184         // 绑定回复事件
185         var parent_comment_pk = "";
186         $(".comment_item .reply_btn").click(function () {
187             // 获取焦点
188             $("#comment_area").focus();
189             // 设置:@用户名
190             var val = "@" + $(this).attr("comment_user") + "\n";
191             $("#comment_area").val(val);
192             // 获取回复评论的主键值 以便插入数据库
193             parent_comment_pk = $(this).attr("comment_id")
194         });
195 
196         // 评论树功能请求comment_list
197         $(".show_tree").click(function () {
198             $.ajax({
199                 url: "/blog/get_comment_tree/" +{{ article_obj.pk }},
200                 success: function (data) {
201                     var comment_list = data;
202                     var comment_html = "";
203                     $.each(comment_list, function (index, comment) {
204                         var nid = comment.nid;
205                         var content = comment.content;
206                         var pid = comment.parent_comment_id;
207                         var username = comment.user__username;
208 
209                         comment_html = '<div class="comment_item"><span>' + username + '</span>:&nbsp;&nbsp;<span class="content" tree_comment_id=' + nid + '>' + content + '</span></div>';
210                         if (pid) {
211                             $("[tree_comment_id=" + pid + "]").parent().append(comment_html);
212                         }
213                         else {
214                             $(".comment_tree").append(comment_html);
215                         }
216                     })
217                 }
218             })
219         })
220     </script>
221 
222 {% endblock %}
!!! blog/article_detail
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 6     <meta name="viewport" content="width=device-width, initial-scale=1">
 7     <link rel="stylesheet" href="/static/bs/css/bootstrap.css">
 8     <link rel="stylesheet" href="/static/css/backend_index.css">
 9     <title>后台管理</title>
10 </head>
11 
12 <body>
13 <div class="header">
14     <div class="title">{{ username }}</div>
15 </div>
16 
17 <div class="container-fluid">
18 
19     <div class="row">
20         <!--管理页面左侧-->
21         <div class="col-md-3">
22             <ul class="list-group">
23                 <li class="list-group-item">
24                     <a href="/blog/{{ request.user.username }}/backend_add_article">添加文章</a>
25                 </li>
26                 <li class="list-group-item">分类管理</li>
27                 <li class="list-group-item">标签操作</li>
28             </ul>
29         </div>
30         <!--管理页面主体-->
31         <div class="col-md-9">
32             <div class="con">
33                 <table class="table table-strippen table-hover">
34                     <thead>
35                     <tr>
36                         <th>文章标题</th>
37                         <th>操作</th>
38                         <th>操作</th>
39                     </tr>
40                     </thead>
41                     <tbody>
42                     {% for article in article_list %}
43                         <tr>
44                             <td>{{ article.title }}</td>
45                             <td><a href="">编辑</a></td>
46                             <td><a href="">删除</a></td>
47                         </tr>
48                     {% endfor %}
49                     </tbody>
50                 </table>
51             </div>
52         </div>
53     </div>
54 </div>
55 
56 </body>
57 </html>
blog/backend_index
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 6     <meta name="viewport" content="width=device-width, initial-scale=1">
 7     <link rel="stylesheet" href="/static/bs/css/bootstrap.css">
 8     <link rel="stylesheet" href="/static/css/backend_index.css">
 9     <title>后台管理</title>
10 </head>
11 
12 <body>
13 <div class="header">
14     <div class="title">{{ username }}</div>
15 </div>
16 
17 <div class="container-fluid">
18 
19     <div class="row">
20         <!--管理页面左侧-->
21         <div class="col-md-3">
22             <ul class="list-group">
23                 <li class="list-group-item">
24                     <a href="/blog/{{ request.user.username }}/backend_add_article">添加文章</a>
25                 </li>
26                 <li class="list-group-item">分类管理</li>
27                 <li class="list-group-item">标签操作</li>
28             </ul>
29         </div>
30         <!--管理页面主体-->
31         <div class="col-md-9">
32             <div class="con">
33                 <table class="table table-strippen table-hover">
34                     <thead>
35                     <tr>
36                         <th>文章标题</th>
37                         <th>操作</th>
38                         <th>操作</th>
39                     </tr>
40                     </thead>
41                     <tbody>
42                     {% for article in article_list %}
43                         <tr>
44                             <td>{{ article.title }}</td>
45                             <td><a href="">编辑</a></td>
46                             <td><a href="">删除</a></td>
47                         </tr>
48                     {% endfor %}
49                     </tbody>
50                 </table>
51             </div>
52         </div>
53     </div>
54 </div>
55 
56 </body>
57 </html>
blog/backend_add_article
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 6     <meta name="viewport" content="width=device-width, initial-scale=1">
 7     <title>Title</title>
 8 </head>
 9 <body>
10 
11 <p><b>404.</b> 抱歉! 您访问的资源不存在!</p>
12 <p class="d">请确认您输入的网址是否正确,如果问题持续存在,请发邮件至contact@cnblogs.com与我们联系。</p>
13 <p><a href="/">返回网站首页</a></p>
14 
15 </body>
16 </html>
blog/not_found

转载于:https://www.cnblogs.com/iyouyue/p/8511009.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值