ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

基于Django+MySQL的校园二手交易平台全栈开发实战

基于Django+MySQL的校园二手交易平台全栈开发实战 简介这是一套面向计算机相关专业本科生的毕业设计级校园二手交易平台基于PythonDjangoMySQL实现C2C模式交易功能解决大学生校内闲置物品高效流转与信息互通的实际需求适用于毕设、课程设计或入门级Web开发学习。资源包共198个文件含37个核心Python后端逻辑文件、21个HTML前端模板、28个PNG/JPEG商品图片及51张界面截图、13个CSS样式文件如bootstrap.min.css、user_center.css等和7个JS交互脚本整体压缩后仅5.06MB结构清晰、模块完整。已有792人下载学习代码经实机测试运行无误答辩平均分达96分提供完整数据库初始化SQL、管理员与普通用户双账号、详细部署说明及多角色功能闭环游客浏览/会员发布/管理员审核开箱即用亦支持二次开发与功能拓展。1. 项目缘起与核心价值最近在整理硬盘翻到了几年前带学生做的一个毕业设计项目——一个基于PythonDjangoMySQL的校园二手交易平台。当时这个项目反响不错很多同学照着做也顺利通过了答辩。今天重新梳理一下把整个项目的设计思路、技术选型、核心实现以及那些年踩过的坑都完整地分享出来。如果你正在寻找一个结构清晰、功能完整、能跑起来的Django实战项目来练手或者需要一个有文档、有源码的毕业设计参考那这篇内容应该能帮到你。校园二手交易市场本质上是一个垂直领域的C2C电商平台。它的核心价值在于解决信息不对称和信任问题。在校园这个半封闭的环境里学生有大量的闲置物品教材、电子产品、生活用品需要流转但传统的贴吧、QQ群信息杂乱、难以检索、交易缺乏保障。一个专属的平台能提供商品发布、搜索、沟通、交易哪怕是线下的完整链路让“断舍离”和“淘好货”都变得更高效、更安全。用Django来实现它是一个绝佳的选择因为它“自带电池”能让我们快速搭建起一个具备用户认证、后台管理、数据模型等核心功能的Web应用把精力更多地聚焦在业务逻辑本身。2. 技术栈选型背后的逻辑为什么是PythonDjangoMySQL看到这个技术组合你可能会觉得“老生常谈”但每个选择背后都有其坚实的理由。我们先拆开来看。2.1 Python快速原型与生态优势选择Python作为后端语言首要原因是其极低的入门门槛和强大的表达力。对于校园项目或快速验证想法的场景Python能让开发者尤其是学生快速将想法转化为可运行的代码而不必在复杂的语法和内存管理上耗费过多精力。其次Python拥有庞大而活跃的社区这意味着当你遇到任何问题——从Django的ORM查询到图片处理——几乎都能在Stack Overflow或相关文档中找到成熟的解决方案。最后Python在数据爬虫、自动化脚本、机器学习等领域也有广泛应用为项目未来的功能扩展比如基于用户行为的简单商品推荐预留了可能性。2.2 Django为“快速开发健壮应用”而生Django是一个“重量级”的全栈Web框架它奉行“约定优于配置”的原则。对于校园二手交易平台这类典型的CRUD增删改查应用Django的优势是碾压性的自带ORM用Python类定义数据模型Django自动生成数据库表无需手写SQL复杂查询除外极大提升了开发效率和数据安全性。自带Admin后台几行代码就能生成功能强大的内容管理后台方便项目演示和初期数据管理。对于二手平台管理员可以轻松审核商品、管理用户。完整的MVT架构清晰的分层Model模型, View视图, Template模板让代码结构一目了然便于团队协作和后期维护。强大的安全机制默认提供了CSRF防护、SQL注入防护、XSS防护等对于新手开发者而言这相当于上了一道重要的安全保险。丰富的第三方包比如django-crispy-forms用于美化表单Pillow用于处理图片上传生态完善。2.3 MySQL成熟稳定的关系型数据库为什么不用SQLiteDjango默认或者PostgreSQL对于这个项目MySQL是一个平衡了性能、可靠性和学习成本的选择。成熟与普及MySQL是世界上最流行的开源关系数据库之一教程、问题解决方案海量遇到任何坑都容易找到答案。性能足够校园二手平台的并发量和数据量在项目初期乃至中期MySQL都能轻松应对。其索引优化、查询缓存等机制非常成熟。与Django配合良好Django官方对MySQL的支持非常完善配置简单。使用mysqlclient或pymysql驱动即可轻松连接。事务支持虽然我们这个版本的交易流程可能不涉及在线支付多为线下交易但数据库层面的事务支持是构建可靠应用的基础MySQL完全满足。这个技术栈组合形成了一个从快速开发到稳定部署的完整闭环特别适合作为学习全栈开发或完成课程设计的实战项目。3. 核心功能模块设计与数据模型构建一个二手交易平台最核心的实体就是用户、商品和交易或沟通。围绕它们我们设计出以下核心功能模块并用Django的Model来具象化。3.1 用户模块 (User Profile)Django自带了强大的django.contrib.auth用户认证系统但我们通常需要扩展它添加手机号、头像、校区等校园场景特有字段。# models.py from django.contrib.auth.models import User from django.db import models class UserProfile(models.Model): # 与Django内置User模型一对一关联 user models.OneToOneField(User, on_deletemodels.CASCADE, related_nameprofile) # 校园信息 campus models.CharField(max_length50, verbose_name校区) student_id models.CharField(max_length20, blankTrue, verbose_name学号) phone_number models.CharField(max_length15, verbose_name手机号) # 信誉与头像 avatar models.ImageField(upload_toavatars/, defaultavatars/default.png, verbose_name头像) credit_score models.IntegerField(default100, verbose_name信用分) # 简单模拟信用体系 def __str__(self): return self.user.username注意ImageField需要安装Pillow库 (pip install Pillow)。upload_to参数指定了图片上传到media/avatars/目录下记得在settings.py中配置MEDIA_URL和MEDIA_ROOT。3.2 商品模块 (Product)这是系统的核心。一个商品需要包含丰富的信息并处理好状态流转如上架、下架、已售出。# models.py class Product(models.Model): STATUS_CHOICES ( (available, 可购买), (pending, 交易中), (sold, 已售出), (offline, 已下架), ) CATEGORY_CHOICES ( (book, 教材图书), (digital, 数码产品), (daily, 生活日用), (other, 其他), ) seller models.ForeignKey(User, on_deletemodels.CASCADE, related_nameselling_products, verbose_name卖家) title models.CharField(max_length200, verbose_name商品标题) description models.TextField(verbose_name商品描述) category models.CharField(max_length20, choicesCATEGORY_CHOICES, verbose_name分类) price models.DecimalField(max_digits10, decimal_places2, verbose_name价格) original_price models.DecimalField(max_digits10, decimal_places2, nullTrue, blankTrue, verbose_name原价) main_image models.ImageField(upload_toproducts/%Y/%m/%d/, verbose_name主图) # 多图存储可以采用另一个模型关联这里简化处理用JSONField或逗号分隔的CharField images_extra models.TextField(blankTrue, verbose_name额外图片(JSON)) # 实际可用ArrayField(PostgreSQL)或另建表 status models.CharField(max_length20, choicesSTATUS_CHOICES, defaultavailable, verbose_name状态) campus models.CharField(max_length50, verbose_name所在校区) # 冗余存储避免频繁联表查询 view_count models.PositiveIntegerField(default0, verbose_name浏览量) created_at models.DateTimeField(auto_now_addTrue, verbose_name创建时间) updated_at models.DateTimeField(auto_nowTrue, verbose_name更新时间) class Meta: ordering [-created_at] # 默认按发布时间倒序排列 def __str__(self): return self.title设计思考分类字段使用choices选项既保证了数据一致性又方便前端渲染下拉框。价格字段使用DecimalField而非FloatField这是金融或交易相关数据的铁律避免浮点数精度问题。校区冗余在Product中存储campus虽然与卖家的UserProfile.campus可能重复但在商品列表页过滤和展示时无需联表查询User和UserProfile用空间换时间提升了查询性能。状态机status字段定义了商品的完整生命周期任何改变商品状态的业务操作如买家点击“我想要”、卖家点击“已售出”都必须严谨地更新此字段。3.3 商品图片的优化处理上述模型中的images_extra字段处理多图比较粗糙。更优的做法是建立独立的图片模型并与商品建立外键关联。# models.py class ProductImage(models.Model): product models.ForeignKey(Product, on_deletemodels.CASCADE, related_nameimages) image models.ImageField(upload_toproducts/details/%Y/%m/%d/) is_main models.BooleanField(defaultFalse, verbose_name是否为主图) order models.IntegerField(default0, verbose_name排序) class Meta: ordering [order]这样一个商品可以对应多个ProductImage通过is_main标识主图通过order控制展示顺序管理起来更加灵活和规范。3.4 沟通与收藏模块交易始于沟通。我们需要一个让买家和卖家就某个商品发起对话的功能。# models.py class Conversation(models.Model): product models.ForeignKey(Product, on_deletemodels.CASCADE, related_nameconversations) participants models.ManyToManyField(User, related_nameconversations) created_at models.DateTimeField(auto_now_addTrue) updated_at models.DateTimeField(auto_nowTrue) class Message(models.Model): conversation models.ForeignKey(Conversation, on_deletemodels.CASCADE, related_namemessages) sender models.ForeignKey(User, on_deletemodels.CASCADE, related_namesent_messages) content models.TextField() timestamp models.DateTimeField(auto_now_addTrue) class Meta: ordering [timestamp]同时用户收藏商品的功能也很重要。# models.py class Favorite(models.Model): user models.ForeignKey(User, on_deletemodels.CASCADE, related_namefavorites) product models.ForeignKey(Product, on_deletemodels.CASCADE, related_namefavorited_by) created_at models.DateTimeField(auto_now_addTrue) class Meta: unique_together [user, product] # 防止重复收藏至此我们完成了最核心的数据模型设计。运行python manage.py makemigrations和python manage.py migrateDjango便会自动在MySQL数据库中创建对应的表。4. 视图与模板将数据转化为用户界面数据模型是骨架视图View和模板Template则是血肉负责处理业务逻辑和呈现页面。我们采用Django经典的基于函数的视图FBV或基于类的视图CBV来构建。4.1 商品列表页过滤、搜索与分页这是用户访问最频繁的页面。核心需求是按分类、校区、价格排序、关键词进行过滤并分页展示。# views.py from django.core.paginator import Paginator from django.shortcuts import render from .models import Product, CATEGORY_CHOICES from django.db.models import Q def product_list(request): # 获取查询参数 category request.GET.get(category, ) campus request.GET.get(campus, ) query request.GET.get(q, ) sort_by request.GET.get(sort, -created_at) # 默认按最新排序 # 构建查询集 products Product.objects.filter(statusavailable) # 只展示可购买的商品 if category: products products.filter(categorycategory) if campus: products products.filter(campuscampus) if query: # 在标题和描述中搜索关键词 products products.filter(Q(title__icontainsquery) | Q(description__icontainsquery)) # 排序 valid_sorts [price, -price, -created_at, view_count] if sort_by in valid_sorts: products products.order_by(sort_by) # 分页 paginator Paginator(products, 12) # 每页12个 page_number request.GET.get(page) page_obj paginator.get_page(page_number) context { page_obj: page_obj, categories: CATEGORY_CHOICES, selected_category: category, selected_campus: campus, query: query, sort_by: sort_by, } return render(request, market/product_list.html, context)在模板product_list.html中我们需要渲染page_obj并生成带有查询参数的分页链接这是一个关键细节。!-- 示例分页控件 -- nav aria-labelPage navigation ul classpagination {% if page_obj.has_previous %} li classpage-item a classpage-link href?page{{ page_obj.previous_page_number }}{% for key, value in request.GET.items %}{% if key ! page %}{{ key }}{{ value }}{% endif %}{% endfor %}上一页/a /li {% endif %} {% for num in page_obj.paginator.page_range %} {% if page_obj.number num %} li classpage-item activespan classpage-link{{ num }}/span/li {% else %} li classpage-itema classpage-link href?page{{ num }}{% for key, value in request.GET.items %}{% if key ! page %}{{ key }}{{ value }}{% endif %}{% endfor %}{{ num }}/a/li {% endif %} {% endfor %} {% if page_obj.has_next %} li classpage-item a classpage-link href?page{{ page_obj.next_page_number }}{% for key, value in request.GET.items %}{% if key ! page %}{{ key }}{{ value }}{% endif %}{% endfor %}下一页/a /li {% endif %} /ul /nav实操心得分页时保留原有的搜索过滤条件是一个易错点。上面的模板代码通过循环request.GET字典排除了page参数将其它所有参数重新拼接回URL确保了翻页时不会丢失筛选状态。这是提升用户体验的重要细节。4.2 商品详情页与状态管理详情页需要展示商品所有信息、卖家信息并提供“联系卖家”、“收藏”、“立即购买”线下等操作入口。对于卖家则需提供“编辑商品”、“下架商品”、“标记为已售出”等管理入口。这里的关键是权限控制确保只有商品所有者才能执行管理操作。# views.py from django.contrib.auth.decorators import login_required from django.http import HttpResponseForbidden from django.shortcuts import get_object_or_404, redirect login_required def product_detail(request, pk): product get_object_or_404(Product, pkpk) # 增加浏览量简单处理存在并发问题生产环境需用更严谨方式 product.view_count 1 product.save(update_fields[view_count]) # 检查当前用户是否为卖家 is_owner request.user product.seller # 检查是否已收藏 is_favorited False if request.user.is_authenticated: is_favorited Favorite.objects.filter(userrequest.user, productproduct).exists() context { product: product, is_owner: is_owner, is_favorited: is_favorited, } return render(request, market/product_detail.html, context) login_required def mark_as_sold(request, pk): product get_object_or_404(Product, pkpk) # 权限校验必须是商品所有者 if request.user ! product.seller: return HttpResponseForbidden(你没有权限执行此操作。) # 状态变更 product.status sold product.save(update_fields[status]) # 可以在这里添加通知买家的逻辑如果需要 return redirect(product_detail, pkpk)在模板中通过判断is_owner来动态显示管理按钮。{% if is_owner %} div classbtn-group rolegroup a href{% url product_edit product.id %} classbtn btn-outline-primary编辑/a a href{% url product_offline product.id %} classbtn btn-outline-warning下架/a form action{% url mark_as_sold product.id %} methodpost styledisplay: inline; {% csrf_token %} button typesubmit classbtn btn-outline-success标记为已售出/button /form /div {% else %} !-- 显示买家操作按钮 -- {% endif %}4.3 表单处理发布商品与用户注册处理表单是Web开发的基础。Django提供了forms.Form和forms.ModelForm来简化这一过程。以发布商品为例我们使用ModelForm。# forms.py from django import forms from .models import Product class ProductForm(forms.ModelForm): class Meta: model Product fields [title, category, price, original_price, campus, main_image, description] widgets { description: forms.Textarea(attrs{rows: 4}), } # 可以在这里添加自定义验证逻辑 def clean_price(self): price self.cleaned_data.get(price) if price and price 0: raise forms.ValidationError(价格必须大于0。) return price在视图中处理表单提交# views.py from django.contrib.auth.decorators import login_required from .forms import ProductForm login_required def product_create(request): if request.method POST: form ProductForm(request.POST, request.FILES) # 注意处理文件上传 if form.is_valid(): product form.save(commitFalse) product.seller request.user # 关联当前用户为卖家 product.status available product.save() # 这里可以处理多图上传如果使用ProductImage模型 return redirect(product_detail, pkproduct.pk) else: form ProductForm() return render(request, market/product_form.html, {form: form})踩坑记录处理图片或文件上传时视图函数中实例化ModelForm必须传入request.FILES即form ProductForm(request.POST, request.FILES)否则文件数据不会被接收。同时确保HTML表单的enctype属性设置为multipart/form-data。5. 项目部署与上线前关键配置开发完成在本地跑通只是第一步。要让其他同学也能访问就需要部署。这里我们讨论使用Nginx Gunicorn MySQL的经典Linux部署方案并指出几个关键配置点。5.1 生产环境设置 (settings.py)首先必须区分开发和生产配置。一个常见的做法是创建settings目录内含base.py,development.py,production.py。# settings/production.py from .base import * DEBUG False # 必须关闭调试模式 ALLOWED_HOSTS [your_domain.com, your_server_ip] # 必须设置允许的主机 # 静态文件配置 STATIC_URL /static/ STATIC_ROOT os.path.join(BASE_DIR, staticfiles) # 执行collectstatic后文件收集的目录 STATICFILES_DIRS [os.path.join(BASE_DIR, static)] # 开发时的静态文件目录 # 媒体文件配置 MEDIA_URL /media/ MEDIA_ROOT os.path.join(BASE_DIR, media) # 数据库配置生产环境务必使用强密码 DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: campus_market_prod, USER: market_user, PASSWORD: your_strong_password_here, # 使用环境变量更安全 HOST: localhost, PORT: 3306, } } # 安全相关配置 SECRET_KEY os.environ.get(DJANGO_SECRET_KEY) # 从环境变量读取不要硬编码 SESSION_COOKIE_SECURE True # 仅HTTPS传输Cookie CSRF_COOKIE_SECURE True # 仅HTTPS传输CSRF Token SECURE_BROWSER_XSS_FILTER True SECURE_CONTENT_TYPE_NOSNIFF True X_FRAME_OPTIONS DENY关键点DEBUGFalse这是铁律。开启调试模式会暴露敏感信息。ALLOWED_HOSTS必须正确配置否则Django会拒绝服务。SECRET_KEY绝对不要提交到版本库。使用环境变量管理。静态文件Django在生产环境不直接服务静态文件。需要配置Nginx来服务STATIC_ROOT和MEDIA_ROOT。5.2 使用Gunicorn作为WSGI服务器Django自带的开发服务器性能低下且不安全仅用于开发。生产环境使用Gunicorn。pip install gunicorn # 在项目根目录创建一个gunicorn配置文件 gunicorn_config.py bind 0.0.0.0:8000 # 监听所有IP的8000端口 workers 3 # 工作进程数通常为CPU核心数*21 worker_class sync # 同步worker对于I/O密集型也可用gevent timeout 120 accesslog ./logs/gunicorn_access.log errorlog ./logs/gunicorn_error.log capture_output True启动命令gunicorn -c gunicorn_config.py your_project.wsgi:application5.3 使用Nginx作为反向代理和静态文件服务器Nginx负责接收外部请求将动态请求转发给Gunicorn并直接处理静态文件请求效率更高。# /etc/nginx/sites-available/campus_market server { listen 80; server_name your_domain.com your_server_ip; location /static/ { alias /path/to/your/project/staticfiles/; # 指向STATIC_ROOT expires 30d; access_log off; } location /media/ { alias /path/to/your/project/media/; # 指向MEDIA_ROOT expires 30d; access_log off; } location / { proxy_pass http://127.0.0.1:8000; # 转发给Gunicorn proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 75s; proxy_read_timeout 300s; } }配置完成后创建软链接到sites-enabled并重启Nginxsudo systemctl restart nginx。5.4 使用Supervisor管理进程为了防止Gunicorn进程意外退出使用Supervisor来守护进程。; /etc/supervisor/conf.d/campus_market.conf [program:campus_market] command/path/to/your/venv/bin/gunicorn -c /path/to/your/project/gunicorn_config.py your_project.wsgi:application directory/path/to/your/project userwww-data autostarttrue autorestarttrue redirect_stderrtrue stdout_logfile/path/to/your/project/logs/supervisor.log然后更新并启动sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start campus_market。6. 开发与部署中的常见“坑”与解决方案在实际开发和部署过程中总会遇到一些预料之外的问题。这里分享几个高频“坑点”。6.1 静态文件404部署后CSS/JS/图片不显示这是Django新手部署时几乎百分百会遇到的问题。症状页面能打开但样式全无浏览器控制台显示静态文件404。原因Django在生产模式(DEBUGFalse)下不负责服务静态文件。你配置了STATIC_ROOT但Nginx没有正确指向它或者没有执行collectstatic命令。解决方案确保在settings.py中正确设置了STATIC_ROOT和STATIC_URL。运行python manage.py collectstatic将所有app的静态文件收集到STATIC_ROOT目录。检查Nginx配置中location /static/的alias路径是否绝对正确并指向STATIC_ROOT。确保Nginx进程对静态文件目录有读取权限例如sudo chmod -R 755 /path/to/staticfiles。重启Nginxsudo systemctl restart nginx。6.2 MySQL连接错误django.db.utils.OperationalError: (2003, “Can‘t connect to MySQL server”)原因1MySQL服务未启动。sudo systemctl status mysql检查状态sudo systemctl start mysql启动。原因2Django配置的数据库用户没有远程登录权限如果你用的是本地localhost则不是此问题。MySQL默认只允许root用户从本地连接。解决方案创建专用用户并授权-- 登录MySQL: mysql -u root -p CREATE DATABASE campus_market_prod CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER market_userlocalhost IDENTIFIED BY your_strong_password; GRANT ALL PRIVILEGES ON campus_market_prod.* TO market_userlocalhost; FLUSH PRIVILEGES;确保settings.py中的HOST是localhost用户密码与创建的一致。6.3 图片上传后无法访问403 Forbidden症状用户上传的头像或商品图片在详情页显示为破损图标浏览器检查网络请求返回403。原因Web服务器Nginx对媒体文件目录没有执行权限。与静态文件不同媒体文件是用户上传的通常位于MEDIA_ROOT。解决方案确保Nginx配置中location /media/的alias路径正确。最关键的一步设置正确的目录权限。Nginx的工作进程通常是www-data用户需要对MEDIA_ROOT目录及其父目录有x执行权限并对MEDIA_ROOT目录本身有r读权限。sudo chmod 755 /path/to/your/project/media # 如果media目录下已有文件可能需要递归修改 sudo chmod -R 755 /path/to/your/project/media # 或者更精细地设置所有权假设项目目录属于用户deploy sudo chown -R deploy:www-data /path/to/your/project/media sudo chmod -R 755 /path/to/your/project/media6.4 Django的Time Zone警告与时间显示问题症状运行python manage.py runserver时控制台出现RuntimeWarning: ... received a naive datetime ...警告或者数据库中存储的时间与本地时间不符。原因Django强烈建议使用带时区信息的aware datetime。如果数据库存储的是naive datetime不带时区而settings.py中设置了USE_TZ True就会产生警告和显示问题。解决方案在settings.py中明确设置时区TIME_ZONE Asia/Shanghai根据你所在地区。保持USE_TZ True。这样Django会在内部使用UTC时间并在模板渲染时根据TIME_ZONE转换为本地时间。在代码中创建时间对象时使用django.utils.timezone.now()替代Python标准的datetime.datetime.now()。对于MySQLDjango的DateTimeField在USE_TZTrue时会存储为UTC时间的TIMESTAMP类型这是正确的做法。7. 项目优化与功能扩展思路一个基础版本完成后可以从以下几个方向进行优化和扩展让项目更具竞争力和实用性。7.1 性能优化数据库查询优化使用select_related和prefetch_related在商品列表页如果需要显示卖家昵称来自UserProfile使用Product.objects.all().select_related(seller__profile)可以避免“N1查询问题”。添加数据库索引为经常用于查询和排序的字段添加索引如Product表的category,campus,status,created_atFavorite表的user_id和product_idDjango为外键自动创建索引但联合索引可能需要手动在Meta中定义index_together。缓存使用Django的缓存框架缓存首页、热门商品列表等变化不频繁的页面或数据片段。可以配置为使用内存缓存如Memcached或Redis。静态文件CDN将static和media文件托管到云存储如阿里云OSS、腾讯云COS并配置CDN大幅加快图片等资源的加载速度减轻服务器压力。7.2 功能增强全文搜索使用django-haystackWhoosh轻量或Elasticsearch强大替代简单的icontains查询实现更高效、更精准的商品搜索支持分词、高亮、相关度排序。即时通讯集成WebSocket通过Channels库将站内信升级为实时聊天功能让买卖家沟通更顺畅。简单的推荐系统基于用户浏览记录、收藏行为实现“猜你喜欢”功能。初期可以用基于物品的协同过滤看此商品的人也看了...简单实现。订单与交易流程引入简单的订单模型记录买卖家、商品、价格、状态待确认、待见面、已完成、已取消并集成站内信通知让交易流程更可追踪。后台管理增强定制Django Admin增加数据看板、用户行为统计、商品审核流程等方便运营。7.3 安全加固用户上传文件安全对用户上传的图片进行重命名如使用UUID并使用Pillow验证文件确实是图片防止上传恶意文件。SQL注入与XSS防护坚持使用Django ORM或参数化查询模板中自动转义变量{{ variable }}这些Django已默认提供良好保护但自己写原生SQL或使用mark_safe时要格外小心。速率限制对登录、注册、发布商品等接口进行速率限制使用django-ratelimit防止恶意刷接口。回顾整个项目从技术选型、模型设计、业务逻辑实现到部署上线每一个环节都充满了权衡和细节。这个基于Django的校园二手交易平台项目麻雀虽小五脏俱全涵盖了Web开发的绝大部分核心概念。对于学习者而言吃透这个项目不仅能让你对Django开发有体系化的理解更能让你对如何将一个想法一步步落地成可运行的、有一定健壮性的产品有一个完整的认知。代码和文档只是起点在解决一个个具体问题的过程中积累的经验和形成的思维模式才是更宝贵的财富。如果在复现过程中遇到任何问题欢迎随时交流探讨。本文还有配套的精品资源点击获取
返回列表