互动科技 网站建设,珠海 网站建设,wordpress怎么做目录,做心理咨询的网站#x1f31f;所属专栏#xff1a;献给榕榕#x1f414;作者简介#xff1a;rchjr——五带信管菜只因一枚#x1f62e;前言#xff1a;该专栏系为女友准备的#xff0c;里面会不定时发一些讨好她的技术作品#xff0c;感兴趣的小伙伴可以关注一下~#x1f449;文章简介…所属专栏献给榕榕作者简介rchjr——五带信管菜只因一枚前言该专栏系为女友准备的里面会不定时发一些讨好她的技术作品感兴趣的小伙伴可以关注一下~文章简介献给女友的简单网站源代码0 前言与开发环境前言这篇文章把自己今年寒假花了20天做的一个网站放出来。这个网站就是用来练练手感的接下来会重新做一个属于我的个人网站主题还没有想好但是应该是类似于一个个人博客吧。后面做网站时会一直更新进度感兴趣的小伙伴可以关注我了解后续这个送给女朋友的就不详解了直接放置源码可以直接运行当做一个参考。开发环境开发语言python 3.8开发框架Flask开发工具PyCharm专业版虚拟环境工具Anaconda浏览器谷歌浏览器1 运行结果图主页登录界面注册界面照片墙想去的地方挪威留言无法提交浪漫烟花带背景音乐注销2 代码结构一个app文件夹用来存放各个功能忘记术语叫啥了对应上面展示的几个功能。static文件夹存放静态文件具体包括css文件js文件和html文件以及图片和背景音乐。当然还有模型文件models.py存放数据库模型。然后是config.py存放一些要用的配置类manager.py作为主文件用于启动整个项目。3 config.py配置文件先从配置信息开始讲起吧。这个网站我用到的配置信息只有连接MySQL要用的一些相关信息比较简单。# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/1/3 15:08各种配置类class BaseConfig(object):所有配置类的基类SECRET_KEY LOVEDEBUG TrueTESTING FalseVISIT_TIME 0 # 网站访问次数# 数据库配置SQLALCHEMY_DATABASE_URI mysqlpymysql://root:这里换成自己的MySQL密码localhost/personalwebsiteSQLALCHEMY_TRACK_MODIFICATIONS False # 是否追踪数据库的修改class ProductionConfig(BaseConfig):生产环境下的配置类DEBUG Falseclass DevelopmentConfig(BaseConfig):开发模式下的配置类DEBUG TrueTESTING True
然后我是使用的Navicat这个工具用来可视化操作MySQL的。就是下面这个家伙啦可以在网上找到破解版的如果想和我用一样的话这里也有百度网盘的下载链接链接https://pan.baidu.com/s/1WqS8H2fHAwkPm76O-7OClg?pwd9rlv 提取码9rlv --来自百度网盘超级会员V3的分享打开Navicat可以看到我创建了一个名为personalwebsite的数据库双击它可以看到我创建了两个表一个是存放用户登录信息的另一个message本来打算存放留言的但是后面没用到大家可以不用管。4 app包详解这个包里面包含了整个网页代码因此是本次项目的大头我将按照登录注册功能、照片墙功能、我说功能、我想去的地方功能和浪漫烟花功能的顺序进行讲解。另外项目采用蓝图的方式开发每次搞定完一个功能就会在app包下面的__init__.py文件中添加相应的信息。这样方便管理整个项目结构使之整洁、易于修改可扩展性也很好。4.1 登录注册功能登录注册功能在app_login包中里面一共两个文件分别是__init__.py和view.py视图文件。先看__init__.py文件。# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/1/8 23:19登录视图的蓝图
from flask import Blueprintlogin Blueprint(login, __name__)
from . import view在app_login/__init__.py文件中我创建了一个登录视图的蓝图。接下来看登录注册的视图文件首先导入了实现登录要用的一些Flask提供的模块比如login_required, login_user, logout_user。具体功能我就不细讲了。然后导入了跳转网页要用的request, render_template, redirect, url_for, flash还导入了数据库模型User和刚刚创建的蓝图login最后从app包下的__init__.py中导入了管理登录用的login_manager这个等会展示app/__init__.py的时候会看得到。# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/1/6 11:39登录的视图函数
from flask import request, render_template, redirect, url_for, flash
from flask_login import login_required, login_user, logout_user
from . import login
from app.models import User
from app import login_managerlogin_manager.user_loader
def load_user(user_id): # 创建用户加载回调函数接受用户 ID 作为参数user User.query.get(int(user_id)) # 用 ID 作为 User 模型的主键查询对应的用户return user # 返回用户对象login.route(/index, methods[GET, POST])
login_required
def index():return render_template(index.html)login.route(/register, methods[GET, POST])
def register():# 如果请求为postif request.method POST:count request.form.get(count)password request.form.get(password)repassword request.form.get(repassword)from app import dbif password repassword:user User(count, password)user.set_password(password)db.session.add(user)db.session.commit()return redirect(url_for(login.login_))else:flash(两次密码不一致!)return render_template(register.html)return render_template(register.html)login.route(/, methods[GET, POST])
login.route(/login, methods[GET, POST])
def login_():if request.method POST:count request.form[count]password request.form[password]if not count or not password:flash(请输入账号和密码!)return redirect(url_for(login.login_))user User.query.filter_by(countcount).first()if not user:flash(用户不存在)return redirect(url_for(login.login_))if count user.count and user.check_password(password):login_user(user) # 登入用户return redirect(url_for(login.index)) # 重定向到主页flash(账号或密码不正确, 请重新登录!) # 如果验证失败显示错误消息return redirect(url_for(login.login_)) # 重定向回登录页面return render_template(login.html)login.route(/logout, methods[GET,POST])
login_required
def logout():logout_user()return redirect(url_for(login.login_))导入需要的模块和函数后用login_manager作为修饰器管理用户登录具体就是从数据库中查询信息判断是否存在用户可以看其他博客了解详情。然后是分别用对应的修饰器修饰主页、注册页面、登录页面和注销页面。下面给出要用到的前端文件index.html{% extends base.html %}
{% block title %}主页
{% endblock %}{% block div %}
div classwenzi_aimg src../static/images/background_images/照片墙.png styleheight: 50px; width: 50pxspanfont size4 color#000000bnbsp;我们的相册/b/font/spandiv classwenzi_fontfont size3b举目望向天空有说不尽的美好。br/夏天来临之前温暖洒满了一地。br/轻轻翻阅发黄的书卷斑驳往事。br/抓住午后跳跃的阳光锁住流年。br/到底是怎样一种繁华创造了永恒br/夏日的夕阳将天空染成了橘色。br/我们走过的路上落满一地的幸福。br//b/font/div
/div
div classwenzi_bimg src../static/images/background_images/爱心.pngspanfont size4 color#000000b我与你/b/font/spandiv classwenzi_fontfont size3b时光的洪流把每个人的生命印刻成一br/枚枚底片。记忆沿着掌心的脉络聚成br/一幅幅永恒的画面。这些光怪陆离的br/记忆中最令我怀念的就是最美的你br/陪我走过最绚烂的年华。br//b/font/div
/div
div classwenzi_cimg src../static/images/background_images/消息.pngspanfont size4 color#000000b我想说/b/font/spandiv classwenzi_fontfont size3b呯呯的心跳却总能代表我的情意。br/想说爱你其实真的很遥远傍山 br/涉水地追求可能才是我的目的。br/想说爱你只是想真心对待你br/想说爱你只是想真实地表达自己。br//b/font/div
/div
div classwenzi_dimg src../static/images/background_images/走.pngspanfont size4 color#000000bnbsp;emsp;想去的地方/b/font/spandiv classwenzi_fontfont size3b前面以上的文字均来自百度 br/原谅我即时在这种特殊的日子 br/也说不出来一句“像样的”言语。br/我平时已经说的够多了为了 br/让记忆永存我自学了网页语 br/言编写了这个网站。制作过程 br/过程费尽心血和精力但一切 br/都是得的。br//b/font/div
/div
{% endblock %}register.html!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/titlelink relstylesheet typetext/css href../static/css/login.css/script src../static/js/register.js typetext/javascript/script/head
body
div classlogin-boxh2注册/h2p classtip{% for item in get_flashed_messages() %}{{ item }}{% endfor %}/pform action/register methodpostdiv classlogin-fieldspan stylecolor: aqua; size: 12px账号/spaninput typetext namecount required//divdiv classlogin-fieldspqn stylecolor: aqua; size: 12px密码/spqninput typepassword namepassword required//divdiv classlogin-fieldspqn stylecolor: aqua; size: 12px确认密码/spqninput typepassword namerepassword required//divinput typesubmit value提交 idmyloginlabelp stylecolor: rgba(194,108,108,0.58)已有账号a href./login stylecolor: rgba(22,180,166,0.58)onclicktopggleForm();登录/a/p/form
/div
/body
/html
login.html!DOCTYPE html
html
headmeta charsetUTF-8title榕城与佳人/titlelink relstylesheet typetext/css href../static/css/login.css/script src../static/js/register.js typetext/javascript/scriptlink relshortcut icon href../static/images/ico_images/wjr.ico/head
body
div classlogin-boxh2 stylecolor: #ce8483; font-family: 华文彩云榕城佳人/h2p classtip{% for item in get_flashed_messages() %}{{ item }}{% endfor %}/pform action/login methodpostdiv classlogin-fieldspan stylecolor: aqua; size: 12px账号/spaninput typetext namecount required//divdiv classlogin-fieldspqn stylecolor: aqua; size: 12px密码/spqninput typepassword namepassword required//divinput typesubmit value点击进入 idmyloginlabelp stylecolor: rgba(222,112,112,0.58)没有账号a href./register stylecolor: rgba(22,180,166,0.58)onclicktopggleForm();注册/a/p/form
/div
/body
/html当然其他的css文件图片等后面会一并给出。4.2 照片墙功能照片墙功能在app_photo_wall包中里面一共两个文件分别是__init__.py和view.py视图文件。先看__init__.py文件。# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/1/13 16:10照片墙的蓝图
from flask import Blueprintphoto_wall Blueprint(photo_wall, __name__)
from . import view在app_photo_wall/__init__.py文件中我创建了一个照片墙视图的蓝图。接下来看照片墙的视图文件# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/1/13 16:20照片墙的视图函数
from flask import render_template
from flask_login import login_required
from . import photo_wallphoto_wall.route(/photo_wall, methods[GET, POST])
login_required
def index():return render_template(photo_wall.html)照片墙后端很简单主要是靠前端实现的下面给出前端代码photo_wall.html当然大家可以换成自己想换的照片。{% extends base.html %}
{% block title %}照片墙
{% endblock %}{% block div %}div iddiv2div idphoto_boximg src../static/images/photo_wall_images/wjr%20(1).jpgimg src../static/images/photo_wall_images/wjr%20(2).jpgimg src../static/images/photo_wall_images/wjr%20(3).jpgimg src../static/images/photo_wall_images/wjr%20(4).jpgimg src../static/images/photo_wall_images/wjr%20(5).jpgimg src../static/images/photo_wall_images/wjr%20(6).jpgimg src../static/images/photo_wall_images/wjr%20(7).jpgimg src../static/images/photo_wall_images/wjr%20(8).jpgimg src../static/images/photo_wall_images/wjr%20(9).jpgimg src../static/images/photo_wall_images/wjr%20(10).jpgimg src../static/images/photo_wall_images/wjr%20(11).jpgimg src../static/images/photo_wall_images/wjr%20(12).jpgimg src../static/images/photo_wall_images/wjr%20(13).jpgimg src../static/images/photo_wall_images/wjr_%20(1).jpgimg src../static/images/photo_wall_images/wjr_%20(2).jpgimg src../static/images/photo_wall_images/wjr_%20(3).jpgimg src../static/images/photo_wall_images/wjr_%20(4).jpgimg src../static/images/photo_wall_images/wjr_%20(5).jpgimg src../static/images/photo_wall_images/wjr_%20(6).jpgimg src../static/images/photo_wall_images/wjr_%20(7).jpg/div/div
{% endblock %}
4.3 我说功能我说功能在app_isay包中里面一共两个文件分别是__init__.py和view.py视图文件。先看__init__.py文件。# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/1/22 8:52
from flask import Blueprintisay Blueprint(isay, __name__)
from . import view在app_isay/__init__.py文件中我创建了一个我说视图的蓝图。接下来看我说功能的视图文件# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/1/22 8:52我说的视图函数
import time
from . import isay
from flask import request, render_template, session
from flask_login import login_required
from app.models import User, Messageisay.route(/isay, methods[GET, POST])
login_required
def isay():from app import dbif request.method POST:return render_template(isay.html)if request.method POST:title request.form.get(title)text request.form.get(text)count session.get(count)print(count)# 获取当前系统时间created_time time.strftime(%Y-%m-%d %H:%M:%S)user User.query.filter_by(countcount).first()message Message(titletitle, texttext, created_timecreated_time, user_iduser.id)db.session.add(message)db.session.commit()blog Message.query.filter(Message.created_time created_time).first()return render_template(blogSuccess.html, titletitle, idmessage.id)
这个功能其实没开发好大家可以不用管它或者自行完善也行。✈4.4 想去的地方功能想去的地方功能在app_togo包中里面一共两个文件分别是__init__.py和view.py视图文件。先看__init__.py文件。# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/1/23 11:34
from flask import Blueprinttogo Blueprint(togo, __name__)
from . import view在app_togo/__init__.py文件中我创建了一个想去的地方视图的蓝图。接下来看看想去的地方功能的视图文件# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/1/23 11:35想去的地方
from . import togo
from flask import render_templatetogo.route(/togo, methods[POST, GET])
def togo():return render_template(togo.html)
这个功能主要是在前端导入了谷歌地图的API下面给出前端页面togo.html{% extends base.html %}{% block div %}iframe srchttps://www.google.com/maps/embed?pb!1m14!1m12!1m3!1d11329513.820172088!2d14.194477459720666!3d61.318977221270224!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!5e0!3m2!1szh-CN!2s!4v1674447168409!5m2!1szh-CN!2swidth800 height600 classmap allowfullscreen loadinglazyreferrerpolicyno-referrer-when-downgrade/iframe
{% endblock %}4.5 浪漫烟花功能浪漫烟花功能在app_fireflower包中里面一共两个文件分别是__init__.py和view.py视图文件。先看__init__.py文件。# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/2/11 20:48
from flask import Blueprintfireflower Blueprint(fireflower, __name__)
from . import view在app_fireflower/__init__.py文件中我创建了一个浪漫烟花视图的蓝图。接下来看看浪漫烟花功能的视图文件# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/2/11 20:48
from flask import render_template
from flask_login import login_required
from . import fireflowerfireflower.route(/fireflower, methods[GET, POST])
login_required
def index():return render_template(romanticFireFlower.html)
这个功能主要是在前端实现的下面给出前端页面romanticFireFlower.html{% extends base.html %}{% block title %}浪漫烟花
{% endblock %}{% block div %}stylehtml, body {width: 100%;height: 100%;overflow: hidden;background: rgba(15, 23, 22, 0.8);}/style
{# form action/fireflower methodpost/form#}audio autoplayautoplay looploop preloadautosrc../static/music/Because%20of%20You.mp3/audiocanvas idcanvas styleposition:relative;width:1500px;height:800px;z-index:9999;top: 100px/canvascanvas styleposition:absolute;width:100%;height:100%;z-index:9999 classcanvas/canvasdiv classoverlaydiv classtabsdiv classtabs-labelsspan classtabs-labelCommands/spanspan classtabs-labelInfo/spanspanclasstabs-labelShare/span/divdiv classtabs-panelsul classtabs-panel commands/ul/div/div/divscriptfunction initVars() {pi Math.PI;ctx canvas.getContext(2d);canvas.width canvas.clientWidth;canvas.height canvas.clientHeight;cx canvas.width / 2;cy canvas.height / 2;playerZ -25;playerX playerY playerVX playerVY playerVZ pitch yaw pitchV yawV 0;scale 600;seedTimer 0;seedInterval 5, seedLife 100;gravity .02;seeds new Array();sparkPics new Array();s https://cantelope.org/NYE/;for (i 1; i 10; i) {sparkPic new Image();sparkPic.src s spark i .png;sparkPics.push(sparkPic);}sparks new Array();pow1 new Audio(s pow1.ogg);pow2 new Audio(s pow2.ogg);pow3 new Audio(s pow3.ogg);pow4 new Audio(s pow4.ogg);frames 0;}function rasterizePoint(x, y, z) {var p, d;x - playerX;y - playerY;z - playerZ;p Math.atan2(x, z);d Math.sqrt(x * x z * z);x Math.sin(p - yaw) * d;z Math.cos(p - yaw) * d;p Math.atan2(y, z);d Math.sqrt(y * y z * z);y Math.sin(p - pitch) * d;z Math.cos(p - pitch) * d;var rx1 -1000, ry1 1, rx2 1000, ry2 1, rx3 0, ry3 0, rx4 x, ry4 z,uc (ry4 - ry3) * (rx2 - rx1) - (rx4 - rx3) * (ry2 - ry1);if (!uc) return {x: 0, y: 0, d: -1};var ua ((rx4 - rx3) * (ry1 - ry3) - (ry4 - ry3) * (rx1 - rx3)) / uc;var ub ((rx2 - rx1) * (ry1 - ry3) - (ry2 - ry1) * (rx1 - rx3)) / uc;if (!z) z .000000001;if (ua 0 ua 1 ub 0 ub 1) {return {x: cx (rx1 ua * (rx2 - rx1)) * scale,y: cy y / z * scale,d: Math.sqrt(x * x y * y z * z)};} else {return {x: cx (rx1 ua * (rx2 - rx1)) * scale,y: cy y / z * scale,d: -1};}}function spawnSeed() {seed new Object();seed.x -50 Math.random() * 100;seed.y 25;seed.z -50 Math.random() * 100;seed.vx .1 - Math.random() * .2;seed.vy -1.5;//*(1Math.random()/2);seed.vz .1 - Math.random() * .2;seed.born frames;seeds.push(seed);}function splode(x, y, z) {t 5 parseInt(Math.random() * 150);sparkV 1 Math.random() * 2.5;type parseInt(Math.random() * 3);switch (type) {case 0:pic1 parseInt(Math.random() * 10);break;case 1:pic1 parseInt(Math.random() * 10);do {pic2 parseInt(Math.random() * 10);} while (pic2 pic1);break;case 2:pic1 parseInt(Math.random() * 10);do {pic2 parseInt(Math.random() * 10);} while (pic2 pic1);do {pic3 parseInt(Math.random() * 10);} while (pic3 pic1 || pic3 pic2);break;}for (m 1; m t; m) {spark new Object();spark.x x;spark.y y;spark.z z;p1 pi * 2 * Math.random();p2 pi * Math.random();v sparkV * (1 Math.random() / 6)spark.vx Math.sin(p1) * Math.sin(p2) * v;spark.vz Math.cos(p1) * Math.sin(p2) * v;spark.vy Math.cos(p2) * v;switch (type) {case 0:spark.img sparkPics[pic1];break;case 1:spark.img sparkPics[parseInt(Math.random() * 2) ? pic1 : pic2];break;case 2:switch (parseInt(Math.random() * 3)) {case 0:spark.img sparkPics[pic1];break;case 1:spark.img sparkPics[pic2];break;case 2:spark.img sparkPics[pic3];break;}break;}spark.radius 25 Math.random() * 50;spark.alpha 1;spark.trail new Array();sparks.push(spark);}switch (parseInt(Math.random() * 4)) {case 0:pow new Audio(s pow1.ogg);break;case 1:pow new Audio(s pow2.ogg);break;case 2:pow new Audio(s pow3.ogg);break;case 3:pow new Audio(s pow4.ogg);break;}d Math.sqrt((x - playerX) * (x - playerX) (y - playerY) * (y - playerY) (z - playerZ) * (z - playerZ));pow.volume 1.5 / (1 d / 10);pow.play();}function doLogic() {if (seedTimer frames) {seedTimer frames seedInterval * Math.random() * 10;spawnSeed();}for (i 0; i seeds.length; i) {seeds[i].vy gravity;seeds[i].x seeds[i].vx;seeds[i].y seeds[i].vy;seeds[i].z seeds[i].vz;if (frames - seeds[i].born seedLife) {splode(seeds[i].x, seeds[i].y, seeds[i].z);seeds.splice(i, 1);}}for (i 0; i sparks.length; i) {if (sparks[i].alpha 0 sparks[i].radius 5) {sparks[i].alpha - .01;sparks[i].radius / 1.02;sparks[i].vy gravity;point new Object();point.x sparks[i].x;point.y sparks[i].y;point.z sparks[i].z;if (sparks[i].trail.length) {x sparks[i].trail[sparks[i].trail.length - 1].x;y sparks[i].trail[sparks[i].trail.length - 1].y;z sparks[i].trail[sparks[i].trail.length - 1].z;d ((point.x - x) * (point.x - x) (point.y - y) * (point.y - y) (point.z - z) * (point.z - z));if (d 9) {sparks[i].trail.push(point);}} else {sparks[i].trail.push(point);}if (sparks[i].trail.length 5) sparks[i].trail.splice(0, 1);sparks[i].x sparks[i].vx;sparks[i].y sparks[i].vy;sparks[i].z sparks[i].vz;sparks[i].vx / 1.075;sparks[i].vy / 1.075;sparks[i].vz / 1.075;} else {sparks.splice(i, 1);}}p Math.atan2(playerX, playerZ);d Math.sqrt(playerX * playerX playerZ * playerZ);d Math.sin(frames / 80) / 1.25;t Math.sin(frames / 200) / 40;playerX Math.sin(p t) * d;playerZ Math.cos(p t) * d;yaw pi p t;}function rgb(col) {var r parseInt((.5 Math.sin(col) * .5) * 16);var g parseInt((.5 Math.cos(col) * .5) * 16);var b parseInt((.5 - Math.sin(col) * .5) * 16);return # r.toString(16) g.toString(16) b.toString(16);}function draw() {ctx.clearRect(0, 0, cx * 2, cy * 2);ctx.fillStyle #ff8;for (i -100; i 100; i 3) {for (j -100; j 100; j 4) {x i;z j;y 25;point rasterizePoint(x, y, z);if (point.d ! -1) {size 250 / (1 point.d);d Math.sqrt(x * x z * z);a 0.75 - Math.pow(d / 100, 6) * 0.75;if (a 0) {ctx.globalAlpha a;ctx.fillRect(point.x - size / 2, point.y - size / 2, size, size);}}}}ctx.globalAlpha 1;for (i 0; i seeds.length; i) {point rasterizePoint(seeds[i].x, seeds[i].y, seeds[i].z);if (point.d ! -1) {size 200 / (1 point.d);ctx.fillRect(point.x - size / 2, point.y - size / 2, size, size);}}point1 new Object();for (i 0; i sparks.length; i) {point rasterizePoint(sparks[i].x, sparks[i].y, sparks[i].z);if (point.d ! -1) {size sparks[i].radius * 200 / (1 point.d);if (sparks[i].alpha 0) sparks[i].alpha 0;if (sparks[i].trail.length) {point1.x point.x;point1.y point.y;switch (sparks[i].img) {case sparkPics[0]:ctx.strokeStyle #f84;break;case sparkPics[1]:ctx.strokeStyle #84f;break;case sparkPics[2]:ctx.strokeStyle #8ff;break;case sparkPics[3]:ctx.strokeStyle #fff;break;case sparkPics[4]:ctx.strokeStyle #4f8;break;case sparkPics[5]:ctx.strokeStyle #f44;break;case sparkPics[6]:ctx.strokeStyle #f84;break;case sparkPics[7]:ctx.strokeStyle #84f;break;case sparkPics[8]:ctx.strokeStyle #fff;break;case sparkPics[9]:ctx.strokeStyle #44f;break;}for (j sparks[i].trail.length - 1; j 0; --j) {point2 rasterizePoint(sparks[i].trail[j].x, sparks[i].trail[j].y, sparks[i].trail[j].z);if (point2.d ! -1) {ctx.globalAlpha j / sparks[i].trail.length * sparks[i].alpha / 2;ctx.beginPath();ctx.moveTo(point1.x, point1.y);ctx.lineWidth 1 sparks[i].radius * 10 / (sparks[i].trail.length - j) / (1 point2.d);ctx.lineTo(point2.x, point2.y);ctx.stroke();point1.x point2.x;point1.y point2.y;}}}ctx.globalAlpha sparks[i].alpha;ctx.drawImage(sparks[i].img, point.x - size / 2, point.y - size / 2, size, size);}}}function frame() {if (frames 100000) {seedTimer 0;frames 0;}frames;draw();doLogic();requestAnimationFrame(frame);}window.addEventListener(resize, () {canvas.width canvas.clientWidth;canvas.height canvas.clientHeight;cx canvas.width / 2;cy canvas.height / 2;});initVars();frame();/script{% endblock %}4.6 models.py模型文件这里创建了User和Message数据库模型也就是对应数据库里的两张表。其中第一个模型和登录也是有关联的都是Flask自带的模块。# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/1/4 20:00登录需要的数据库模型用户表
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
from app import dbclass User(UserMixin, db.Model):# 第一个参数指定字段类型后面设置属性__tablename__ usersid db.Column(db.Integer, primary_keyTrue, autoincrementTrue)count db.Column(db.String(128), nullableFalse, uniqueTrue)password db.Column(db.String(128), nullableFalse)def __init__(self, count, password):self.count countself.password passworddef set_password(self, password):self.password generate_password_hash(password)def check_password(self, password):return check_password_hash(self.password, password)class Message(db.Model):__tablename__ messagesid db.Column(db.Integer, primary_keyTrue, autoincrementTrue)title db.Column(db.String(128))text db.Column(db.TEXT)created_time db.Column(db.String(64))# 关联用户iduser_id db.Column(db.Integer, db.ForeignKey(users.id))user db.relationship(User, backrefuser)if __name__ __main__:user User(count0101, password2021)db.session.add(user)db.session.commit()
4.7 __init__.py文件这里完成对整个项目的蓝图的注册配置信息和初始化数据库。# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/1/3 1:54构建app注册蓝图from flask import Flask
from config import BaseConfig
from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemylogin_manager LoginManager()
login_manager.session_protection strong
login_manager.login_view login
db SQLAlchemy()def register_bp(app):注册蓝图:param app::return:from .app_login import login as login_blueprintfrom .app_photo_wall import photo_wall as photo_wall_blueprintfrom .app_isay import isay as isay_blueprintfrom .app_togo import togo as togo_blueprintfrom .app_fireflower import fireflower as fireflower_blueprintapp.register_blueprint(login_blueprint)app.register_blueprint(photo_wall_blueprint)app.register_blueprint(isay_blueprint)app.register_blueprint(togo_blueprint)app.register_blueprint(fireflower_blueprint)def database(app, db):初始化数据库:param app::return:db.init_app(app)db.create_all()db.session.commit()def create_app():my_app Flask(__name__)with my_app.app_context():# app注册蓝图register_bp(my_app)# app加载配置my_app.config.from_object(BaseConfig)# 数据库管理对象database(my_app, db)# 用于登录验证login_manager.init_app(my_app)login_manager.login_view login.loginreturn my_app
5 manager.py 启动项目从app/__init__.py导入create()函数用于启动同时设置了错误页面。# coding: utf-8
# 作者(Author): Messimeimei
# 创建时间(Created_time): 2023/1/3 13:50启动文件
from app import create_app
from flask import render_template, sessionapp create_app()# 404页面
app.errorhandler(404)
def page_not_found(e):return render_template(error.html), 404# 500页面
app.errorhandler(500)
def internal_server_error(e):return render_template(error.html), 500if __name__ __main__:app.run(debugTrue)
6 一些静态文件下面是要用到的所有静态文件篇幅原因这里就不全部放出来了有需要的朋友在评论区扣1我会及时给的。背景图片和照片墙大家可以自己选。