加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

django搭建BBS-表单创建&注册

发布时间:2020-12-15 17:09:40 所属栏目:大数据 来源:网络整理
导读:django搭建BBS-表单创建注册 0824自我总结 文件结构 app 接口 migrations __inint__.py admin.py 管理员页面注册表单用 apps.py bbsform.py form组件相关设置 models.py 模型存放 tests.py views.py 业务逻辑 avatar 图片文件存储 BBS 项目名称以及路由存放

django搭建BBS-表单创建&注册

0824自我总结

文件结构

  • app 接口

    • migrations
    • __inint__.py
    • admin.py 管理员页面注册表单用
    • apps.py
    • bbsform.py form组件相关设置
    • models.py 模型存放
    • tests.py
    • views.py 业务逻辑
  • avatar 图片文件存储

  • BBS 项目名称以及路由存放

    • __inint__.py
    • settings.py
    • urls.py
    • wsgi.py
  • static

    • bootstrap-3.3.7-dist bootstrap文件网上下载的
    • jquery-3.4.1.min.js jq文件
  • templates 页面文件存放

一.django相关设置

settings.py

"""
Django settings for BBS project.

Generated by 'django-admin startproject' using Django 1.11.22.

For more information on this file,see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values,see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR,...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 's0x+v@gqeoxs4ruj58cq5&*5#7on_h$n4-$hwb3cr&h(@qcmoc'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','app.apps.AppConfig',]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',]

ROOT_URLCONF = 'BBS.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [os.path.join(BASE_DIR,'templates')],'APP_DIRS': True,'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug','django.template.context_processors.request','django.contrib.auth.context_processors.auth','django.contrib.messages.context_processors.messages',],},]

WSGI_APPLICATION = 'BBS.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3','NAME': os.path.join(BASE_DIR,'db.sqlite3'),}
}


# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',{
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',{
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',{
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',]


# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS,JavaScript,Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS=(
    os.path.join(BASE_DIR,'static'),)

#因为我创建模型的时候用到了user的类
AUTH_USER_MODEL='app.Userinfo'

二.模型的创建&管理页面注册

models.py

from django.db import models
from django.contrib.auth.models import AbstractUser


class UserInfo(AbstractUser):
    nid = models.AutoField(primary_key=True)
    # 头像:FileField文件(varchar类型),default:默认值,upload_to上传的路径
    avatar = models.FileField(upload_to='avatar/',default='avatar/default.png')
    #跟blog表一对一
    #OneToOneField本质就是ForeignKey,只不过有个唯一性约束
    blog = models.OneToOneField(to='Blog',to_field='nid',null=True)
    # blog = models.ForeignKey(to='Blog',null=True,unique=True)

    class Meta:
        # db_table='xxxx'
        # 在admin中显示的表名
        verbose_name='用户表'
        #去掉  用户表  后的s
        verbose_name_plural = verbose_name

class Blog(models.Model):
    nid = models.AutoField(primary_key=True)
    #站点名称
    title = models.CharField(max_length=64)
    #站点副标题
    site_name = models.CharField(max_length=32)
    #不同人不同主题
    theme = models.CharField(max_length=64)
    def __str__(self):
        return self.site_name
#分类表
class Category(models.Model):
    nid = models.AutoField(primary_key=True)
    #分类名称
    title = models.CharField(max_length=64)
    #跟博客是一对多的关系,关联字段写在多的一方
    #to  是跟哪个表关联   to_field跟表中的哪个字段做关联, null=True 表示可以为空
    blog = models.ForeignKey(to='Blog',null=True)
    def __str__(self):
        return self.title

class Tag(models.Model):
    nid = models.AutoField(primary_key=True)
    #标签名字
    title = models.CharField(max_length=64)
    # 跟博客是一对多的关系,关联字段写在多的一方
    blog = models.ForeignKey(to='Blog',null=True)
    def __str__(self):
        return self.title

class Article(models.Model):
    nid = models.AutoField(primary_key=True)
    #verbose_name在admin中显示该字段的中文
    title = models.CharField(max_length=64,verbose_name='文章标题')
    #文章摘要
    desc = models.CharField(max_length=255)
    #文章内容  大文本
    content = models.TextField()
    #DateTimeField 年月日时分秒(注意跟datafield的区别)
    #auto_now_add=True:插入数据会存入当前时间
    #auto_now=True  修改数据会存入当前时间
    create_time = models.DateTimeField(auto_now_add=True)
    commit_num=models.IntegerField(default=0)
    up_num=models.IntegerField(default=0)
    down_num=models.IntegerField(default=0)
#一对多的关系
    blog = models.ForeignKey(to='Blog',null=True)
    # 一对多的关系
    category = models.ForeignKey(to='Category',null=True)
    #多对多关系  through_fields  不能写反了:
    tag = models.ManyToManyField(to='Tag',through='ArticleTOTag',through_fields=('article','tag'))
    def __str__(self):
        return self.title+'----'+self.blog.userinfo.username

class ArticleTOTag(models.Model):
    nid = models.AutoField(primary_key=True)
    article = models.ForeignKey(to='Article',to_field='nid')
    tag = models.ForeignKey(to='Tag',to_field='nid')

class Commit(models.Model):
    #谁对那篇文章评论了什么内容
    nid = models.AutoField(primary_key=True)
    user = models.ForeignKey(to='UserInfo',to_field='nid')
    article = models.ForeignKey(to='Article',to_field='nid')
    content = models.CharField(max_length=255)
    #评论时间
    create_time = models.DateTimeField(auto_now_add=True)
    #自关联()
    parent = models.ForeignKey(to='self',blank=True)

class UpAndDown(models.Model):
    #谁对那篇文章点赞或点踩
    nid = models.AutoField(primary_key=True)
    user = models.ForeignKey(to='UserInfo',to_field='nid')
    #布尔类型,本质也还是0和1
    is_up = models.BooleanField()

    class Meta:
        #联合唯一,一个用户只能给一片文章点赞或点踩
        unique_together = (('user','article'),)

admin.py

from django.contrib import admin

# Register your models here.
#先导入模型
from app import models

#注册表
admin.site.register(models.UserInfo)
admin.site.register(models.Blog)
admin.site.register(models.Category)
admin.site.register(models.Tag)
admin.site.register(models.Article)
admin.site.register(models.ArticleTOTag)
admin.site.register(models.Commit)
admin.site.register(models.UpAndDown)

三.路由

urls.py

from django.conf.urls import url
from django.contrib import admin
#主路由导入视图内函数
from app import views
urlpatterns = [
    url(r'^admin/',admin.site.urls),url(r'^register/',views.register),]

四.form组件


from django import forms
from django.forms import widgets

from django.core.exceptions import ValidationError

from app import models
#写一个类,继承Form  没有头像校验的字段
class Register(forms.Form):
    username=forms.CharField(max_length=18,min_length=3,label="用户名",error_messages={'max_length':'太长了','min_length':'太短了','required':'不能为空'},widget=widgets.TextInput(attrs={'class':'form-control'}),)
    password=forms.CharField(max_length=18,label="密码",widget=widgets.PasswordInput(attrs={'class':'form-control'}),)
    re_pwd=forms.CharField(max_length=18,label="确认密码",)
    email=forms.EmailField(max_length=18,label="邮箱",widget=widgets.EmailInput(attrs={'class':'form-control'}),)
    #局部钩子,局部校验
    def clean_username(self):
        #取出name对应的值
        name=self.cleaned_data.get('username')
        # if name.startswith('sb'):
        #     #校验不通过,抛异常
        #     raise ValidationError('不能以sb开头')
        #     #校验通过,直接return name值
        # else:
        #     return name
        user=models.UserInfo.objects.filter(username=name).first()
        if user:
            #用户存在,抛异常
            raise ValidationError('用户已经存在')
        else:
            return name
    #全局钩子,全局校验

    def clean(self):
        pwd=self.cleaned_data.get('password')
        r_pwd=self.cleaned_data.get('re_pwd')
        if pwd==r_pwd:
            #校验通过,返回清洗后的数据
            return self.cleaned_data
        else:
            #校验不通过,抛异常
            raise ValidationError('两次密码不一致')

五.业务逻辑&html页面

1.业务逻辑

views.py

from django.shortcuts import render,HttpResponse,redirect
from django.http import JsonResponse
#Image导入
#ImageDraw在图片上写字
#ImageFont 写字的格式
from PIL import Image,ImageDraw,ImageFont
import random
# 相当于把文件以byte格式存到内存中
from io import BytesIO

from django.contrib import auth

from app.bbsforms import Register
from app import models

from django.db.models import Count
from django.db.models.functions import TruncMonth
from django.db.models import F





# Create your views here.
def register(request):
    if request.method=='GET':
        form=Register()
        return render(request,'register.html',{'form':form})
    elif request.is_ajax():
        response={'code':100,'msg':None}
        form = Register(request.POST)
        if form.is_valid():
            #校验通过的数据
            clean_data=form.cleaned_data
            #把re_pwd剔除
            clean_data.pop('re_pwd')
            #取出头像
            avatar=request.FILES.get('avatar')
            if avatar:
                #因为用的是FileField,只需要把文件对象赋值给avatar字段,自动做保存
                clean_data['avatar']=avatar
            user=models.UserInfo.objects.create_user(**clean_data)
            if user:
                response['msg'] = '创建成功'
            else:
                response['code'] = 103
                # 把校验不通过的数据返回
                response['msg'] = '创建失败'
        else:
            response['code']=101
            #把校验不通过的数据返回
            response['msg']=form.errors
            print(type(form.errors))
        return JsonResponse(response,safe=False)

2.网页

常见的几条函数的封装

jq.html

<script src="/static/jquery-3.4.1.min.js"></script>

bootstrap.html

<link rel="stylesheet" href='/static/bootstrap-3.3.7-dist/css/bootstrap.min.css'>
<script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>

主视图

register.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>注册</title>
    {% include 'bootstrap.html' %}
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">

            <h1>注册</h1>
            <form id="my_form">
                {% csrf_token %}
                {% for foo in form %}
                    <div class="form-group">
                        {#foo.auto_id   就是foo生成的input的id#}
                        <label for="{{ foo.auto_id }}">{{ foo.label }}</label>
                        {{ foo }} <span style="color: red" class="error pull-right"></span>
                    </div>

                {% endfor %}
                <div class="form-group">
                    <label for="id_file">头像
                        <img src="/static/img/default.png" width="80" height="80" style="margin-left: 20px" id="id_img">
                    </label>


                    <input type="file" name="file" id="id_file" style="display: none">
                </div>
                <input type="button" class="btn btn-success" value="提交" id="id_submit">
            </form>
        </div>
    </div>
</div>
</body>
{% include 'jq.html' %}
<script>
    //当该控件发生变化,响应该事件
    $("#id_file").change(function () {
        //alert(1)
        //取到文件对象
        var file = $("#id_file")[0].files[0]
        //放到img控件上,借助于filereader 中间的东西,文件阅读器
        //生成一个文件阅读器对象赋值给filereader
        var filereader = new FileReader()
        //把文件读到filereader对象中
        //读文件需要时间,需要文件读完再去操作img
        filereader.readAsDataURL(file)

        filereader.onload = function () {
            $("#id_img").attr('src',filereader.result)
        }

    })
    $("#id_submit").click(function () {

        //ajax 上传文件


        var formdata = new FormData()
        //一个一个往里添加,稍微复杂,用简便方法
        // formdata.append('name',$("#id_name").val())
        // formdata.append('pwd',$("#id_pwd").val())

        //简便方法
        //form 对象的serializeArray,它会把form中的数据包装到一个对象中(不包含文件)
        var my_form_data = $("#my_form").serializeArray()
        //console.log(typeof my_form_data)
        //console.log(my_form_data)
        //jq的循环,传两个参数,第一个是要循环的对象,第二个参数是一个匿名函数
        $.each(my_form_data,function (k,v) {
            {#console.log(k)#}
            {#console.log(v)#}
            formdata.append(v.name,v.value)
        })
        formdata.append('avatar',$("#id_file")[0].files[0])


        $.ajax({
            url: '/register/',type: 'post',processData: false,//告诉jQuery不要去处理发送的数据
            contentType: false,// 告诉jQuery不要去设置Content-Type请求头
            data: formdata,success: function (data) {
                //console.log(data)
                if(data.code==100){
                    location.href='/login/'
                }else if(data.code==101){
                    $.each(data.msg,v) {
                        console.log(k)
                        console.log(v)
                        $("#id_"+k).next().html(v[0])
                        if(k=='__all__'){
                            $("#id_re_pwd").next().html(v[0])
                        }

                    })

                }
                //定时器
                setTimeout(function () {
                    $(".error").html("")
                },3000)
            }


        })
    })


</script>
</html>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读