栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

表创建及,同步注册功能 - forms组件 - 用户头像前端实时展示,登录功能 - 实现图片验证码

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

表创建及,同步注册功能 - forms组件 - 用户头像前端实时展示,登录功能 - 实现图片验证码

数据库表创建及同步

'''
表的关系如下(models.py)
1、用户表
	继承AbstractUser (既具有auto_user表字段,也有扩展字段)
	
	扩展   
	phone  电话号码
    avatar   用户头像
    creat_time    创建时间
    
     外键字段
    	一对一个人站点表(查询频率较高,建在用户表)
    	
    from django.contrib.auth.models import AbstractUser
	class UserInfo(AbstractUser):
    phone = models.BigIntegerField(verbose_name='手机号',null=True)
    #头像
    avatar = models.FileField(upload_to='avatar/',default='avatar/default.png',verbose_name='用户头像')
    '''
    给avatar字段传文件对象,该文件会自动存储到avatar字段值保存文件路径avatar/default.png
    '''
    create_time = models.DateField(auto_now_add=True,verbose_name='创建时间')

    blog = models.OneToOneField(to='Blog',null=True,on_delete=models.CASCADE)
    (站点)
    
    
2.个人站点表
    site_name 站点名称
    site_title   站点标题
    site_theme  站点样式
    
    
    class Blog(models.Model):
    site_name = models.CharField(verbose_name='站点名称',max_length=32)
    site_title = models.CharField(verbose_name='站点标题',max_length=32)
    #site_theme存放的是css/js的文件路径
    site_theme = models.CharField(verbose_name='站点样式',max_length=64)
    
    
3.文章标签表
   name        标签名
   外键字段
      一对多个人站点   
      
    class Tag(models.Model):
    name = models.CharField(verbose_name='文章标签',max_length=32)
    blog = models.ForeignKey(to='Blog', null=True,on_delete=models.CASCADE)
    
    
 4.文章分类表
   name        分类名
	  外键字段
         一对多个人站点
         
    class Category(models.Model):
    name = models.CharField(verbose_name='文章分类',max_length=32)
    blog = models.ForeignKey(to='Blog',null=True,on_delete=models.CASCADE)
    
    
 5.文章表
   title   文章标题
   desc    文章简介
   content 文章内容
   create_time 发布时间

   数据库字段设计优化(******)(设计为普通字段,然后同步的将对应的普通字段更新即可)
   (虽然下述的三个字段可以从其他表里面跨表查询计算得出,但是频繁跨表效率)
        up_num                  点赞数
        down_num                点踩数
        comment_num         	评论数

    外键字段
       一对多个人站点
       多对多文章标签
       一对多文章分类
	class Article(models.Model):
    title = models.CharField(verbose_name='文章标题',max_length=64)
    desc = models.CharField(verbose_name='文章简介',max_length=255)
    #文章内容由很多,一般情况下使用TextFiled
    content = models.TextField(verbose_name='文章内容')
    create_time = models.DateField(auto_now_add=True)

    #数据库字段设计优化
    up_num = models.BigIntegerField(verbose_name='点赞数',default=0)
    down_num = models.BigIntegerField(verbose_name='点踩数',default=0)
    comment_num = models.BigIntegerField(verbose_name='评论数',default=0)

    blog = models.ForeignKey(to='Blog',null=True,on_delete=models.CASCADE)
    category = models.ForeignKey(to='Category',null=True,on_delete=models.CASCADE)

    #多对多文章标签(三种方式,其中我们用半自动)
    tags = models.ManyToManyField(to='Tag',
                                  through='Article2Tag',
                                  through_fields=('article','tag'),
                                  )
     
    #第三张关系表
	class Article2Tag(models.Model):
    article = models.ForeignKey(to='Article',on_delete=models.CASCADE)
    tag = models.ForeignKey(to='Tag',on_delete=models.CASCADE)
    
    
6.点赞点踩表
    记录哪个用户给哪篇文章点了赞还是点了踩
    user                        ForeignKey(to="User")               
    article                 	ForeignKey(to="Article")    
    is_up                       BooleanField()


	class UpAndDown(models.Model):
    user = models.ForeignKey(to='UserInfo',on_delete=models.CASCADE)
    article = models.ForeignKey(to='Article',on_delete=models.CASCADE)
    is_up = models.BooleanField()   #存布尔值0/1
    
    
  
7.文章评论表
    记录哪个用户给哪篇文章写了哪些评论内容
    user                        ForeignKey(to="User")               
    article                 	ForeignKey(to="Article")
    content                 	CharField()
    comment_time        		DateField()
    # 自关联
    parent                  	ForeignKey(to="Comment",null=True)      
    # ORM专门提供的自关联写法 
    parent                 	 	ForeignKey(to="self",null=True)

	class Comment(models.Model):
    user = models.ForeignKey(to='UserInfo',on_delete=models.CASCADE)
    article = models.ForeignKey(to='Article',on_delete=models.CASCADE)
    content = models.CharField(verbose_name='评论内容',max_length=255)
    comment_time = models.DateTimeField(verbose_name='评论时间',auto_now_add=True)

    #自关联
    parent = models.ForeignKey(to='self',null=True,on_delete=models.CASCADE)
    #记得要加null=True
'''

views.py导的模块

from django.shortcuts import render,HttpResponse,redirect
from app01.myforms import MyRegForm
from app01 import models
from django.http import JsonResponse

forms组件

myform.py

# 书写针对用户表的forms组件代码
from django import forms
from app01 import models
class MyRegForm(forms.Form):
    username = forms.CharField(label='用户名',
                               max_length=8,
                               min_length=3,
                               error_messages={
                                   'min_length': '用户名最小3位',
                                   'max_length': '用户名最大8位',
                                   'required': '用户名不能为空'
                               },
                               # 还需要让标签有bootstrap样式
                               widget=forms.widgets.TextInput(
                                   attrs={
                                       'class': 'form-control'})
                               )
    password = forms.CharField(label='密码',
                               max_length=8,
                               min_length=3,
                               error_messages={
                                   'min_length': '密码最小3位',
                                   'max_length': '密码最大8位',
                                   'required': '密码不能为空'
                               },
                               # 还需要让标签有bootstrap样式
                               widget=forms.widgets.PasswordInput(
                                   attrs={
                                       'class': 'form-control'})
                               )
    confirm_password = forms.CharField(
        label='确认密码', max_length=8, min_length=3,
        error_messages={
            'min_length': '确认密码最小3位',
            'max_length': '确认密码最大8位',
            'required': '确认密码不能为空'
        },
        # 还需要让标签有bootstrap样式
        widget=forms.widgets.PasswordInput(
            attrs={'class': 'form-control'})
        )
    email = forms.EmailField(label='邮箱',
                             error_messages={
                                 'required': '邮箱不能为空',
                                 'invalid': '邮箱格式不正确',
                             },
                             # 还需要让标签有bootstrap样式
                             widget=forms.widgets.EmailInput(
                                 attrs={
                                     'class': 'form-control'})
                             )

    # 钩子函数
    # 局部钩子:当你需要给单个字段增加校验规则的时候使用(校验用户名是否存在)
    def clean_username(self):
        username = self.cleaned_data.get(
            'username')
        # 去数据库校验
        is_exist = models.UserInfo.objects.filter(
            username=username)
        if is_exist:
            self.add_error('username', '用户已存在!')
        return username

    # 全局钩子:当需要给多个字段增加校验规则的时候使用(校验两次密码是否一致)
    def clean(self):
        password = self.cleaned_data.get(
            'password')
        confirm_password = self.cleaned_data.get(
            'confirm_password')
        if not password == confirm_password:
            self.add_error('confirm_password',
                           '两次密码不一致')

        return self.cleaned_data

注册功能

def register(request):
    form_obj = MyRegForm()
    back_dic = {'code': 1000, 'msg': ''}
    if request.method == 'POST':
        #校验数据是否合法
        form_obj = MyRegForm(request.POST)
        #判断数据是否合法
        if form_obj.is_valid():
            # print(form_obj.cleaned_data)  #{'username': 'tom', 'password': '1234', 'confirm_password': '1234', 'email':'111@qq.com'}
            #将校验通过的数据字典赋值给一个变量
            clean_data = form_obj.cleaned_data
            #将字典里面的confirm_password键值对删除
            clean_data.pop('confirm_password')
            #用户头像
            file_obj = request.FILES.get('avatar')
            #针对用户头像一定要判断是否传值
            if file_obj:
                clean_data['avatar'] = file_obj
            #直接操作数据库保存数据
            models.UserInfo.objects.create_user(**clean_data)
            #注册成功跳到登录页面
            back_dic['url'] = '/login/'
        else:
            back_dic['code'] = 2000
            back_dic['msg'] = form_obj.errors
        return JsonResponse(back_dic)
    return render(request,'register.html',locals())

登录功能

def login(request):
    return render(request,'login.html')

登录功能

  • 实现图片验证码
'''
图片相关的模块
pip install pillow
'''
from PIL import Image,ImageDraw,ImageFont
'''
Image:生成图片
ImageDraw:能够在图片上乱涂乱画
ImageFont:控制字体样式
'''
from io import BytesIO,StringIO
'''
内存管理器模块
BytesIO:临时存储数据,返回的时候数据是二进制
StringIO:临时存储数据,返回的时候数据是字符串
'''
import random
def get_random():
    return random.randint(0,255),random.randint(0,255),random.randint(0,255)
def get_code(request):
    #推导步骤1:直接获取后端现成的图片二进制数据发送给前端
    # with open(r'static/img/111.png','rb') as f:
    #     data = f.read()
    # return HttpResponse(data)

    #推导步骤2:利用pillow模块动态生成图片
    # img_obj = Image.new('RGB',(500,35),get_random())
    # with open('xxx.png','wb') as f:
    #     img_obj.save(f,'png')
    # with open('xxx.png','rb') as f:
    #     data = f.read()
    # return HttpResponse(data)
    #文件存储繁琐IO操作效率低


    #推导步骤3:借助内存管理器模块

    # img_obj = Image.new('RGB', (500, 35),
    #                     get_random())
    # io_obj = BytesIO()   #生成一个内存管理器对象,可以看成是文件句柄
    # img_obj.save(io_obj,'png')
    # return HttpResponse(io_obj.getvalue())
    #从内存管理器读取二进制的图片数据返回给前端


    #最终步骤4:写图片验证码
    img_obj = Image.new('RGB', (500, 35),get_random())
    img_draw = ImageDraw.Draw(img_obj)   #产生一个画笔对象
    img_font = ImageFont.truetype('static/font/222.ttf',30)   #字体样式和大小


    #随机验证码,5位数字,小写字母,大写字母
    code = ''
    for i in range(5):
        random_upper = chr(random.randint(65,90))
        random_lower = chr(random.randint(97,122))
        random_int = str(random.randint(0,9))
        #从上面三个里面随机选择一个
        tmp = random.choice([random_upper,random_lower,random_int])
        #将产生的随机字符串写入到图片上
        '''
        为什么是一个个写而不是生成5个后再写?
        因为一个个写可以控制每个字体的间隙,而生成后就无法控制了
        '''
        img_draw.text((i*60+60,0),tmp,get_random(),img_font)
        #拼接随机字符串
        code += tmp
    # print(code)
    #随机验证码在登录的视图函数需要用到,要比对,所以要找地方存起来并且其他视图函数
    #也能拿到
    request.session['code'] = code
    io_obj = BytesIO()
    img_obj.save(io_obj,'png')
    return HttpResponse(io_obj.getvalue())

register.html(注册)




    
    Title
    
    
    



注册

{% csrf_token %} {% for form in form_obj %}
{{ form }}
{% endfor %}

login.html(登录)




    
    Title
    
    
    
    {% load static %}


登录

urls

from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('register/',views.register,name='reg'),
    path('login/',views.login,name='login'),
    path('get_code/',views.get_code,name='gc'),
]

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/977764.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号