BBS前后端混合项目--01

news/2024/10/22 11:44:17/

总路由

python"># 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),  # 个人站点路由放最后---》上面所有都匹配完了--->再看是不是个人站点
]

总配置

python"># 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'

总模版层

python"># 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-验证码

python"># 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

python">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)

数据库

python"># 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

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

展示

今日思维导图:


http://www.ppmy.cn/news/1439697.html

相关文章

比亚迪唐EV和唐DM-p荣耀版上市,成为新能源汽车市场中的佼佼者!

随着环保理念的深入人心&#xff0c;新能源汽车市场正迎来前所未有的发展机遇。在这个变革的浪潮中&#xff0c;唐EV和唐DM-p荣耀版的上市无疑为市场注入了新的活力。它们凭借先进的技术、卓越的性能以及豪华配置&#xff0c;成为了新能源汽车市场中的佼佼者。然而&#xff0c;…

RK3568 学习笔记 : busybox 制作 ext4最小根文件系统

前言 开发板型号&#xff1a; 【正点原子】 的 RK3568 开发板 AtomPi-CA1 使用 VMware 虚拟机 ubuntu 20.04 编译 busybox&#xff0c;并制作 emmc 中的 ext4 根文件系统 rootfs 下载 busybox 可以在 https://busybox.net/downloads/snapshots/ 下载最新的 busybox&#xff…

C++教学——从入门到精通 11.嵌套循环及数组

上次讲到了循环&#xff0c;这次来讲嵌套循环 如果一个人叫你用C来画一个10*10/2cm^2三角形会么&#xff1f; 这就要用到嵌套循环了 来看看结构&#xff1a; for(变量类型1 变量;条件1;返回值1){语句1;for(变量类型 变量2;条件2;返回值2){语句2;}语句3; } 语句1,2,3是依次…

Flutter笔记:DefaultTextStyle和DefaultTextHeightBehavior解读

Flutter笔记 DefaultTextStyle和DefaultTextHeightBehavior解读 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:htt…

ubuntu通过crontab创建定时任务,并执行sh

1、初始化crontab 执行命令 crontab -e no crontab for username - using an empty one Select an editor. To change later, run select-editor.1. /bin/nano <---- easiest2. /usr/bin/vim.basic3. /usr/bin/vim.tiny4. /bin/ed选择第一项 /bin/nano即可&#x…

(免费分享)基于springboot,vue学生成绩管理系统

(1) 课程信息的管理&#xff0c;包括课程信息的条件查询、录入、修改和删除。 (2) 课程表的管理&#xff0c;包括排课、录入课程表、修改课程表。 (3) 用户信息管理。包括对系统管理员、教师和学生的信息进行维护管理&#xff0c;可以新增、修改、删除和条件分页查询用户信息…

免费开源线上社交交友婚恋系统平台 可打包小程序 支持二开 源码交付!

婚姻是人类社会中最重要的关系之一&#xff0c;它对个人和家庭都有着深远的影响。然而&#xff0c;在现代社会的快节奏生活中&#xff0c;找到真爱变得越来越困难。在这个时候&#xff0c;婚恋产品应运而生&#xff0c;为人们提供了寻找真爱的新途径。 1.拓宽人际交流圈子 现代…

HTTPS和HTTP有什么区别,如何启用HTTPS

HTTP和HTTPS是两个非常重要的概念。它们分别代表了“超文本传输协议”和“安全超文本传输协议”。虽然它们的名字非常相似&#xff0c;但它们之间却存在着一些关键性的区别。本文将详细解析这两种协议的不同之处&#xff0c;并介绍如何申请HTTPS。 HTTP详解 HTTP是一种用于分…