前言
- 本项目前后端进行了分离,前端使用vue实现,并且前端代码已经打包好放在
static
目录下 - 后端使用django的views.py来制作api接口,具体请求接口可以查看
API接口文档.md
环境要求:MySQL 8、python3.11、django4.2、pymysql
如何运行
1、下载本项目到你的电脑后解压
2、附加数据库
将根目录下的 sports_shop.sql
附加到你的mysql中
3、修改数据库连接语句
在sports_shop_backend_war/dao.py
文件中,将登录名和密码修改为你mysql的配置
4、pip安装所需的库
一共有如下两个个:
pip install django==4.2
pip install pymysql
5、运行项目
前端已经写死了请求后端api的基准地址为http://127.0.0.1:8888
因此需要切到 项目根目录
执行如下命令:
shell
python .\manage.py runserver 8888
然后,就可以项目就跑起来了
效果总览
如何入手
- static 文件夹是前端打包过后的代码,具体前端代码可以移步:https://gitee.com/kang-zhenbin/sports_shop_front
- django_shop是项目,sports_shop_backend_war是app。一下讲的都是app
- models.py里面编写了对应数据库表的实体类
- dao.py里面编写了数据库连接方法,已经对应表的增删改查操作
- urls.py和views.py以及service.py 一起完成了api的逻辑
- 其中urls.py是请求的路由分发逻辑
- views.py和service.py完成了api逻辑实现
踩坑记录
2023/4/25
django自带的ORM对mysql进行增删改查很奇怪,会给你的数据库生成一大堆表(似乎帮你搞好了一个后台管理系统)
与spring开发并不相同,没法用实体类对应数据库表的习惯来理解这东西
Template 这东西并不能挂载静态资源
得用static来挂载静态资源,默认访问路径是 ip+端口号/static/xxx
2023/4/26
挂载vue打包后的静态文件,只需在urls.py的urlpatterns中添加一行:
path('', RedirectView.as_view(url='/static/index.html', permanent=False), name='index'),
2023/4/27
python这语言简直是非主流,当你习惯了主流C,Java,JavaScript之类的语言,再来写python,简直要世界观崩塌
关于实体类:
- 1.文件名也算名,并不是文件名与类名一致就可以了。导入的时候要
entity.User.User
是的,第一个是文件名,第二个是类名 - 2.如果你的项目分了多个子目录,比如dao、entity、util。那么你想要在dao中调用entity,你还得用
sys.path.appedn()
去拼接路径 - 3.如果你要调用一个python文件中的类,然后这个文件的类又引用了其他文件的类,你还得改这个文件的类import的路径,去迎合最大的那个调用类。。。。。amazing
- 4.在python中定义一个类 简直就是依托答辩。。。。
2023/4/27
不错不错,逐渐适应了这个语言
django现在暂时只用来挂载我vue打包好的静态页面,默认进入loclahost:8000
的时候,自动路由跳转到localhost:8000/static/index.html
在django_shop项目下,有一个名为sports_shop_backend_war的app
这个app里面目前主要编写的文件夹和文件有
- dao文件夹
- entity文件夹
- test.py
entity里面是实体类
dao里面是一些未来service将要用到的数据库操作
test.py用来测试写好的代码,已经测了各个实体类,还有一些XxxDaoImpl类下的方法
2023/4/28
由于python奇葩的导包机制,比如
shell
¬父级目录∨:
urls.py
views.py
¬dao文件夹∨:
UserDao.py
OrderDao.py
Shopping_cartDao.py
GoodDao.py
CommentDao.py
Mini_Shopping_cartDao.py
¬entity文件夹∨:
User.py
Order.py
Shopping_cart.py
Good.py
Comment.py
Mini_Shopping_cart.py
然后,
我在那些dao操作的类中,引用了entity文件夹里面的实体类
python
from entity.User import User
我在那些service操作的类中,引用了dao文件夹里面的dao数据访问类
python
from dao.UserDao import UserDaoImpl
最后,
我在views.py开始编写后端网络api请求:
python
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
# 服务层
from .service.UserService import UserService
# Create your views here.
def index(request):
return HttpResponse('欢迎测试')
# 登录API
def login(request):
username = request.POST.get('username')
password = request.POST.get('password')
return JsonResponse(UserService().login(username,password))
在urls.py绑定请求路径:
python
# app/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login, name="login")
]
一通操作猛如虎,一开测试凉凉
最后的解决办法只能是:
- 把实体类一股脑粘贴到models.py文件内
- 把dao数据访问类一股脑粘贴到models.py同级的dao.py文件内
这个时候在回来写views.py
,urls.py
作为control
2023/4/29
关于多个类存进字典再转换成JSON数据
python
def login (self,username:str,password:str):
'''通过用户ID查询用户信息
@param 用户名,
@param 密码,
@return {User+Meta} 字典数据'''
user_id = UserDaoImpl().selectByNamePWD(username,password)
data = UserDaoImpl().selectByID(user_id)
meta = Meta("登录成功",200)
response = {
'data': data,
'meta': meta
}
json_str = json.dumps(response, default=lambda o: o.__json__() if isinstance(o, (User, Meta)) else None, ensure_ascii=False)
print(json_str)
return (json_str)
关于获取AJAX发送过来的POST数据
request.POST.GET('XXX')无法使用
先把request.body 用json转换出来,在.get('XXX')也不行
打印request.POST 打印 request.body 啥也没有
翻了大半天资料找不出方法
最后死马当活马医,瞎写用request.GET.GET('XXX')就可以,这就很神奇
python
def login(request):
username = request.GET.get('username')
password = request.GET.get('password')
print(request.body)
# print("=============================")
# concat = request.POST
# postBody = request.body
# print(concat)
# print(type(postBody))
# print(postBody)
# json_result = json.loads(postBody)
# print(json_result)
return HttpResponse(UserService().login(username,password),content_type="application/json")
2023/5/4
如何进行接受上传的文件
使用 request.FILES.get('表单name')
即可获取到上传过来的文件
- 其中
request.FILES.get('表单name').name
可以获取到文件名 request.FILES.get('表单name').read()
可以读取文件的二进制数据流
如何保存到目标目录下
千万别去导入什么 项目名.settings的BASE_DIR
这玩意导进来空空如也
你只需要这样操作
一行获取当前项目的位置
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
再来一行拼接到文件目标位置
upload_path = BASE_DIR + '/static/picture/'+fileName
千万别搞什么os.path.join()来拼接路径,你的BASE_DIR会被吞的
具体实现代码:
python
import os
# 15 上传用户头像 http://127.0.0.1:8888/static/picture/xXxX.jpg
def UserPicture(request):
if request.method == 'POST':
fileName = request.FILES.get('file').name
# 当前脚本的绝对路径
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
upload_path = BASE_DIR + '/static/picture/'+fileName
fileData = request.FILES.get('file').read()
with open(upload_path, "wb+") as f:
f.write(fileData)
# do something else with the image if needed
response = {
'img': "http://127.0.0.1:8888/static/picture/"+fileName
}
json_str = json.dumps(response, default=lambda o: o.__json__() if isinstance(o, (str)) else None, ensure_ascii=False)
return HttpResponse(json_str,content_type="application/json")
```