django搭建BBS-表單創建&註冊

来源:https://www.cnblogs.com/pythonywy/archive/2019/08/24/11405681.html
-Advertisement-
Play Games

django搭建BBS 表單創建&註冊 0824自我總結 文件結構 app 介面 migrations _\_inint\_\_.py admin.py apps.py bbsform.py models.py tests.py views.py avatar BBS \_\_inint\_\_.p ...


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', to_field='nid',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', to_field='nid', 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', to_field='nid', 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', to_field='nid', null=True)
    # 一對多的關係
    category = models.ForeignKey(to='Category', to_field='nid', 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', to_field='nid',null=True,blank=True)

class UpAndDown(models.Model):
    #誰對那篇文章點贊或點踩
    nid = models.AutoField(primary_key=True)
    user = models.ForeignKey(to='UserInfo', to_field='nid')
    article = models.ForeignKey(to='Article', 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,min_length=3,label="密碼",
                         error_messages={'max_length':'太長了',
                                         'min_length':'太短了',
                                         'required':'不能為空'},
                            widget=widgets.PasswordInput(attrs={'class':'form-control'}),
                         )
    re_pwd=forms.CharField(max_length=18,min_length=3,label="確認密碼",
                         error_messages={'max_length':'太長了',
                                         'min_length':'太短了',
                                         'required':'不能為空'},
                            widget=widgets.PasswordInput(attrs={'class':'form-control'}),
                         )
    email=forms.EmailField(max_length=18,min_length=3,label="郵箱",
                         error_messages={'max_length':'太長了',
                                         'min_length':'太短了',
                                         'required':'不能為空'},
                            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,function (k,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>

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在 IntelliJ IDEA 中,沒有類似於 Eclipse 工作空間(Workspace)的概念,而是提出了Project和Module這兩個概念。多module有一個父maven工程,多個子工程。在多個子工程中,可能有一個web工程,也可能有多個web工程。這樣的好處在於大大解耦各個modul... ...
  • 會話技術: 會話是什麼? 瀏覽器和伺服器交互,瀏覽器打開網頁訪問伺服器,會話開始,正常交互. 瀏覽器關閉,會話結束. 會話能幹什麼? 會話可以共用數據. Cookie和session將數據保存在不同的位置 進行數據共用 Cookie入門案例 1.創建一個cookie對象 a. Cookie cook ...
  • 1.iter補充 2.ntp_client和ntp_server 3.time複習 4.udp的客戶端與服務端通信 5.解決粘包 # from socket import * # ip_port=('127.0.0.1',8080) # back_log=5 # buffer_size=1024 # ...
  • 1. course 1.進程創建的兩種方式 1. 開啟進程的第一種方式: 2. 開啟進程的第二種方式: 3. 簡單應用 2.獲取進程pid 3.驗證進程之間的空間隔離 4. join 5.進程的其他參數 6.守護進程 7.僵屍進程孤兒進程 基於 環境( ) 主進程需要等待子進程結束之後,主進程才結束 ...
  • 服務鏈路跟蹤 背景 微服務以微出名,在實際的開發過程中,涉及到成百上千個服務,網路請求引起服務之間的調用極其複雜。 當請求不可用或者變慢時,需要及時排查出故障服務點成為了微服務維護的一大難關。 服務鏈路跟蹤技術應運而生。 ZipKin Zipkin 是一個開放源代碼分散式的跟蹤系統,由Twitter ...
  • Python 入門之常用運算符 算數運算符 比較運算符 賦值運算符 邏輯運算符 成員運算符 位運算符 身份運算符 Python運算符優先順序 ...
  • HTTP不能保持連接,可使用會話保存用戶信息。 常用的會話技術有2種:Cookie、Session。 Cookie 1、原理 當用戶第一次訪問某個網站時,伺服器設置Cookie,存儲用戶信息,放在響應頭欄位中,隨HTTP響應傳給瀏覽器,瀏覽器把Cookie存儲到本地電腦上。 當用戶再次訪問該網站時 ...
  • 摘要: 在 的版本變遷過程中,註解發生了很多的變化,然而代理的設計也發生了微妙的變化,從 的`ProxyFactoryBean Spring2.x Aspectj`註解,最後到了現在廣為熟知的自動代理。 說明: 代理的相關配置類 實現了 ,封裝了對 和`Advisor`的操作 該類及其子類主要是利用 ...
一周排行
    -Advertisement-
    Play Games
  • 1. 說明 /* Performs operations on System.String instances that contain file or directory path information. These operations are performed in a cross-pla ...
  • 視頻地址:【WebApi+Vue3從0到1搭建《許可權管理系統》系列視頻:搭建JWT系統鑒權-嗶哩嗶哩】 https://b23.tv/R6cOcDO qq群:801913255 一、在appsettings.json中設置鑒權屬性 /*jwt鑒權*/ "JwtSetting": { "Issuer" ...
  • 引言 集成測試可在包含應用支持基礎結構(如資料庫、文件系統和網路)的級別上確保應用組件功能正常。 ASP.NET Core 通過將單元測試框架與測試 Web 主機和記憶體中測試伺服器結合使用來支持集成測試。 簡介 集成測試與單元測試相比,能夠在更廣泛的級別上評估應用的組件,確認多個組件一起工作以生成預 ...
  • 在.NET Emit編程中,我們探討了運算操作指令的重要性和應用。這些指令包括各種數學運算、位操作和比較操作,能夠在動態生成的代碼中實現對數據的處理和操作。通過這些指令,開發人員可以靈活地進行算術運算、邏輯運算和比較操作,從而實現各種複雜的演算法和邏輯......本篇之後,將進入第七部分:實戰項目 ...
  • 前言 多表頭表格是一個常見的業務需求,然而WPF中卻沒有預設實現這個功能,得益於WPF強大的控制項模板設計,我們可以通過修改控制項模板的方式自己實現它。 一、需求分析 下圖為一個典型的統計表格,統計1-12月的數據。 此時我們有一個需求,需要將月份按季度劃分,以便能夠直觀地看到季度統計數據,以下為該需求 ...
  • 如何將 ASP.NET Core MVC 項目的視圖分離到另一個項目 在當下這個年代 SPA 已是主流,人們早已忘記了 MVC 以及 Razor 的故事。但是在某些場景下 SSR 還是有意想不到效果。比如某些靜態頁面,比如追求首屏載入速度的時候。最近在項目中回歸傳統效果還是不錯。 有的時候我們希望將 ...
  • System.AggregateException: 發生一個或多個錯誤。 > Microsoft.WebTools.Shared.Exceptions.WebToolsException: 生成失敗。檢查輸出視窗瞭解更多詳細信息。 內部異常堆棧跟蹤的結尾 > (內部異常 #0) Microsoft ...
  • 引言 在上一章節我們實戰了在Asp.Net Core中的項目實戰,這一章節講解一下如何測試Asp.Net Core的中間件。 TestServer 還記得我們在集成測試中提供的TestServer嗎? TestServer 是由 Microsoft.AspNetCore.TestHost 包提供的。 ...
  • 在發現結果為真的WHEN子句時,CASE表達式的真假值判斷會終止,剩餘的WHEN子句會被忽略: CASE WHEN col_1 IN ('a', 'b') THEN '第一' WHEN col_1 IN ('a') THEN '第二' ELSE '其他' END 註意: 統一各分支返回的數據類型. ...
  • 在C#編程世界中,語法的精妙之處往往體現在那些看似微小卻極具影響力的符號與結構之中。其中,“_ =” 這一組合突然出現還真不知道什麼意思。本文將深入剖析“_ =” 的含義、工作原理及其在實際編程中的廣泛應用,揭示其作為C#語法奇兵的重要角色。 一、下劃線 _:神秘的棄元符號 下劃線 _ 在C#中並非 ...