importjsonimportrandomfrom django.shortcuts importrender,HttpResponse,redirectfrom django.utils.safestring importmark_safefrom app01.myforms importRegFormfrom app01 importmodelsfrom django.http importJsonResponsefrom django.contrib importauthfrom django.db.models.functions importTruncMonthfrom django.db.models importFfrom app01.utils.my_page importPagination#Create your views here.
defregister(request):#当你用ajax进行数据交互 通常 试图函数都会事先定义一个字典
back_dic = {'code':None,"msg":None}
form_obj=RegForm()if request.method == 'POST':#利用forms组件校验普通字段的数据,即把传过来的数据放到ReForm去校验
form_obj =RegForm(request.POST)ifform_obj.is_valid():#校验通过,从claend_data拿到所有数据
clean_data =form_obj.cleaned_data"""clean_data = {'username':'','password':'','confirm_password':'','email':''}"""
#将confirm_password键值对从clean_data去除掉
clean_data.pop('confirm_password')#先获取头像文件对象 用户是否上传
avatar = request.FILES.get('my_avatar')ifavatar:
clean_data['avatar'] =avatar"""clean_data = {'username':'','password':'','email':'','avatar':'文件对象'}"""
#print(clean_data)
#将数据保存到数据库中
models.Userinfo.objects.create_user(**clean_data)
back_dic['code'] = 2000back_dic['msg'] = '注册成功'back_dic['url'] = '/login/'
else:
back_dic['code'] = 2001back_dic['msg'] =form_obj.errorsreturnJsonResponse(back_dic)return render(request,'register.html',locals())deflogin(request):
back_dic= {'code':None,"msg":None}#request.is_ajax() # 判断当前请求是ajax请求
if request.method == 'POST':
username= request.POST.get('username')
password= request.POST.get('password')
code= request.POST.get('code')#验证码忽略大小写进行比较
if request.session.get('code').upper() ==code.upper():#利用auth认证验证用户信息,因为密码也是密文存入数据库中的
user_obj = auth.authenticate(username=username,password=password)#类似于但不是等于,注意哈models.Userinfo.objects.filter(username=username,password=password).first()
ifuser_obj:#print(request.user.is_authenticated()) # 判断当前用户是否登录 这条语句在auth.login之前,结果为False
auth.login(request,user_obj)"""作用:
1. 设置cookie, session,类似于request.session['username'] = user_obj
2. 生成request.user的对象, 这个对象可以再视图函数中使用
3. request.user这个对象 相当于 request.session,后续可以在任意位置通过request.user拿到当前登录对象"""back_dic['code'] =100back_dic['msg'] = '登录成功'back_dic['url'] = '/home/' #设置一个让前端登陆成功后跳转到home主页
#print(request.user.is_authenticated()) # 判断当前用户是否登录 这条语句在auth.login之后,结果为True
else:
back_dic['code'] = 200back_dic['msg'] = '用户名或密码错误'
else:
back_dic['code'] = 300back_dic['msg'] = '验证码错误'
returnJsonResponse(back_dic)return render(request,'login.html')from PIL importImage,ImageDraw,ImageFontfrom io importBytesIO#生成三个随机数
defget_random():return random.randint(0,255),random.randint(0,255),random.randint(0,255)defget_code(request):#生成一个图片对象
img_obj = Image.new('RGB',(260,30),get_random())#在当前图片上生成一个画笔
img_draw =ImageDraw.Draw(img_obj)#设置样式
img_font = ImageFont.truetype('static/font/222.ttf',30)#图片验证码 (数字 小写字母 大写字母) 五位验证码 1aZd2
#A-Z:65-90 a-z:97-122
#定义一个变量用来存储验证码
code = ''
for i in range(5):
upper_str= chr(random.randint(65,90))
lower_str= chr(random.randint(97,122))
random_int= str(random.randint(0,9))#从上面三个里面随机选择一个
res =random.choice([upper_str,lower_str,random_int])#是用画笔对象在生成的图片上写一个一个的验证码,注意书写的坐标位置是在变化的
img_draw.text((40+ i * 40,-5),res,get_random(),img_font)
code+=res#保存到内存管理器中,需要用到BytesIO模块
#就把它当成文件句柄
io_obj =BytesIO()
img_obj.save(io_obj,'png')#图片格式必须得传
#找一个公共的地方存储验证码 以便后续其他视图函数校验
request.session['code']=code#讲些好的图片返回到前端img标签src属性中(再次说一下src属性可以存放三种:1、静态路径地址 2、二进制数据 3、url地址)
#io_obj.getvalue() 获取二进制数据,
returnHttpResponse(io_obj.getvalue())defhome(request):
article_list=models.Article.objects.all()return render(request,'home.html',locals())defset_password(request):if request.method == 'POST':
old_password= request.POST.get('old_password')
new_password= request.POST.get('new_password')
confirm_password= request.POST.get('confirm_password')if new_password ==confirm_password:ifrequest.user.check_password(old_password):
request.user.set_password(new_password)
request.user.save()return redirect('/login/')return render(request,'set_password.html')deflogout(request):
auth.logout(request)return redirect('/login/')from django.db.models importCountdef site(request,username,*args,**kwargs):
user_obj= models.Userinfo.objects.filter(username=username).first()
blog=user_obj.blog#查询当前用户下对应的文章列表
article_list = models.Article.objects.filter(blog=blog)#当前用户所有的文章
if notuser_obj:return render(request,'error.html')
username=user_obj.username#判断kwagrs是否有值,如果有值你应该对上面的article_list在做一层筛选
if kwargs:#两个值# {'condition':'','params':''}
condition = kwargs.get('condition')
params= kwargs.get('params')print(condition,params)if condition == 'category':#链式过滤查询,得到分类下对应的文章 注意category_id位文章表中真实存在的字段
article_list = article_list.filter(category_id=params)elif condition == 'tag':#链式过滤查询,得到标签下对应的文章 注意tag__id:有文章表跨表到标签表使用神奇双下划线
article_list = article_list.filter(tag__id=params)elif condition == 'archive':#链式过滤查询,得到年和月下对应的文章 2018-1
year,month = params.split('-')#解压赋值 需要分别对年和月进行刷选
article_list = article_list.filter(create_time__year=year,create_time__month=month)#下面是侧边栏渲染相关
#查询当前用户每一个的分类及分类下的文章数,分类查文章:表明小写
#category_list = models.Category.objects.filter(blog=blog).annotate(c=Count('article')).values('category_name','c') 列表套字典
#print(category_list)
#列表套元组
category_list = models.Category.objects.filter(blog=blog).annotate(c=Count('article')).values_list('category_name', 'c','pk')#查询当前用户每一个标签下的文章数
tag_list = models.Tag.objects.filter(blog=blog).annotate(c=Count('article')).values_list('tag_name', 'c','pk')#print(tag_list)
#日期归档
#data_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time')).values('month').annotate(c=Count('pk')).values_list('month','c')
date_list = models.Article.objects.filter(blog=blog).annotate(month=TruncMonth('create_time')).values('month').annotate(c=Count('pk')).values_list('month', 'c')"""pk:会自动帮你查找到当前表的主键字段"""
#print(date_list)
return render(request,'site.html',locals())defarticle_detail(request,username,article_id):#获取具体文章的对象
article_obj = models.Article.objects.filter(pk=article_id).first()
blog=article_obj.blog#将当前文章的所有评论内容查询出来发给前端渲染
comment_list = models.Comment.objects.filter(article=article_obj)#分页
page_obj = Pagination(current_page=request.GET.get('page',1),all_count=comment_list.count())
page_queryset=comment_list[page_obj.start:page_obj.end]return render(request,'article_detail.html',locals())#点赞点踩
defup_or_down(request):
back_dic= {"code": None, 'msg': ''}#这里可以来个骚操作,判断ajax请求
ifrequest.is_ajax():"""1.用户是否登陆
2.有没有点过
3.自己不能给自己点赞
4.数据库同步
article
upanddown
数据要同步"""is_up= request.POST.get('is_up') #你拿到的是js格式的布尔值 对应到python里面就是字符串
is_up = json.loads(is_up) #利用json模块 将字符串形式转成python里面的布尔值
article_id= request.POST.get('article_id')#1、判断用户是否登陆
ifrequest.user.is_authenticated():#2、判断当前文章是不是用户自己写的,即判断当前文章对象和当前登录用户是否是一个人
#先拿到当前文章对象
article_obj = models.Article.objects.filter(pk=article_id).first()ifarticle_obj:if not article_obj.blog.userinfo.pk ==request.user.pk:#3、判断当前文章是否被点过了,即去点赞表查是否被点过了 逆向思维
is_click = models.UpAndDown.objects.filter(user=request.user,article=article_obj)if notis_click:#没有点过,记录数据,问题:到底是点赞还是点踩
if is_up:#如果是点赞
models.Article.objects.filter(pk=article_id).update(up_num = F('up_num')+1)else:
models.Article.objects.filter(pk=article_id).update(up_num=F('down_num') + 1)#点赞点踩操作点赞点踩表写入数据
models.UpAndDown.objects.create(user=request.user,article=article_obj,is_up=is_up)
back_dic['code'] = 2000back_dic['msg'] = '点赞成功' if is_up else '点踩成功'
else:
back_dic['code'] = 2001back_dic['msg'] = '你已经点过了'
else:
back_dic['code'] = 2002back_dic['msg'] = '你个臭不要脸的 不能给自己点'
else:
back_dic['code'] = 2003back_dic['msg'] = '未知错误'
else:
back_dic['code'] = 2004
#这里使用后端取消转义字符
back_dic['msg'] = mark_safe('请先登录')returnJsonResponse(back_dic)"""事务:ACID
原子性
一致性
隔离性
持久性
将评论内容同步写入到评论表和文章表,这里用到事务的原子性,要么一起成功,要么一起失败"""
from django.contrib.auth.decorators importlogin_requiredfrom django.db import transaction #django中开启事务 需要先倒入该模块
@login_required #全局登录认证装饰器
defcomment(request):
back_dic= {'code':None,'msg':''}ifrequest.is_ajax():
comment= request.POST.get('comment')
article_id= request.POST.get('article_id')
parent_id= request.POST.get('parent_id')
with transaction.atomic():#在with代码块写的就是一个事务
#文章表修改comment_num字段
models.Article.objects.filter(pk=article_id).update(comment_num=F('comment_num')+1)#评论表里面新增数据
models.Comment.objects.create(user=request.user,article_id=article_id,content=comment,parent_id=parent_id)
back_dic['code'] = 2000back_dic['msg'] = '评论成功'
returnJsonResponse(back_dic)
@login_requireddefbackend(request):
article_list= models.Article.objects.filter(blog=request.user.blog)#分页
page_obj = Pagination(current_page=request.GET.get('page', 1), all_count=article_list.count())
page_queryset=article_list[page_obj.start:page_obj.end]return render(request,'backend/backend.html',locals())from bs4 importBeautifulSoup
@login_requireddefadd_article(request):if request.method == 'POST':
title= request.POST.get('title')
content= request.POST.get('content')#能够帮我拿到当前用户写的所有的标签 将script删除
res = BeautifulSoup(content,'html.parser')#获取所有标签
tags =res.find_all()for tag intags:#将script全部删除
if tag.name == 'script':#删除指定的标签
tag.decompose()#获取用户输入的文本值
desc = res.text[0:150]
models.Article.objects.create(title=title,content=str(res),desc=desc,blog=request.user.blog)return redirect('/backend/')return render(request,'backend/add_article.html')from bbs importsettingsimportos
@login_requireddefupload_img(request):
back_dic= {'error': ''}if request.method == 'POST':#print(request.FILES) 查看字典的key 和文件值
img_obj = request.FILES.get('imgFile')#规定编辑器上传的图片全部放到media文件夹里面的upload_img文件夹下
#1.将文件存储到media文件夹下
path = os.path.join(settings.BASE_DIR, 'media', 'upload_img')if notos.path.exists(path):
os.mkdir(path)
file_path=os.path.join(path, img_obj.name)
with open(file_path,'wb') as f:for line inimg_obj:
f.write(line)#2.将文件路径返回给前端
back_dic['error'] =0
back_dic['url'] = '/media/upload_img/%s' %img_obj.name"""//成功时
{
"error" : 0,
"url" : "http://www.example.com/path/to/file.ext"
}
//失败时
{
"error" : 1,
"message" : "错误信息"
}"""
returnJsonResponse(back_dic)#用户修改头像
@login_requireddefset_avatar(request):
username=request.user.usernameif request.method == 'POST':
new_avatar= request.FILES.get('new_avatar')#如果用queryset对象更新头像 不会自动帮你拼接前缀,要手动拼接
#models.Userinfo.objects.filter(pk=request.user.pk).update(avatar = new_avatar)
#或者直接通过对象点属性来进行修改,但是这样的缺点是该对象的整个信息都会从新写一遍
user_obj = models.Userinfo.objects.filter(pk=request.user.pk).first()
user_obj.avatar=new_avatar
user_obj.save()return redirect('/home/')return render(request,'set_avatar.html',locals())