• module-07-2 简单BBS


    需求


    项目:开发一个简单的BBS论坛

    需求:

    1、整体参考“抽屉新热榜” + “虎嗅网”

    2、实现不同论坛版块

    3、帖子列表展示

    4、帖子评论数、点赞数展示

    5、在线用户展示

    6、允许登录用户发贴、评论、点赞

    7、允许上传文件

    8、帖子可被置顶

    9、可进行多级评论

    code


     1 #! /usr/bin/env python3
     2 #  -*- coding:utf-8 -*-
     3 
     4 from django.template import Library
     5 from django.utils.safestring import mark_safe
     6 
     7 register = Library()
     8 
     9 
    10 @register.simple_tag
    11 def searchCondition(arg_dict, k):
    12     if k == 'article_type':
    13         if arg_dict['article_type'] == 0:
    14             res = '<a class="active_condition" href="/backend/article-0-%s.html">全部</a>' % arg_dict['category_id']
    15         else:
    16             res = '<a href="/backend/article-0-%s.html">全部</a>' % arg_dict.category_id
    17         return mark_safe(res)
    18     else:
    19         if arg_dict['category_id'] == 0:
    20             res = '<a class="active_condition" href="/backend/article-%s-0.html">全部</a>' % arg_dict['article_type']
    21         else:
    22             res = '<a href="/backend/article-%s-0.html">全部</a>' % arg_dict['article_type']
    23         return mark_safe(res)
    24 
    25 
    26 @register.simple_tag
    27 def searchCondition2(arg_dict,category_list):
    28     res_list = []
    29     for c in category_list:
    30         if arg_dict['category_id'] == c.nid:
    31             res_list.append('<a class="active_condition" href="/backend/article-%s-%s.html">%s</a>' % (
    32             arg_dict['article_type'], c.nid, c.title))
    33         else:
    34             res_list.append('<a href="/backend/article-%s-%s.html">%s</a>' % (arg_dict['article_type'], c.nid, c.title))
    35 
    36     return mark_safe(' '.join(res_list))
    37 
    38 
    39 @register.simple_tag
    40 def searchCondition3(arg_dict,article_type_list):
    41     res_list = []
    42     for t in article_type_list:
    43         if arg_dict['article_type'] == t[0]:
    44             temp = '<a class ="active_condition" href="/backend/article-%s-%s.html">%s</a>'%(t[0],arg_dict['category_id'],t[1])
    45         else:
    46             temp = '<a href="/backend/article-%s-%s.html">%s</a>'%(t[0],arg_dict['category_id'],t[1])
    47         res_list.append(temp)
    48 
    49     return mark_safe(' '.join(res_list))
    backend/templatetags/search.py
      1 #!/usr/bin/env python
      2 # -*- coding:utf-8 -*-
      3 from django.shortcuts import render,redirect,HttpResponse
      4 from django.db import transaction
      5 from repository import models
      6 from backend import forms
      7 from utils.custom_json_encoder import CustomJsonEncoder
      8 import json,os,time
      9 
     10 
     11 def auth(func):
     12     '''
     13     用户验证装饰器 | 或写成2个函数,由对应的view启用对应的装饰器或许更好?
     14     :param func:
     15     :return:
     16     '''
     17     def wrapper(request,*args,**kwargs):
     18         # print(request.path_info)
     19         if request.path_info == '/backend/base-info.html':
     20             if request.session.get('username',None):
     21                 return func(request,*args,**kwargs)
     22             else:
     23                 return redirect('/login.html')
     24         else:
     25             if request.session.get('username',None) and request.session.get('blog_nid',None):
     26                 return func(request,*args,**kwargs)
     27             elif request.session.get('username',None) and not request.session.get('blog_nid',None):
     28                 return render(request,'backend_return_to_base_info.html')
     29             else:
     30                 return redirect('/login.html')
     31 
     32     return wrapper
     33 
     34 
     35 @auth
     36 def base_info(request):
     37     """
     38     博主个人信息
     39     :param request:
     40     :return:
     41     """
     42     if request.method == 'GET':
     43         user = models.UserInfo.objects.filter(username=request.session['username']).select_related('blog').first()
     44         # cur_user = request.session['cur_user']
     45         return render(request, 'backend_base_info.html',{'user':user})
     46 
     47     elif request.method == 'POST':
     48         # print(request.POST)
     49         data = {}
     50         for k,v in request.POST.items():
     51             data[k] = v.strip()
     52 
     53         data['username'] = request.session['username']
     54 
     55         bf = forms.BlogForm(data)
     56         res = {'status':True,'error':None,'data':None}
     57         if bf.is_valid():
     58             userS = models.UserInfo.objects.filter(username=request.session['username'])
     59             if bf.cleaned_data['nickname']:
     60                 userS.update(nickname=bf.cleaned_data['nickname'])
     61 
     62             blog_obj,is_created = models.Blog.objects.update_or_create(
     63                 user=userS.first(),
     64                 defaults={
     65                     'site':request.POST['site'],
     66                     'theme':request.POST['theme'],
     67                     'title':request.POST['title'],
     68                 }
     69             )
     70             # 对于新注册的博客,将blog的id保存入session
     71             if is_created:
     72                 request.session['blog_nid'] = blog_obj.nid
     73         else:
     74             res['status'] = False
     75             res['error'] = bf.errors.as_data()
     76         return HttpResponse(json.dumps(res,cls=CustomJsonEncoder))
     77 
     78     else:
     79         return redirect('/')
     80 
     81 
     82 @auth
     83 def uploadAvatar(request):
     84     '''
     85     上传头像
     86     :param request:
     87     :return:
     88     '''
     89     if request.method == 'POST':
     90         file = request.FILES.get('avatar',None)
     91         res = {'status':True,'data':None}
     92         file_path = os.path.join('static/imgs/avatar',file.name)
     93         with open( file_path,'wb' ) as f:
     94             for line in file:
     95                 f.write(line)
     96 
     97         res['data'] = '/' + file_path
     98         models.UserInfo.objects.filter(username = request.session['username']).update(avatar=res['data'])
     99 
    100         return HttpResponse(json.dumps(res))
    101     else:
    102         return redirect('/')
    103 
    104 
    105 @auth
    106 def tag(request):
    107     """
    108     博主个人标签管理
    109     :param request:
    110     :return:
    111     """
    112     # cur_blog = models.Blog.objects.filter(user__username=request.session['username']).first()
    113     cur_blog = models.Blog.objects.filter(nid=request.session['blog_nid']).first()
    114     if request.method == 'GET':
    115         tags = models.Tag.objects.filter(blog=cur_blog)
    116         return render(request,'backend_tag.html',{'tags':tags})
    117     elif request.method == 'POST':
    118         res = {'status':True,'error':None,'data':None}
    119         data = {}
    120         for k,v in request.POST.items():
    121             data[k]=v
    122         data['blog_nid'] = cur_blog.nid #;print(data)
    123         tf = forms.TagForm(data)
    124         if tf.is_valid():
    125             models.Tag.objects.create(title=tf.cleaned_data['title'],
    126                                       blog=cur_blog)
    127         else:
    128             res['status'] = False
    129             res['error'] = tf.errors.as_data()
    130         return HttpResponse(json.dumps(res,cls=CustomJsonEncoder))
    131     else:
    132         return redirect('/')
    133 
    134 
    135 @auth
    136 def del_tag(request):
    137     '''
    138     删除标签
    139     :param request:
    140     :return:
    141     '''
    142     if request.method == 'POST':
    143         res = {'status':True,'error':None,'data':None}
    144         try:
    145             nid = request.POST.get('nid',None)
    146             models.Tag.objects.filter(nid=nid).delete()
    147         except Exception as e:
    148             res['status'] = False
    149             res['error'] = str(e)
    150         return HttpResponse(json.dumps(res))
    151     else:
    152         return redirect('/')
    153 
    154 @auth
    155 def edit_tag(request):
    156     '''
    157     编辑标签名称
    158     :param request:
    159     :return:
    160     '''
    161     if request.method == 'POST':
    162         res = {'status':True,'error':None,'data':None}
    163         tf = forms.TagForm2(request.POST)
    164         if tf.is_valid():
    165             models.Tag.objects.filter(nid=tf.cleaned_data['nid']).update(title=tf.cleaned_data['title'])
    166         else:
    167             res['status'] = False
    168             res['error'] = tf.errors.as_data()
    169         return HttpResponse(json.dumps(res,cls=CustomJsonEncoder))
    170     else:
    171         return redirect('/')
    172 
    173 
    174 @auth
    175 def category(request):
    176     """
    177     博主个人分类管理
    178     :param request:
    179     :return:
    180     """
    181     # cur_blog = models.Blog.objects.filter(user__username=request.session['username']).first()
    182     cur_blog = models.Blog.objects.filter(nid=request.session['blog_nid']).first()
    183     if request.method == 'GET':
    184 
    185         categories = models.Category.objects.filter(blog=cur_blog)
    186         # request.session['blog_title'] = cur_blog.title
    187         # cur_categories = request.session['cur_categories']
    188         return render(request, 'backend_category.html',{'cs':categories})
    189     elif request.method == 'POST':
    190         res = {'status':True,'error':None,'data':None}
    191         # 添加验证项
    192         data = {}
    193         for k,v in request.POST.items():
    194             data[k] = v
    195         data['blog_nid'] = cur_blog.nid # ;print(blog.nid)
    196         # 验证
    197         cf = forms.CategoryForm(data)
    198         if cf.is_valid():
    199             models.Category.objects.create(title=cf.cleaned_data['title'],blog=cur_blog)
    200         else:
    201             res['status'] = False
    202             res['error'] = cf.errors.as_data()
    203         return HttpResponse(json.dumps(res,cls=CustomJsonEncoder))
    204     else:
    205         return redirect('/')
    206 
    207 
    208 @auth
    209 def del_ctgy(request):
    210     '''
    211     删除文章分类
    212     :param request:
    213     :return:
    214     '''
    215     if request.method == 'POST':
    216         res = {'status':True,'error':None,'data':None}
    217         try:
    218             nid = request.POST.get('nid',None)
    219             models.Category.objects.filter(nid=nid).delete()
    220         except Exception as e:
    221             res['status'] = False
    222             res['error'] = str(e)
    223         return HttpResponse(json.dumps(res))
    224     else:
    225         return redirect('/')
    226 
    227 
    228 @auth
    229 def edit_ctgy(request):
    230     '''
    231     编辑文章分类
    232     :param request:
    233     :return:
    234     '''
    235     if request.method == 'POST':
    236         res = {'status':True,'error':None,'data':None}
    237         cf = forms.CategoryForm2(request.POST)
    238         if cf.is_valid():
    239             nid = request.POST.get('nid',None) # ;print(nid)
    240             title = request.POST.get('title',None)
    241             models.Category.objects.filter(nid=nid).update(title=title)
    242         else:
    243             res['status'] = False
    244             res['error'] = cf.errors.as_data()
    245         return HttpResponse(json.dumps(res,cls=CustomJsonEncoder))
    246     else:
    247         return redirect('/')
    248 
    249 
    250 @auth
    251 def article(request,*args,**kwargs):
    252     """
    253     博主个人文章管理
    254     :param request:
    255     :return:
    256     """
    257     cur_blog = models.Blog.objects.filter(nid=request.session['blog_nid']).first()  # ;print(cur_blog.nid)
    258     if request.method == 'GET':
    259         condition = {}
    260         for k,v in kwargs.items():
    261             kwargs[k] = int(v)
    262             if v != '0':
    263                 condition[k] = v
    264 
    265         articles =  models.Article.objects.filter(blog_id=cur_blog.nid,**condition)  # ;print(articles);print(condition)
    266         category_list = models.Category.objects.all()
    267         article_type_list = models.Article.type_choices
    268         return render(request, 'backend_article.html',{'articles':articles,'category_list':category_list,'arg_dict':kwargs,'article_type_list':article_type_list})
    269     elif request.method == 'POST':
    270         pass
    271     else:
    272         return redirect('/')
    273 
    274 
    275 @auth
    276 def add_article(request):
    277     """
    278     添加文章
    279     :param request:
    280     :return:
    281     """
    282     cur_blog = models.Blog.objects.filter(nid=request.session['blog_nid']).first()
    283     if request.method == 'GET':
    284         categories = models.Category.objects.filter(blog=cur_blog)
    285         tags = models.Tag.objects.filter(blog=cur_blog)
    286         return render(request,'backend_add_article.html',{'categories':categories,'tags':tags,'blog_nid':cur_blog.nid})
    287     elif request.method == 'POST':
    288         res={'status':True,'error':None,'data':None}
    289         # data = {}
    290         # for k in request.POST.keys():
    291         #     if k == 'tag':
    292         #         data[k] = request.POST.getlist(k,None)
    293         #     else:
    294         #         data[k] = request.POST.get(k,None)
    295         # # data['blog_nid'] = request.session['blog_nid']
    296 
    297         # 验证
    298         # af = forms.ArticleForm(data);print(af.__dict__)
    299         af = forms.ArticleForm(request.POST) # ;print(af.__dict__)
    300         if af.is_valid():
    301             with transaction.atomic():
    302                 # 创建Article表数据
    303                 obj = models.Article.objects.create(
    304                     blog_id = af.cleaned_data['blog_nid'],
    305                     title = af.cleaned_data['title'],
    306                     summary = af.cleaned_data['summary'],
    307                     article_type = af.cleaned_data['article_type'],
    308                     category_id = af.cleaned_data['category'],
    309                 )
    310                 # 创建Article表与Tag表的多对多关系
    311                 tag_list = []
    312                 for tag_id in af.cleaned_data['tags']:
    313                     tag_list.append(models.Article2Tag(article_id = obj.nid,tag_id = tag_id))
    314 
    315                 models.Article2Tag.objects.bulk_create(tag_list)
    316 
    317 
    318                 # 创建ArticleDetail表数据
    319                 models.ArticleDetail.objects.create(
    320                     content = af.cleaned_data['content'],
    321                     article = obj
    322                 )
    323         else:
    324             res['status'] = False
    325             res['error'] = af.errors.as_data()
    326         return HttpResponse(json.dumps(res,cls=CustomJsonEncoder))
    327     else:
    328         return redirect('/')
    329 
    330 
    331 @auth
    332 def edit_article(request,nid):
    333     """
    334     编辑文章
    335     :param request:
    336     :return:
    337     """
    338     cur_blog = models.Blog.objects.filter(nid=request.session['blog_nid']).first()
    339     cur_article = models.Article.objects.filter(nid=nid).select_related('category','articledetail').first() # ;print(cur_article.tags.all())
    340     if request.method == 'GET':
    341         categories = models.Category.objects.filter(blog=cur_blog)
    342         tags = models.Tag.objects.filter(blog=cur_blog)
    343         return render(request, 'backend_edit_article.html',{'article':cur_article,'categories':categories,'tags':tags,'blog_nid':cur_blog.nid})
    344     elif request.method == 'POST':
    345         res = {'status':True,'error':None,'data':None}
    346         af = forms.ArticleForm(request.POST) # ;print(request.POST)
    347         if af.is_valid():
    348             cur_article.title = af.cleaned_data['title']
    349             cur_article.summary = af.cleaned_data['summary']
    350             cur_article.articledetail.content = af.cleaned_data['content']
    351             cur_article.article_type = af.cleaned_data['article_type']
    352             cur_article.category_id = af.cleaned_data['category']
    353             cur_article.save()
    354 
    355             with transaction.atomic():
    356                 # 重设Article表 与 tag 表的多对多关系
    357                 models.Article2Tag.objects.filter(article=cur_article).delete()
    358                 for tid in af.cleaned_data['tags']:
    359                     models.Article2Tag.objects.create(
    360                         article=cur_article,
    361                         tag_id=tid
    362                     )
    363 
    364                 # 修改文章内容
    365                 models.ArticleDetail.objects.filter(article_id = nid).update(content = af.cleaned_data['content'],)
    366 
    367         else:
    368             res['status'] = False
    369             res['error'] = af.errors.as_data()
    370         return HttpResponse(json.dumps(res,cls=CustomJsonEncoder))
    371     else:
    372         return redirect('/')
    373 
    374 
    375 
    376 @auth
    377 def del_article(request):
    378     '''
    379     删除文章
    380     :param request:
    381     :return:
    382     '''
    383     if request.method == 'POST':
    384         res = {'status':True,'error':None,'data':None}
    385         try:
    386             a_id = request.POST.get('article_id',None)
    387             models.Article.objects.filter(nid=a_id).delete()
    388         except Exception as e:
    389             res['status'] = True
    390             res['error'] = str(e)
    391         return HttpResponse(json.dumps(res,cls=CustomJsonEncoder))
    392     else:
    393         return redirect('/')
    394 
    395 @auth
    396 def keUploadFile(request):
    397     '''
    398     KindEditor 上传文件API
    399     :param request:
    400     :return:
    401     '''
    402     if request.method == 'POST':
    403         res = {'error':0,'url':None,'message':None}
    404         file_type = request.GET.get('dir', None)
    405         if file_type == 'image' or file_type == 'flash' or file_type == 'file':  # 暂时不考虑 flash 和 file 的情况
    406             uf = request.FILES.get('imgFile',None)
    407             save_path = os.path.join('static/imgs',uf.name)
    408             with open(save_path,'wb') as f:
    409                 for line in uf:
    410                     f.write(line)
    411             res['url'] = save_path
    412         else:
    413             res['error'] = 1
    414             res['message'] = '上传类型不存在'
    415         return HttpResponse(json.dumps(res))
    416     else:
    417         return redirect('/')
    418 
    419 
    420 
    421 @auth
    422 def keFileManager(request):
    423     '''
    424     KindEditor 文件管理API
    425     :param request:
    426     :return:
    427     '''
    428 
    429     dic = {}
    430     root_path = r'E:学习Python_Practice51cto第七模块EdmureBlogstatic/'
    431     static_root_path = '/static/'
    432     request_path = request.GET.get('path')
    433     if request_path:
    434         abs_current_dir_path = os.path.join(root_path, request_path)
    435         move_up_dir_path = os.path.dirname(request_path.rstrip('/'))
    436         dic['moveup_dir_path'] = move_up_dir_path + '/' if move_up_dir_path else move_up_dir_path
    437 
    438     else:
    439         abs_current_dir_path = root_path
    440         dic['moveup_dir_path'] = ''
    441 
    442     dic['current_dir_path'] = request_path
    443     dic['current_url'] = os.path.join(static_root_path, request_path)
    444 
    445     file_list = []
    446     for item in os.listdir(abs_current_dir_path):
    447         abs_item_path = os.path.join(abs_current_dir_path, item)
    448         a, exts = os.path.splitext(item)
    449         is_dir = os.path.isdir(abs_item_path)
    450         if is_dir:
    451             temp = {
    452                 'is_dir': True,
    453                 'has_file': True,
    454                 'filesize': 0,
    455                 'dir_path': '',
    456                 'is_photo': False,
    457                 'filetype': '',
    458                 'filename': item,
    459                 'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
    460             }
    461         else:
    462             temp = {
    463                 'is_dir': False,
    464                 'has_file': False,
    465                 'filesize': os.stat(abs_item_path).st_size,
    466                 'dir_path': '',
    467                 'is_photo': True if exts.lower() in ['.jpg', '.png', '.jpeg'] else False,
    468                 'filetype': exts.lower().strip('.'),
    469                 'filename': item,
    470                 'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
    471             }
    472 
    473         file_list.append(temp)
    474     dic['file_list'] = file_list
    475     return HttpResponse(json.dumps(dic))
    backend/views/user.py
      1 #! /usr/bin/env python3
      2 # -*- coding:utf-8 -*-
      3 # Author:Jailly
      4 
      5 from django.forms import Form
      6 from django.forms import fields
      7 from django.forms import widgets
      8 from repository import models
      9 from django.core.validators import ValidationError
     10 from django.db.models import Q
     11 from django.forms.models import ModelChoiceField
     12 
     13 class BlogForm(Form):
     14     username = fields.CharField()
     15     nickname = fields.CharField(max_length=64,required=False)
     16     site = fields.CharField(max_length=32,
     17                             error_messages={
     18                                 'max_length':'博客地址不能超过32个字符',
     19                                 'required':'请填写博客地址'
     20                             })
     21     theme = fields.ChoiceField(
     22         choices=((1,''),(2,''),(3,''),(4,''),(5,''))
     23     )
     24     title = fields.CharField(max_length=64,required=False,error_messages={'max_length':'内容过长'})
     25 
     26     def clean_site(self):
     27         # print(self.cleaned_data)
     28         if models.Blog.objects.exclude(user__username=self.cleaned_data['username']).filter(site=self.cleaned_data['site']).count():
     29             raise ValidationError('该地址已存在')
     30         else:
     31             return self.cleaned_data['site']
     32 
     33 
     34 class CategoryForm(Form):
     35     blog_nid = fields.CharField()
     36     title = fields.CharField(max_length=32,
     37                              error_messages={
     38                                  'max_length':'分类名称太长',
     39                                  'required':'请填写分类名称',
     40                              })
     41 
     42     def clean_title(self):
     43         if models.Category.objects.filter(blog__nid=self.cleaned_data['blog_nid'],title=self.cleaned_data['title']).count():
     44             raise ValidationError('您已经在使用该分类')
     45         else:
     46             return self.cleaned_data['title']
     47 
     48 
     49 class CategoryForm2(Form):
     50     nid = fields.CharField()
     51     title = fields.CharField(max_length=32,
     52                              error_messages={
     53                                  'max_length':'分类名称太长',
     54                                  'required':'请填写分类名称',
     55                              })
     56 
     57 
     58 
     59 class TagForm(Form):
     60     blog_nid = fields.CharField()
     61     title = fields.CharField(max_length=32,
     62                              error_messages={
     63                                  'max_length': '标签名称太长',
     64                                  'required': '请填写标签名称',
     65                              })
     66 
     67     def clean_title(self):
     68         if models.Tag.objects.filter(blog__nid=self.cleaned_data['blog_nid'],title=self.cleaned_data['title']).count():
     69             raise ValidationError('您已经拥有该标签')
     70         else:
     71             return self.cleaned_data['title']
     72 
     73 
     74 class TagForm2(Form):
     75     nid = fields.CharField()
     76     title = fields.CharField(max_length=32,
     77                              error_messages={
     78                                  'max_length': '标签名称太长',
     79                                  'required': '请填写标签名称',
     80                              })
     81 
     82 class ArticleForm(Form):
     83     blog_nid = fields.CharField()
     84     title = fields.CharField(max_length=128,
     85                              error_messages={
     86                                  'max_length':'文章标题不能超过128个字符',
     87                                  'required':'请填写文章标题'
     88                              })
     89     summary = fields.CharField(max_length=255,
     90                                error_messages={
     91                                    'max_length':'文章简介不能超过255个字符',
     92                                    'required':'请填写文件简介',
     93                                })
     94     content = fields.CharField(error_messages={'required':'请填写内容'})
     95 
     96     article_type = fields.ChoiceField(
     97         choices=((1,'Python'),(2,'Linux'),(3,'OpenStack'),(4,'GoLang'),),
     98         required=False
     99     )
    100 
    101     category = fields.ChoiceField()
    102     
    103     tags = fields.MultipleChoiceField()
    104     
    105     def __init__(self,*args,**kwargs):
    106         super(ArticleForm, self).__init__(*args,**kwargs)
    107         self.fields['category'].choices = models.Category.objects.filter(blog__nid=self.data['blog_nid']).values_list('nid','title')
    108         self.fields['tags'].choices = models.Tag.objects.filter(blog__nid=self.data['blog_nid']).values_list('nid','title')
    109         # print(self.fields['tag'].choices)
    backend/forms.py
     1 from django.conf.urls import url
     2 from django.conf.urls import include
     3 from .views import user
     4 
     5 urlpatterns = [
     6     url(r'^base-info.html$', user.base_info),
     7 
     8     url(r'^tag.html$', user.tag),
     9     url(r'^del_tag.html$',user.del_tag),
    10     url(r'^edit_tag.html$',user.edit_tag),
    11 
    12     url(r'^category.html$', user.category),
    13     url(r'^del_ctgy.html$', user.del_ctgy),
    14     url(r'^edit_ctgy.html$', user.edit_ctgy),
    15 
    16     url(r'^article-(?P<article_type>d+)-(?P<category_id>d+).html$', user.article),
    17     url(r'^add-article.html$', user.add_article),
    18     url(r'^del-article.html$', user.del_article),
    19     url(r'^edit-article-(d+).html$', user.edit_article),
    20 
    21     url(r'^uploadAvatar.html$',user.uploadAvatar),
    22 
    23     url(r'^ke-upload-file.html$',user.keUploadFile),
    24     url(r'^ke-file-manager.html$',user.keFileManager),
    25 ]
    backend/urls.py
     1 """EdmureBlog URL Configuration
     2 
     3 The `urlpatterns` list routes URLs to views. For more information please see:
     4     https://docs.djangoproject.com/en/1.10/topics/http/urls/
     5 Examples:
     6 Function views
     7     1. Add an import:  from my_app import views
     8     2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
     9 Class-based views
    10     1. Add an import:  from other_app.views import Home
    11     2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    12 Including another URLconf
    13     1. Import the include() function: from django.conf.urls import url, include
    14     2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    15 """
    16 from django.conf.urls import url
    17 from django.conf.urls import include
    18 from django.contrib import admin
    19 
    20 urlpatterns = [
    21     url(r'^admin/docs/', include('django.contrib.admindocs.urls')),
    22     url(r'^admin/', admin.site.urls),
    23     url(r'^backend/', include('backend.urls')),
    24     url(r'^', include('web.urls')),
    25 ]
    EdmureBlog/urls.py
      1 from django.db import models
      2 
      3 
      4 class UserInfo(models.Model):
      5     """
      6     用户表
      7     """
      8     nid = models.BigAutoField(primary_key=True)
      9     username = models.CharField(verbose_name='用户名', max_length=32, unique=True)
     10     password = models.CharField(verbose_name='密码', max_length=64)
     11     nickname = models.CharField(verbose_name='昵称', max_length=32,null=True)
     12     email = models.EmailField(verbose_name='邮箱', unique=True)
     13     avatar = models.ImageField(verbose_name='头像',null=True)
     14 
     15     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
     16 
     17     fans = models.ManyToManyField(verbose_name='粉丝们', to='UserInfo', through='UserFans',
     18                                   through_fields=('user', 'follower'))
     19 
     20 
     21 class Blog(models.Model):
     22     """
     23     博客信息
     24     """
     25     nid = models.BigAutoField(primary_key=True)
     26     title = models.CharField(verbose_name='个人博客标题', max_length=64,null=True)
     27     site = models.CharField(verbose_name='个人博客前缀', max_length=32, unique=True)
     28     theme = models.CharField(verbose_name='博客主题', max_length=32)
     29     user = models.OneToOneField(to='UserInfo', to_field='nid',on_delete=models.CASCADE)
     30 
     31 
     32 class UserFans(models.Model):
     33     """
     34     互粉关系表
     35     """
     36     user = models.ForeignKey(verbose_name='博主', to='UserInfo', to_field='nid', related_name='users',on_delete=models.CASCADE)
     37     follower = models.ForeignKey(verbose_name='粉丝', to='UserInfo', to_field='nid', related_name='followers',on_delete=models.CASCADE)
     38 
     39     class Meta:
     40         unique_together = [
     41             ('user', 'follower'),
     42         ]
     43 
     44 
     45 class Category(models.Model):
     46     """
     47     博主个人文章分类表
     48     """
     49     nid = models.AutoField(primary_key=True)
     50     title = models.CharField(verbose_name='分类标题', max_length=32)
     51 
     52     blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid',on_delete=models.CASCADE)
     53 
     54 
     55 class ArticleDetail(models.Model):
     56     """
     57     文章详细表
     58     """
     59     content = models.TextField(verbose_name='文章内容', )
     60 
     61     article = models.OneToOneField(verbose_name='所属文章', to='Article', to_field='nid',on_delete=models.CASCADE)
     62 
     63 
     64 class UpDown(models.Model):
     65     """
     66     文章顶或踩
     67     """
     68     article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid',on_delete=models.CASCADE)
     69     user = models.ForeignKey(verbose_name='赞或踩用户', to='UserInfo', to_field='nid',on_delete=models.CASCADE)
     70     up = models.BooleanField(verbose_name='是否赞')
     71 
     72     class Meta:
     73         unique_together = [
     74             ('article', 'user'),
     75         ]
     76 
     77 
     78 class Comment(models.Model):
     79     """
     80     评论表
     81     """
     82     nid = models.BigAutoField(primary_key=True)
     83     content = models.CharField(verbose_name='评论内容', max_length=255)
     84     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
     85 
     86     # reply = models.ForeignKey(verbose_name='回复评论', to='self', related_name='back', null=True,on_delete=models.CASCADE)
     87     reply = models.ManyToManyField(verbose_name='回复评论', to='self', related_name='back', null=True,symmetrical=False)
     88     article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid',on_delete=models.CASCADE)
     89     user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid',on_delete=models.CASCADE)
     90 
     91 
     92 class Tag(models.Model):
     93     nid = models.AutoField(primary_key=True)
     94     title = models.CharField(verbose_name='标签名称', max_length=32)
     95     blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid',on_delete=models.CASCADE)
     96 
     97 
     98 class Article(models.Model):
     99     nid = models.BigAutoField(primary_key=True)
    100     title = models.CharField(verbose_name='文章标题', max_length=128)
    101     summary = models.CharField(verbose_name='文章简介', max_length=255)
    102     read_count = models.IntegerField(default=0)
    103     comment_count = models.IntegerField(default=0)
    104     up_count = models.IntegerField(default=0)
    105     down_count = models.IntegerField(default=0)
    106     create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    107 
    108     blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid',on_delete=models.CASCADE)
    109     category = models.ForeignKey(verbose_name='文章类型', to='Category', to_field='nid', null=True,on_delete=models.CASCADE)
    110 
    111     type_choices = [
    112         (1, "Python"),
    113         (2, "Linux"),
    114         (3, "OpenStack"),
    115         (4, "GoLang"),
    116     ]
    117 
    118     article_type = models.IntegerField(choices=type_choices, default=None)
    119 
    120     tags = models.ManyToManyField(
    121         to="Tag",
    122         through='Article2Tag',
    123         through_fields=('article', 'tag'),
    124     )
    125 
    126 
    127 class Article2Tag(models.Model):
    128     article = models.ForeignKey(verbose_name='文章', to="Article", to_field='nid',on_delete=models.CASCADE)
    129     tag = models.ForeignKey(verbose_name='标签', to="Tag", to_field='nid',on_delete=models.CASCADE)
    130 
    131     class Meta:
    132         unique_together = [
    133             ('article', 'tag'),
    134         ]
    repository/models.py

    static - 略

    templates - 略

      1 #!/usr/bin/env python
      2 # -*- coding:utf-8 -*-
      3 from io import BytesIO
      4 from django.shortcuts import HttpResponse, redirect, render
      5 from utils.check_code import create_validate_code
      6 from web import forms
      7 import json
      8 from utils.custom_json_encoder import CustomJsonEncoder
      9 from repository import models
     10 
     11 
     12 def check_code(request):
     13     """
     14     验证码
     15     :param request:
     16     :return:
     17     """
     18     stream = BytesIO()
     19     img, code = create_validate_code()
     20     img.save(stream, 'PNG')
     21     request.session['checkCode'] = code
     22     print(code)
     23     return HttpResponse(stream.getvalue())
     24 
     25 
     26 def save_session(request):
     27     '''
     28     注册/登录成功时,保存session
     29     :param request:
     30     :return:
     31     '''
     32     # username = request.POST['username']
     33     # cur_userS = models.UserInfo.objects.filter(username=username)
     34     # cur_user = cur_userS.values('username', 'email', 'avatar','nickname').first()
     35     # request.session['cur_user'] = cur_user
     36     #
     37     # cur_blogS = models.Blog.objects.filter(user__username=username)
     38     # cur_blog = cur_blogS.values('title').first()
     39     # request.session['cur_blog'] = cur_blog if cur_blog else ''  # django的session只能接受可以被json序列化的对象,None不能被序列化
     40     #
     41     # cur_categoriesS = models.Category.objects.filter(blog__title=cur_blogS.first().title)
     42     # cur_categories = cur_categoriesS.values('title')
     43     # request.session['cur_categories'] = cur_categories if cur_categories else ''
     44     #
     45     # cur_tagsS = models.Tag.objects.filter(blog=cur_blogS.first())
     46     # cur_tags = cur_tagsS.values('title')
     47     # request.session['cur_tags'] = cur_tags if cur_tags else ''
     48     #
     49     # cur_articlesS = models.Article.objects.filter(blog=cur_blogS.first())
     50     # cur_articles = cur_articlesS.values('title','summary','read_count','comment_count','up_count','down_count','blog__site','category__title','tags__title')
     51     # request.session['cur_articles'] = cur_articles if cur_articles else ''
     52 
     53     request.session['username'] = request.POST['username']
     54     cur_blog = models.Blog.objects.filter(user__username=request.POST['username'])
     55     request.session['blog_nid'] = cur_blog.first().nid if cur_blog else ''
     56 
     57 
     58 def login(request):
     59     """
     60     登陆
     61     :param request:
     62     :return:
     63     """
     64     if request.method == 'GET':
     65         return render(request, 'login.html')
     66     elif request.method == 'POST':
     67 
     68         lf = forms.LoginForm(request.POST)
     69         res = {'status': True, 'error': None, 'data': None}
     70         if lf.is_valid():
     71             if request.POST['checkCode'].upper() == request.session['checkCode'].upper():
     72                 # 判断是否勾选自动登陆
     73                 if request.POST.get('autoLogin', None):
     74                     request.session.set_expiry(60 * 60 * 24 * 30)
     75                 # 保存session
     76                 save_session(request)
     77             else:
     78                 res['status'] = False # 方法2:重构传入 Form 中的参数,将session中的checkcode传入,由Form来验证。哪种方法更好?
     79                 res['error'] = {'checkCode': ['验证码错误', ]}
     80         else:
     81             res['status'] = False
     82             res['error'] = lf.errors.as_data()
     83             if request.POST['checkCode'].upper() != request.session['checkCode'].upper():
     84                 res['error']['checkCode'] = ['验证码错误', ]
     85 
     86         return HttpResponse(json.dumps(res, cls=CustomJsonEncoder))
     87     else:
     88         return redirect('/')
     89 
     90 
     91 def register(request):
     92     """
     93     注册
     94     :param request:
     95     :return:
     96     """
     97 
     98     if request.method == 'GET':
     99         return render(request, 'register.html')
    100     elif request.method == 'POST':
    101         res = {'status': True, 'error': None, 'data': None}
    102         rf = forms.RegisterForm(request.POST)
    103         # print(request.POST)
    104         if rf.is_valid():
    105             # 判断验证码是否输入正确
    106             if request.session['checkCode'].upper() != request.POST.get('checkCode', None).upper():
    107                 res['status'] = False
    108                 res['error'] = {'checkCode': ['验证码错误', ]}
    109             else:
    110                 request.session['username'] = request.POST.get('username', None)
    111                 # 将注册信息存储入数据库
    112                 username = request.POST.get('username', None)
    113                 password = request.POST.get('password', None)
    114                 email = request.POST.get('email', None)
    115                 models.UserInfo.objects.create(username=username, password=password, email=email)
    116                 save_session(request)
    117 
    118         else:
    119             res['status'] = False
    120             res['error'] = rf.errors.as_data()
    121             # 向ErrorDict中添加验证码项
    122             res['error']['checkCode'] = ['验证码错误', ] if request.session['checkCode'].upper() != request.POST.get(
    123                 'checkCode', None).upper() else ''
    124 
    125         return HttpResponse(json.dumps(res, cls=CustomJsonEncoder))
    126     else:
    127         return redirect('/index.html')
    128 
    129 
    130 def logout(request):
    131     '''
    132     注销
    133     :param request:
    134     :return:
    135     '''
    136     request.session.clear()
    137     return redirect('/')
    138 
    139 # def t(request):
    140 #     if request.method == 'GET':
    141 #         f = forms.LoginForm()
    142 #         return render(request,'t.html',{'f':f})
    143 #
    144 #     elif request.method == 'POST':
    145 #         print(request.POST)
    146 #         f = forms.LoginForm(request.POST)
    147 #         if f.is_valid():
    148 #             print(f.cleaned_data)
    149 #             return HttpResponse(f.cleaned_data)
    150 #         else:
    151 #             print(f.errors)
    152 #             return HttpResponse(f.errors)
    web/views/account.py
      1 #!/usr/bin/env python
      2 # -*- coding:utf-8 -*-
      3 from django.shortcuts import render, redirect, HttpResponse
      4 from repository import models
      5 from web import forms
      6 import json,datetime
      7 from utils.custom_json_encoder import CustomJsonEncoder
      8 from dateutil.relativedelta import relativedelta
      9 from django.db.models import F
     10 from django.db import transaction
     11 from django.utils.safestring import mark_safe
     12 
     13 def index(request):
     14     """
     15     博客首页,展示全部博文
     16     :param request:
     17     :return:
     18     """
     19     article_list = models.Article.objects.all()  # ;print('index')
     20 
     21     if request.session.get('blog_nid',None):
     22         visitor_blog = models.Blog.objects.filter(nid = request.session['blog_nid']).values('site').first()
     23     else:
     24         visitor_blog = None
     25 
     26     return render(request, 'index.html', {'article_list': article_list,'visitor_blog':visitor_blog})
     27 
     28 
     29 def home(request, site):
     30     """
     31     博主个人首页
     32     :param request:
     33     :param site: 博主的网站后缀如:http://xxx.com/wupeiqi.html
     34     :return:
     35     """
     36     if request.method == 'GET':
     37         if request.session.get('username', None):
     38             visitor = models.UserInfo.objects.filter(username=request.session['username']).select_related('blog').first()
     39             visitor_blog = visitor.blog
     40         else:
     41             visitor = ''
     42             visitor_blog = ''
     43 
     44         cur_blog = models.Blog.objects.filter(site=site).select_related('user').first()
     45         cur_user = cur_blog.user
     46         articles = models.Article.objects.filter(blog=cur_blog)
     47 
     48         # d_c 是 由日期(年+月)和文章数组成的元组们,组成的列表
     49         dates = models.Article.objects.filter(blog=cur_blog).dates('create_time','month',order='DESC')
     50         d_c = []
     51         for d in dates:
     52             c = models.Article.objects.filter(create_time__date__gte = d,create_time__date__lte=d+relativedelta(months=1)).count()
     53             d_c.append((d,c))
     54 
     55         return render(request, 'home.html', {'blog': cur_blog,'user':cur_user,'visitor_blog': visitor_blog,'visitor':visitor,'d_c':d_c,'articles':articles})
     56     else:
     57         return redirect('/')
     58 
     59 
     60 def filter(request, site, condition, val):
     61     """
     62     分类显示
     63     :param request:
     64     :param site:
     65     :param condition:
     66     :param val:
     67     :return:
     68     """
     69     cur_blog = models.Blog.objects.filter(site=site).select_related('user').first()
     70     cur_user = cur_blog.user
     71     template_name = "home_summary_list.html"
     72 
     73     if request.session.get('username', None):
     74         visitor = models.UserInfo.objects.filter(username=request.session['username']).select_related('blog').first()
     75         visitor_blog = visitor.blog
     76     else:
     77         visitor = ''
     78         visitor_blog = ''
     79 
     80     # d_c 是 由日期(年+月)和文章数组成的元组们,组成的列表
     81     dates = models.Article.objects.filter(blog=cur_blog).dates('create_time','month',order='DESC')
     82     d_c = []
     83     for d in dates:
     84         c = models.Article.objects.filter(create_time__date__gte = d,create_time__date__lte=d+relativedelta(months=1)).count()
     85         d_c.append((d,c))
     86 
     87     if condition == 'tag':
     88         article_list = models.Article.objects.filter(tags__title=val, blog=cur_blog).all()
     89     elif condition == 'category':
     90         article_list = models.Article.objects.filter(category__title=val, blog=cur_blog).all()
     91     elif condition == 'date':
     92         article_list = models.Article.objects.filter(blog=cur_blog).extra(
     93             where=['date_format(create_time,"%%Y-%%m")=%s'], params=[val, ]).all()
     94     else:
     95         article_list = []
     96 
     97 
     98     return render(request, template_name,{'article_list':article_list,'blog': cur_blog,'user':cur_user,'visitor_blog': visitor_blog,'visitor':visitor,'d_c':d_c})
     99 
    100 
    101 def detail(request, site, nid):
    102     """
    103     博文详细页
    104     :param request:
    105     :param site:
    106     :param nid:
    107     :return:
    108     """
    109     cur_blog = models.Blog.objects.filter(site=site).select_related('user').first()
    110     cur_article = models.Article.objects.filter(nid=nid).first()
    111     cur_user = cur_blog.user
    112     cur_comments = models.Comment.objects.filter(article=cur_article) #;print( mark_safe(cur_comments[5].content))
    113     if request.method == 'GET':
    114         if request.session.get('username', None):
    115             visitor = models.UserInfo.objects.filter(username=request.session['username']).select_related('blog').first()
    116             visitor_blog = visitor.blog
    117         else:
    118             visitor = ''
    119             visitor_blog = ''
    120 
    121         # 阅读数 +1
    122         cur_article.read_count += 1
    123         cur_article.save()
    124 
    125         # d_c 是 由日期(年+月)和文章数组成的元组们,组成的列表
    126         dates = models.Article.objects.filter(blog=cur_blog).dates('create_time', 'month', order='DESC')
    127         d_c = []
    128         for d in dates:
    129             c = models.Article.objects.filter(create_time__date__gte=d,
    130                                               create_time__date__lte=d + relativedelta(months=1)).count()
    131             d_c.append((d, c))
    132 
    133         return render(request, 'home_detail.html',
    134                       {'article': cur_article, 'user': cur_user, 'blog': cur_blog, 'comments': cur_comments,
    135                        'visitor_blog': visitor_blog,'visitor':visitor,'d_c':d_c})
    136     elif request.method == 'POST':  # 可以做对 提交评论 的处理,或者 让 提交评论 由单独的视图函数处理
    137         pass
    138     else:
    139         return redirect('/')
    140 
    141 def auth(func):
    142     '''
    143     验证 ajax请求的操作者是否是登录用户
    144     :param request:
    145     :return:
    146     '''
    147 
    148     def wrapper(request,*args,**kwargs):
    149         if request.session.get('username',None):
    150             return func(request,*args,**kwargs)
    151         else:
    152             res = {'status': False, 'error': '请登录', 'data': None}
    153             return HttpResponse(json.dumps(res))
    154     return wrapper
    155 
    156 @auth
    157 def comment(request):
    158     '''
    159     对 用户对某文章提交评论 的处理
    160     :param request:
    161     :return:
    162     '''
    163     if request.method == 'POST':
    164         res = {'status': True, 'error': None, 'data': None}
    165         cf = forms.CommentForm(request.POST)
    166         if cf.is_valid():
    167             with transaction.atomic():
    168                 cur_user = models.UserInfo.objects.filter(username=cf.cleaned_data['username']).first()
    169                 c_obj = models.Comment.objects.create(
    170                     content=cf.cleaned_data['content'],
    171                     user=cur_user,
    172                     article_id=cf.cleaned_data['article_id']
    173                 )
    174                 print(cf.cleaned_data['content'])
    175                 # print('reply:',cf.cleaned_data['reply']);print('reply_class:',type(cf.cleaned_data['reply']))
    176                 reply_id_list = cf.cleaned_data['reply'].split(',') if cf.cleaned_data['reply'] else []
    177                 c_obj.reply.add(*reply_id_list)
    178 
    179                 # 评论数+1
    180                 models.Article.objects.filter(nid=cf.cleaned_data['article_id']).update(comment_count = F('read_count')+1 )
    181 
    182         else:
    183             res['status'] = False
    184             res['error'] = cf.errors.as_data()
    185         return HttpResponse(json.dumps(res, cls=CustomJsonEncoder))
    186     else:
    187         return redirect('/')
    188 
    189 @auth
    190 def updown(request):
    191     '''
    192     点赞/踩
    193     :param request:
    194     :return:
    195     '''
    196     res = {'status':True,'error':None,'data':None}
    197     data = {};print(request.POST)
    198     for k,v in request.POST.items():
    199         data[k] = v
    200     data['username'] = request.session['username'];print('data:',data)
    201     udf = forms.UpDownForm(data)
    202 
    203     if udf.is_valid():
    204         with transaction.atomic():
    205             article = models.Article.objects.filter(nid=udf.cleaned_data['article_id']).first()
    206             if udf.cleaned_data['up'] == '0':
    207                 up = False
    208                 res['data'] = article.down_count = article.down_count + 1
    209             else:
    210                 up = True
    211                 res['data'] = article.up_count = article.up_count + 1
    212 
    213             article.save()
    214             models.UpDown.objects.create(
    215                 article=article,
    216                 user = models.UserInfo.objects.filter(username=udf.cleaned_data['username']).first(),
    217                 up=up,
    218             )
    219 
    220     else:
    221         res['status'] = False
    222         res['error'] = udf.errors.as_data()
    223 
    224     return HttpResponse(json.dumps(res,cls=CustomJsonEncoder))
    225 
    226 
    227 def t(request):
    228     # print(request.GET)
    229 
    230     func = request.GET.get('callback',None)
    231 
    232     # return HttpResponse('callback(123456)')
    233     return HttpResponse('%s("From EdmureBlog")'%func)
    web/views/home.py
     1 #! /usr/bin/env python3
     2 #  -*- coding:utf-8 -*-
     3 
     4 from django.forms import Form
     5 from django.forms import fields
     6 from django.forms import widgets
     7 from repository import models
     8 from django.core.validators import ValidationError,RegexValidator
     9 
    10 
    11 class RegisterForm(Form):
    12     '''验证注册信息'''
    13     username = fields.CharField(max_length=32,error_messages={'required':'请填写用户名'})
    14     password = fields.CharField(max_length=64,error_messages={'required':'请填写密码'})
    15     confirm_password = fields.CharField(max_length=64,error_messages={'required':'请再次填写密码'})
    16     email = fields.EmailField(error_messages={'required':'请填写邮箱'})
    17     checkCode = fields.CharField(max_length=10,error_messages={'required':'请填写验证码'})
    18 
    19     def clean_username(self):
    20         if models.UserInfo.objects.filter(username=self.cleaned_data['username']).count():
    21             raise ValidationError('用户名已存在')
    22         else:
    23             return self.cleaned_data['username']
    24 
    25     def clean_confirm_password(self):
    26         if self.cleaned_data['password'] == self.cleaned_data['confirm_password']:
    27             return self.cleaned_data['confirm_password']
    28         else:
    29             raise ValidationError(message='两次密码输入不一致')
    30 
    31 
    32 class LoginForm(Form):
    33     '''验证登陆信息'''
    34     username = fields.CharField(max_length=32,error_messages={'required':'请填写用户名'})
    35     password = fields.CharField(max_length=64,error_messages={'required':'请填写密码'})
    36     checkCode = fields.CharField(max_length=10,
    37                                  error_messages={'required':'请填写验证码'},
    38                                  # validators={r'':''}
    39                                  )
    40     autoLogin = fields.CharField(max_length=1,required=False)
    41 
    42     def clean_username(self):
    43         if models.UserInfo.objects.filter(username = self.cleaned_data['username']).count():
    44             return self.cleaned_data['username']
    45         else:
    46             raise ValidationError('用户名不存在')
    47 
    48     def clean(self):
    49         if self.cleaned_data.get('username',None):
    50             if models.UserInfo.objects.filter(username=self.cleaned_data['username'],password=self.cleaned_data['password']).count():
    51                 return self.cleaned_data
    52             else:
    53                 raise ValidationError('用户名或密码错误')
    54 
    55 
    56 class CommentForm(Form):
    57     '''验证文章评论'''
    58     content = fields.CharField(error_messages={'required':'请填写评论内容',})
    59     article_id = fields.CharField()
    60     username = fields.CharField()
    61     reply = fields.CharField(required=False,
    62                              # validators={RegexValidator(r'(d+,)*d+'):'回复评论的id错误'}
    63                              )
    64 
    65 
    66 class UpDownForm(Form):
    67     '''验证文章点赞/踩'''
    68     article_id = fields.CharField(max_length=65535,error_messages={'required':'文章id 不存在'})
    69     up = fields.CharField()
    70     username = fields.CharField()
    71 
    72     def clean_atrticle_id(self):
    73         if self.cleaned_data['article_id'].isdigit():
    74             return self.cleaned_data['article_id']
    75         else:
    76             raise ValidationError('文章id必须是正整数')
    77 
    78     def clean_up(self):
    79         if self.cleaned_data['up'] in ['0','1']:
    80             return self.cleaned_data['up']
    81         else:
    82             raise ValidationError('up字段必须是0或1')
    83 
    84     def clean(self):
    85         print(models.UpDown.objects.filter( user__username=self.cleaned_data['username'],article_id = self.cleaned_data['article_id'] ).count())
    86         if models.UpDown.objects.filter( user__username=self.cleaned_data['username'],article_id = self.cleaned_data['article_id'] ).count():
    87             raise ValidationError('请不要重复评价')
    88         else:
    89             return self.cleaned_data
    web/forms.py
     1 """EdmureBlog URL Configuration
     2 
     3 The `urlpatterns` list routes URLs to views. For more information please see:
     4     https://docs.djangoproject.com/en/1.10/topics/http/urls/
     5 Examples:
     6 Function views
     7     1. Add an import:  from my_app import views
     8     2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
     9 Class-based views
    10     1. Add an import:  from other_app.views import Home
    11     2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    12 Including another URLconf
    13     1. Import the include() function: from django.conf.urls import url, include
    14     2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    15 """
    16 from django.conf.urls import url
    17 from .views import home
    18 from .views import account
    19 
    20 urlpatterns = [
    21     # url(r'^t$', account.t),
    22     url(r'^t$',home.t),
    23     url(r'^login.html$', account.login),
    24     url(r'^register.html$', account.register),
    25     url(r'^check_code.html$', account.check_code),
    26     url(r'^logout.html$', account.logout),
    27     url(r'^comment.html$', home.comment),
    28 
    29     url(r'^updown.html$',home.updown),
    30 
    31     url(r'^(?P<site>w+)/(?P<condition>((tag)|(date)|(category)))/(?P<val>(w+-)*w+).html', home.filter),
    32     url(r'^(?P<site>w+)/(?P<nid>d+).html', home.detail),
    33     url(r'^(?P<site>w+).html', home.home),
    34     url(r'^', home.index),
    35 ]
    web/urls.py
  • 相关阅读:
    ASP.Net MVC-Web API使用Entity Framework时遇到Loop Reference
    springboot-32-使用mvc测试
    docker-dockerfile使用
    java-jmx使用
    docker-使用ali云加速
    docker-基础命令
    centos7-使用nginx做ftp站
    maven-插件-不同的开发环境指定
    maven
    mysql-定时对表分区
  • 原文地址:https://www.cnblogs.com/jailly/p/9006159.html
Copyright © 2020-2023  润新知