BBS前后端混合项目--01

2024-04-24 00:20
文章标签 项目 01 混合 bbs

本文主要是介绍BBS前后端混合项目--01,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

总路由

# urls.py
"""BBS1 URL ConfigurationThe `urlpatterns` list routes URLs to views. For more information please see:https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views1. Add an import:  from my_app import views2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views1. Add an import:  from other_app.views import Home2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf1. Import the include() function: from django.urls import include, path2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, re_path
from app01 import views
from django.views.static import serve
from django.conf import settingsurlpatterns = [path('admin/', admin.site.urls),path('register/', views.register),path('check_username/', views.check_username),path('login/', views.login),path('logout/', views.logout),path('get_code/', views.get_code),path('upanddown/', views.upanddown),path('commit/', views.commit),path('backend/', views.backend),path('', views.home),path('change_password/', views.change_password),path('add_article/', views.add_article),path('delete/<int:pk>', views.delete_article),path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT}),re_path('(?P<username>\w+)/(?P<choice>category|tag|archive)/(?P<condition>.*?).html', views.site),path('<str:username>/articles/<int:article_id>.html', views.article_detail),path('<str:username>', views.site),  # 个人站点路由放最后---》上面所有都匹配完了--->再看是不是个人站点
]

总配置

# settings
from pathlib import Path
import osBASE_DIR = Path(__file__).resolve().parent.parentSECRET_KEY = 'django-insecure-s7$a4504xk&4-3zdd^1s50f^_%^_vjj_i-beq=b--r-pw%rptz'DEBUG = TrueALLOWED_HOSTS = []INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','app01.apps.App01Config',
]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 = 'BBS1.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 = 'BBS1.wsgi.application'# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': BASE_DIR / 'db.sqlite3',
#     }
# }
DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'bbs1','USER': 'root','PASSWORD': 'JIAJIA','HOST': '127.0.0.1','PORT': 3306}
}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',},
]# 国际化
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = FalseSTATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'AUTH_USER_MODEL='app01.UserInfo'

总模版层

# views.py
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from .forms import RegisterForm
from .models import UserInfo, Article, Category, Tag, UpAndDown, Commit
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO
from .utills import get_random_code, get_random_rgb
import random, json
from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
from django.contrib.auth.decorators import login_required
from django.db.models import F
from django.db import transaction# Create your views here.def register(request):if request.method == 'GET':form = RegisterForm()return render(request, 'register.html', {'form': form})else:# # 1 数据# print(request.POST)# # 2 文件# print(request.FILES.get('my_img'))# 取出头像avatar = request.FILES.get('my_img')# 校验数据是否合法'''username: adminpassword: 123email: 306334678@qq.comphone: 17717823244avatar:文件'''print(request.POST.get('username'))form = RegisterForm(request.POST)# 使用form校验传入的数据print(form)print(form.is_valid())if form.is_valid():  # 校验通过# 保存data = form.cleaned_data# 把re_password 弹出data.pop('re_password')# 把头像加入if avatar:data['avatar'] = avatarUserInfo.objects.create_user(**data)return JsonResponse({'code': 100, 'msg': '注册成功'})else:return JsonResponse({'code': 101, 'msg': '注册失败', 'errors': form.errors})# 校验用户名是否存在接口
def check_username(request):username = request.GET.get('username')res = UserInfo.objects.filter(username=username).exists()if res:return JsonResponse({'code': 100, 'msg': '用户已经存在'})else:return JsonResponse({'code': 101, 'msg': '您可以注册'})def login(request):if request.method == 'GET':return render(request, 'login.html')else:username = request.POST.get('username')password = request.POST.get('password')net_code = request.POST.get('code').lower()#code = request.POST.get('code').lower()  # 会存在bug# 1 校验验证码,取出老验证码,忽略大小写old_code = request.session.get('code').lower()if code == old_code:# 2 去验证用户了---》# 你们去实现:先根据用户名查出用户,check_password校验密码# UserInfo.objects.filter(username=username,password=password).exists() # 错的user = authenticate(username=username, password=password)if user:# 登录成功--->内部写session了auth_login(request, user)return JsonResponse({'code': 100, 'msg': '登录成功', 'url': '/'})else:return JsonResponse({'code': 101, 'msg': '用户名或密码错误'})else:return JsonResponse({'code': 102, 'msg': '验证码错误'})def logout(request):auth_logout(request)return redirect('/')def home(request):article_list = Article.objects.all().order_by('create_time')return render(request, 'home.html', locals())def get_code(request):height = 38width = 300image_tmp = Image.new('RGB', (300, 38), (255, 255, 255))# 把空图片放在了画板上,就可以写字了draw = ImageDraw.Draw(image_tmp)# 加入字体# img_font = ImageFont.truetype('./static/font/xgdl.ttf', 23)   # 字体,字体大小写img_font = ImageFont.truetype('./static/font/ss.TTF', 23)# 验证码code_str = get_random_code()print(code_str)# 重要,要保存request.session['code'] = code_strfor i, item in enumerate(code_str):draw.text((30 + i * 50, 3), item, fill=get_random_rgb(), font=img_font)  # (x轴,y轴),字,字颜色,字体# 增加难度--->在图片上画点for i in range(30):draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_rgb())# 画弧形x = random.randint(0, width)y = random.randint(0, height)draw.arc((x, y, x + 4, y + 4), 0, 90, fill=get_random_rgb())# 在图片上划线for i in range(3):x1 = random.randint(0, width)x2 = random.randint(0, height)y1 = random.randint(0, width)y2 = random.randint(0, height)draw.line((x1, y1, x2, y2), fill=get_random_rgb())# 放在内存中,一旦不用,自动清理内存my_io = BytesIO()image_tmp.save(my_io, 'png')return HttpResponse(my_io.getvalue())def site(request, username,**kwargs):user = UserInfo.objects.filter(username=username).first()if user:# 查出当前用户,所有的文章article_list = Article.objects.filter(blog_id=user.blog.id).all()choice = kwargs.get('choice', None)condition = kwargs.get('condition', None)  # 如果 choice 有值,condition一定有if choice and choice == 'category':# choice有值 说明不是个人站点的:可能是 tag筛选,标签筛选,日期筛选,并且choice是 category,按标签过滤的category_name = Category.objects.filter(pk=condition).first().namearticle_list = article_list.filter(category_id=condition)elif choice and choice == 'tag':tag_name = Tag.objects.filter(pk=condition).first().namearticle_list = article_list.filter(tag__id=condition)elif choice and choice == 'archive':date_y_m = conditionyear, month = condition.split('-')article_list = article_list.filter(create_time__year=year, create_time__month=month)return render(request, 'site.html', locals())else:return render(request, '404.html')def article_detail(request,username,article_id):article = Article.objects.filter(pk=article_id).first()commit_list = Commit.objects.filter(article_id=article_id)return render(request,'article_detail.html',locals())# 加装饰器的话,无法制定返回给agax的数据,前端不好操作
def upanddown(request):# 当前登录用户,如果取不出来,需要返回让它登录user = request.userif user.is_authenticated:article_id = request.POST.get('article_id')up_or_down = request.POST.get('up')  # 是字符串类型,转成 布尔up_or_down = json.loads(up_or_down)  # ajax传入的是二进制res = UpAndDown.objects.filter(article_id=article_id, user=user).first()if res:return JsonResponse({'code': 102, 'msg': '您已经点过了'})else:# 存点赞点踩记录,记录被点的文章,下次查,若文章在数据库,说明点过了UpAndDown.objects.create(user=user, article_id=article_id, is_up=up_or_down)if up_or_down:Article.objects.filter(pk=article_id).update(up_number=F('up_number') + 1)return JsonResponse({'code': 100, 'msg': '点赞成功'})else:Article.objects.filter(pk=article_id).update(down_number=F('down_number') + 1)return JsonResponse({'code': 100, 'msg': '点踩成功'})else:return JsonResponse({'code': 101, 'msg': '您没有登录,请先 <a href="/login/" style="color: red">登录</a>'})# 评论
def commit(request):user = request.userif user.is_authenticated:article_id = request.POST.get('article_id')content = request.POST.get('content')with transaction.atomic():  # 开启事务dcommit=Commit.objects.create(user=user, article_id=article_id, content=content)# 评论数加一Article.objects.filter(pk=article_id).update(commit_number=F('commit_number')+1)return JsonResponse({'code': '100', 'msg': '评论成功', 'content':commit.content , 'username': user.username})else:return JsonResponse({'code': '101', 'msg': '没有登录'})@login_required(login_url='/login/')
def backend(request):article_list = Article.objects.filter(blog=request.user.blog)return render(request,'backend.html',locals())@login_required(login_url='/login/')
def delete_article(request,pk):Article.objects.filter(pk=pk).delete()return redirect('/backend/')@login_required(login_url='/login/')
def add_article(request):if request.method == 'GET':# 当前作者所有分类category_list = Category.objects.filter(blog=request.user.blog).all()tag_list = Tag.objects.filter(blog=request.user.blog).all()return render(request, 'add_article.html',locals())else:title = request.POST.get('title')content = request.POST.get('content')category = request.POST.get('category')desc = content[0:30]tag = request.POST.getlist('tag')# 加入数据库article = Article.objects.create(title=title, desc=desc, content=content, category_id=category,blog=request.user.blog)article.tag.add(*tag)return redirect('/backend/')

总utils-验证码

# utils.py
import random
# 验证码
def get_random_code():code=''for i in range(5):upper_char = chr(random.randint(65,90))low_char = chr(random.randint(97,122))num_char = str(random.randint(0,9))res=random.choice([upper_char,low_char,num_char])code+=resreturn code# 画布
def get_random_rgb():return (random.randint(0,255),random.randint(0,255),random.randint(0,255))if __name__ == '__main__':print(get_random_code())

admin.py

from django.contrib import admin# Register your models here.from .models import *admin.site.register(UserInfo)
admin.site.register(Blog)
admin.site.register(Tag)
admin.site.register(Category)
admin.site.register(Article)
admin.site.register(ArticleToTag)
admin.site.register(Commit)

总数据库表

# models.py
from django.db import models
from django.contrib.auth.models import AbstractUserclass UserInfo(AbstractUser):# 扩写字段---》手机号,头像,phone = models.CharField(max_length=32, verbose_name='手机号', blank=True, null=True)# /media/avatar/default.png# 必须安装pillow 才能使用 ImageFieldavatar = models.ImageField(upload_to='avatar', default='avatar/default.png')blog = models.OneToOneField(to='Blog', on_delete=models.CASCADE, null=True)class Meta:verbose_name_plural = '用户表'  # 给其他人看,知道这是用户表def __str__(self):return self.usernameclass Blog(models.Model):# 博客标题site_title = models.CharField(max_length=32)# 博客副标题site_name = models.CharField(max_length=32)# 博客样式# 每个人样式不同(文件地址)site_style = models.CharField(max_length=32)class Meta:verbose_name_plural = '博客表'def __str__(self):# 会报错try:return self.userinfo.username + '---' + self.site_titleexcept Exception as e:return self.site_titleclass Tag(models.Model):name = models.CharField(max_length=32)blog = models.ForeignKey(to=Blog, on_delete=models.SET_NULL, null=True)class Meta:verbose_name_plural = '标签表'def __str__(self):return self.nameclass Category(models.Model):name = models.CharField(max_length=32)blog = models.ForeignKey(to=Blog, on_delete=models.SET_NULL, null=True)class Meta:verbose_name_plural = '分类表'def __str__(self):return self.nameclass Article(models.Model):title = models.CharField(max_length=128)# 文章摘要desc = models.CharField(max_length=256, verbose_name='文章摘要')# 文章详情  大文本content = models.TextField()create_time = models.DateTimeField(auto_now_add=True)# 关联字段# 标签和分类up_number = models.IntegerField(default=0)down_number = models.IntegerField(default=0)commit_number = models.IntegerField(default=0)# 关联字段# 标签和分类category = models.ForeignKey(to=Category, on_delete=models.SET_NULL, null=True)# 多对多,手动创建中间表tag = models.ManyToManyField(to=Tag, through='ArticleToTag', through_fields=('article', 'tag'))# 博客blog = models.ForeignKey(to=Blog, on_delete=models.CASCADE)class Meta:verbose_name_plural = '文章表'def __str__(self):return self.titleclass ArticleToTag(models.Model):article = models.ForeignKey(to=Article, on_delete=models.CASCADE)tag = models.ForeignKey(to=Tag, on_delete=models.CASCADE)class Meta:verbose_name_plural = '中间表'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(default=True)create_time = models.DateTimeField(auto_now_add=True)# 联合唯一# unique_together=('user','article')class Meta:verbose_name_plural = '点赞点踩'def __str__(self):return self.is_upclass Commit(models.Model):user = models.ForeignKey(to=UserInfo, on_delete=models.CASCADE)article = models.ForeignKey(to=Article, on_delete=models.CASCADE)content = models.CharField(max_length=256)create_time = models.DateTimeField(auto_now_add=True)# 自关联,评论层级---》子评论   一定要写null=Trueparent_id = models.ForeignKey(to='self', on_delete=models.CASCADE, null=True)class Meta:verbose_name_plural = '评论表'def __str__(self):return self.content

asgi.py

import osfrom django.core.asgi import get_asgi_applicationos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'BBS1.settings')application = get_asgi_application()

展示

今日思维导图:

这篇关于BBS前后端混合项目--01的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/930281

相关文章

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

配置springboot项目动静分离打包分离lib方式

《配置springboot项目动静分离打包分离lib方式》本文介绍了如何将SpringBoot工程中的静态资源和配置文件分离出来,以减少jar包大小,方便修改配置文件,通过在jar包同级目录创建co... 目录前言1、分离配置文件原理2、pom文件配置3、使用package命令打包4、总结前言默认情况下,

python实现简易SSL的项目实践

《python实现简易SSL的项目实践》本文主要介绍了python实现简易SSL的项目实践,包括CA.py、server.py和client.py三个模块,文中通过示例代码介绍的非常详细,对大家的学习... 目录运行环境运行前准备程序实现与流程说明运行截图代码CA.pyclient.pyserver.py参

IDEA运行spring项目时,控制台未出现的解决方案

《IDEA运行spring项目时,控制台未出现的解决方案》文章总结了在使用IDEA运行代码时,控制台未出现的问题和解决方案,问题可能是由于点击图标或重启IDEA后控制台仍未显示,解决方案提供了解决方法... 目录问题分析解决方案总结问题js使用IDEA,点击运行按钮,运行结束,但控制台未出现http://

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下

SpringBoot项目中Maven剔除无用Jar引用的最佳实践

《SpringBoot项目中Maven剔除无用Jar引用的最佳实践》在SpringBoot项目开发中,Maven是最常用的构建工具之一,通过Maven,我们可以轻松地管理项目所需的依赖,而,... 目录1、引言2、Maven 依赖管理的基础概念2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机

Vue项目中Element UI组件未注册的问题原因及解决方法

《Vue项目中ElementUI组件未注册的问题原因及解决方法》在Vue项目中使用ElementUI组件库时,开发者可能会遇到一些常见问题,例如组件未正确注册导致的警告或错误,本文将详细探讨这些问题... 目录引言一、问题背景1.1 错误信息分析1.2 问题原因二、解决方法2.1 全局引入 Element

Python 中 requests 与 aiohttp 在实际项目中的选择策略详解

《Python中requests与aiohttp在实际项目中的选择策略详解》本文主要介绍了Python爬虫开发中常用的两个库requests和aiohttp的使用方法及其区别,通过实际项目案... 目录一、requests 库二、aiohttp 库三、requests 和 aiohttp 的比较四、requ