一、前置条件:
1.安装好python 【关联网址】
2. 安装好vscode 【关联网址】
插件
3. 登陆海螺AI【关联网址】
4. 安装好 pip install django 【关联网址】
pip install django -i https://mirrors.aliyun.com/pypi/simple/
二、开始生成
1. 打开vscode 打开终端输入以下命令
django-admin startproject myapp
cd myapp
py manage.py startapp app
# 下面生成 目录 用于修改后台,二次开发用
md templates/admin
2、数据库 对海螺AI 问 : 设计一个进销存数据库
设计一个进销存(Inventory Management System)数据库需要考虑几个关键实体和它们之间的关系。以下是一个基本的进销存数据库设计示例,包括了一些核心表和它们的字段。
### 核心实体和字段
#### 1. 商品(Products)
- 商品ID(ProductID): 主键,唯一标识每个商品。
- 商品名称(ProductName): 商品的名称。
- 商品描述(Description): 商品的详细描述。
- 单位成本(CostPrice): 商品的采购成本。
- 销售价格(SellingPrice): 商品的销售价格。
- 库存数量(StockQuantity): 当前库存中的商品数量。
- 分类ID(CategoryID): 外键,关联到商品分类表。#### 2. 商品分类(Categories)
- 分类ID(CategoryID): 主键,唯一标识每个分类。
- 分类名称(CategoryName): 分类的名称。#### 3. 供应商(Suppliers)
- 供应商ID(SupplierID): 主键,唯一标识每个供应商。
- 供应商名称(SupplierName): 供应商的名称。
- 联系信息(ContactInfo): 供应商的联系信息。#### 4. 客户(Customers)
- 客户ID(CustomerID): 主键,唯一标识每个客户。
- 客户名称(CustomerName): 客户的名称。
- 联系信息(ContactInfo): 客户的联系信息。#### 5. 订单(Orders)
- 订单ID(OrderID): 主键,唯一标识每个订单。
- 客户ID(CustomerID): 外键,关联到客户表。
- 订单日期(OrderDate): 订单的日期。
- 总金额(TotalAmount): 订单的总金额。#### 6. 订单详情(OrderDetails)
- 订单详情ID(OrderDetailID): 主键,唯一标识订单详情。
- 订单ID(OrderID): 外键,关联到订单表。
- 商品ID(ProductID): 外键,关联到商品表。
- 购买数量(QuantityPurchased): 购买的商品数量。
- 单价(UnitPrice): 购买时的商品单价。#### 7. 采购记录(Purchases)
- 采购记录ID(PurchaseID): 主键,唯一标识每次采购。
- 供应商ID(SupplierID): 外键,关联到供应商表。
- 采购日期(PurchaseDate): 采购的日期。
- 总金额(TotalCost): 采购的总金额。#### 8. 采购详情(PurchaseDetails)
- 采购详情ID(PurchaseDetailID): 主键,唯一标识采购详情。
- 采购记录ID(PurchaseID): 外键,关联到采购记录表。
- 商品ID(ProductID): 外键,关联到商品表。
- 购入数量(QuantityReceived): 购入的商品数量。
- 单价(UnitPrice): 购入时的商品单价。### 关系
- 商品与分类是多对一的关系,即一个商品属于一个分类,一个分类可以包含多个商品。
- 订单与客户是多对一的关系,即一个客户可以有多个订单,但每个订单只属于一个客户。
- 订单详情与订单是多对一的关系,即一个订单可以包含多个商品,但每个订单详情只属于一个订单。
- 订单详情与商品是多对一的关系,即一个商品可以在多个订单中出现,但每个订单详情只涉及一个商品。
- 采购记录与供应商是多对一的关系,即一个供应商可以有多次采购记录,但每次采购记录只对应一个供应商。
- 采购详情与采购记录是多对一的关系,即一次采购记录可以包含多个商品,但每个采购详情只属于一次采购记录。
- 采购详情与商品是多对一的关系,即一个商品可以被多次采购,但每个采购详情只涉及一个商品。### 数据库设计注意事项
- 确保主键的唯一性。
- 使用外键来维护表之间的关系。
- 考虑索引的使用,以提高查询效率。
- 根据实际业务需求,可能还需要添加额外的字段或表,例如员工信息、库存变动记录等。这个设计是一个基础版本,实际应用中可能需要根据具体业务需求进行调整和扩展。
第二问:根据上面的数据库生成django 5 的models
第三问:舔加中文标识
第四问:生成admin.py
三、 再改生成app/models.py
from django.db import models
# 商品分类模型
class Category(models.Model):
category_name = models.CharField("分类名称", max_length=100, unique=True)
# 其他字段...
class Meta:
verbose_name = "分类"
verbose_name_plural = "分类"
def __str__(self):
return self.category_name
# 商品模型
class Product(models.Model):
product_name = models.CharField("商品名称", max_length=255)
description = models.TextField("商品描述")
cost_price = models.DecimalField("成本价格", max_digits=10, decimal_places=2)
selling_price = models.DecimalField("销售价格", max_digits=10, decimal_places=2)
stock_quantity = models.IntegerField("库存数量")
category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name="分类")
class Meta:
verbose_name = "商品"
verbose_name_plural = "商品"
def __str__(self):
return self.product_name
# 供应商模型
class Supplier(models.Model):
supplier_name = models.CharField("供应商名称", max_length=255)
contact_info = models.TextField("联系信息")
address = models.CharField("地址", max_length=255, blank=True, null=True)
phone_number = models.CharField("电话号码", max_length=20, blank=True, null=True)
class Meta:
verbose_name = "供应商"
verbose_name_plural = "供应商"
def __str__(self):
return self.supplier_name
# 客户模型
class Customer(models.Model):
customer_name = models.CharField("客户名称", max_length=255)
contact_info = models.TextField("联系信息")
address = models.TextField("地址", blank=True, null=True)
phone_number = models.CharField("电话号码", max_length=20, blank=True, null=True)
class Meta:
verbose_name = "客户"
verbose_name_plural = "客户"
def __str__(self):
return self.customer_name
# 订单模型
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, verbose_name="客户")
order_date = models.DateTimeField("订单日期", auto_now_add=True)
total_amount = models.DecimalField("总金额", max_digits=10, decimal_places=2)
class Meta:
verbose_name = "订单"
verbose_name_plural = "订单"
def __str__(self):
return f"订单 {self.id} 由 {self.customer}"
# 订单详情模型
class OrderDetail(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE, verbose_name="订单")
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="商品")
quantity_purchased = models.IntegerField("购买数量")
unit_price = models.DecimalField("单价", max_digits=10, decimal_places=2)
class Meta:
verbose_name = "订单详情"
verbose_name_plural = "订单详情"
def __str__(self):
return f"{self.quantity_purchased} 个 {self.product} 在订单 {self.order}"
# 采购记录模型
class Purchase(models.Model):
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE, verbose_name="供应商")
purchase_date = models.DateTimeField("采购日期", auto_now_add=True)
total_cost = models.DecimalField("总成本", max_digits=10, decimal_places=2)
class Meta:
verbose_name = "采购记录"
verbose_name_plural = "采购记录"
def __str__(self):
return f"采购 {self.id} 来自 {self.supplier}"
# 采购详情模型
class PurchaseDetail(models.Model):
purchase = models.ForeignKey(Purchase, on_delete=models.CASCADE, verbose_name="采购")
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name="商品")
quantity_received = models.IntegerField("接收数量")
unit_price = models.DecimalField("单价", max_digits=10, decimal_places=2)
class Meta:
verbose_name = "采购详情"
verbose_name_plural = "采购详情"
def __str__(self):
return f"{self.quantity_received} 个 {self.product} 在采购 {self.purchase}"
app/admin.py
from django.contrib import admin
from .models import Category, Product, Supplier, Customer, Order, OrderDetail, Purchase, PurchaseDetail
# 定义一个内联类用于在订单详情中显示商品信息
class OrderDetailInline(admin.TabularInline):
model = OrderDetail
extra = 1 # 默认显示额外的1行
# 定义一个内联类用于在采购详情中显示商品信息
class PurchaseDetailInline(admin.TabularInline):
model = PurchaseDetail
extra = 1 # 默认显示额外的1行
# 定义Category模型的管理类
class CategoryAdmin(admin.ModelAdmin):
list_display = ('category_name',) # 在列表页显示的字段
# 定义Product模型的管理类
class ProductAdmin(admin.ModelAdmin):
list_display = ('id','product_name','selling_price', 'category', 'stock_quantity')
search_fields = ('product_name', 'id')
# 定义Supplier模型的管理类
class SupplierAdmin(admin.ModelAdmin):
list_display = ('id','supplier_name', 'phone_number', 'address')
search_fields = ('supplier_name', 'id')
# 定义Customer 客户模型的管理类
class CustomerAdmin(admin.ModelAdmin):
list_display = ('customer_name', 'phone_number')
search_fields = ('customer_name', 'id')
# 定义Order订单模型的管理类
class OrderAdmin(admin.ModelAdmin):
list_display = ('id', 'customer', 'order_date', 'total_amount')
inlines = [OrderDetailInline] # 使用内联类显示订单详情
search_fields = ('id', 'customer__customer_name')
# 定义Purchase模型的管理类
class PurchaseAdmin(admin.ModelAdmin):
list_display = ('id', 'supplier', 'purchase_date', 'total_cost')
inlines = [PurchaseDetailInline] # 使用内联类显示采购详情
search_fields = ('id', 'supplier__supplier_name')
# 注册模型到admin
admin.site.register(Category, CategoryAdmin)
admin.site.register(Product, ProductAdmin)
admin.site.register(Supplier, SupplierAdmin)
admin.site.register(Customer, CustomerAdmin)
admin.site.register(Order, OrderAdmin)
admin.site.register(Purchase, PurchaseAdmin)
主urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', admin.site.urls), # Django自带的管理界面URLs
]
设置:settings.py
四、输入命令 生成Django 数据库 db.sqlite3
# 生成模型转到数据库
python manage.py makemigrations
python manage.py migrate
# 创建管理员
python manage.py createsuperuser
# 可填写入:admin email:admin@qq.com 密码:abc123456
五、根目录 建 templates/admin
根据 templates/admin 目录优先 打后台的网页拿过来改从而得到覆盖原先页面来改后台页面
C:\Program Files\Python312\Lib\site-packages\django\contrib\admin\templates\admin
复制到:templates/admin
\myapp\templates\admin\change_form.html
{% extends "admin/base_site.html" %}
{% load i18n admin_urls static admin_modify %}
{% block extrahead %}{{ block.super }}
<script src="{% url 'admin:jsi18n' %}"></script>
<style>
/* 对打印机进行样式设置 */
@media print {
.no-print {
display: none; /* 在打印时隐藏带有no-print类的元素 */
}
td,th, tr,table {
border: none;
/* padding: 15px; */
}
.submit-row {
display: none;
}
body {
margin: 0;
padding: 0;
border: none;
}
#site-name {
display: none;
}
@page {
margin-top: 0;
margin-bottom: 0;
}
header, footer {
display: none;
}
/* 或者 */
header, footer {
visibility: hidden;
position: absolute;
top: -10000px;
}
}
</style>
{{ media }}
{% endblock %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" href="{% static "admin/css/forms.css" %}">{% endblock %}
{% block coltype %}colM{% endblock %}
{% block bodyclass %}{{ block.super }} app-{{ opts.app_label }} model-{{ opts.model_name }} change-form{% endblock %}
{% if not is_popup %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% translate 'Home' %}</a>
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
› {% if has_view_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
› {% if add %}{% blocktranslate with name=opts.verbose_name %}Add {{ name }}{% endblocktranslate %}{% else %}{{ original|truncatewords:"18" }}{% endif %}
</div>
{% endblock %}
{% endif %}
{% block content %}<div id="content-main">
{% block object-tools %}
{% if change and not is_popup %}
<ul class="object-tools">
{% block object-tools-items %}
{% change_form_object_tools %}
{% endblock %}
</ul>
{% endif %}
{% endblock %}
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}{% if form_url %}action="{{ form_url }}" {% endif %}method="post" id="{{ opts.model_name }}_form" novalidate>{% csrf_token %}{% block form_top %}{% endblock %}
<div>
{% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="1">{% endif %}
{% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}">{% endif %}
{% if save_on_top %}{% block submit_buttons_top %}{% submit_row %}{% endblock %}{% endif %}
{% if errors %}
<p class="errornote">
{% blocktranslate count counter=errors|length %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktranslate %}
</p>
{{ adminform.form.non_field_errors }}
{% endif %}
{% block field_sets %}
{% for fieldset in adminform %}
{% include "admin/includes/fieldset.html" with heading_level=2 prefix="fieldset" id_prefix=0 id_suffix=forloop.counter0 %}
{% endfor %}
{% endblock %}
{% block after_field_sets %}{% endblock %}
{% block inline_field_sets %}
{% for inline_admin_formset in inline_admin_formsets %}
{% include inline_admin_formset.opts.template %}
{% endfor %}
{% endblock %}
{% block after_related_objects %}{% endblock %}
{% block submit_buttons_bottom %}{% submit_row %}{% endblock %}
<div class="submit-row">
<button onclick="printDocument()" class="btn" style="background-color: rgb(22, 194, 247);height: 35px;width: 80px;border-radius: 5px;border: none;color: #fff;" >打印</button>
</div>
{% block admin_change_form_document_ready %}
<script id="django-admin-form-add-constants"
src="{% static 'admin/js/change_form.js' %}"
{% if adminform and add %}
data-model-name="{{ opts.model_name }}"
{% endif %}
async>
</script>
{% endblock %}
{# JavaScript for prepopulated fields #}
{% prepopulated_fields_js %}
</div>
</form></div>
<script>
function printDocument() {
window.print();
}
</script>
</script>
{% endblock %}
用了CSS 隐藏的方法来和改变样式的 来做个用浏览器打印的方法
@media print {
.no-print {
display: none; /* 在打印时隐藏带有no-print类的元素 */
}@page { ---------------去掉页眉 页脚
margin-top: 0;
margin-bottom: 0;
}调用浏览器来打印
<button οnclick="printDocument()"
window.print();
contine......更多的细节后面分解
运行起来
python manage.py runserver
不想看到 下面的日志
就在settings.py 加入下面这个
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.FileHandler',
'filename': 'general.log',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'DEBUG',
'propagate': False,
},
},
}
六、Window 下配置 Nginx
nginx.conf
server {
listen 80;
server_name localhost;
location /static/ {
alias E:/BIT_Web_2025/static/;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /media/ {
alias E:/BIT_Web_2025/media/;
}
把admin后台 模板 html复制到 templates ,
C:\Program Files\Python312\Lib\site-packages\django\contrib\admin\templates\admin
静态 css js 之类 复制static/admin
C:\Program Files\Python312\Lib\site-packages\django\contrib\admin\static\admin
这样后台就可以打开样式
pm2 来管理
ecosystem.config.js
module.exports = {
apps : [{
name: "内部测试版",
script: "manage.py",
args: "runserver 0.0.0.0:8000",
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: "150M"
}]
};
start_pm2.bat
@echo off
pm2 start ecosystem.config.js --no-daemon
move2.py
移动到第二个桌面
import pyautogui
import time
# # 按下 Windows 键
# pyautogui.press('win')
# # 等待一段时间,确保 Windows 键的效果生效
# time.sleep(0.2)
# # 按下 Tab 键
# pyautogui.press('tab')
# # 释放 Tab 键
# pyautogui.keyUp('tab')
# # 释放 Windows 键
# pyautogui.keyUp('win')
time.sleep(10)
# 模拟 Ctrl+C (复制)
pyautogui.keyDown('win')
pyautogui.press('tab')
# 释放 Tab 键
pyautogui.keyUp('tab')
# 释放 Windows 键
pyautogui.keyUp('win')
# 移动鼠标到指定位置
# pyautogui.moveTo(566, 366, duration=1) # 1秒内移动到(200, 200)
# 按下并释放鼠标右键
# pyautogui.mouseDown(button='right')
# pyautogui.mouseUp(button='right')
# 模拟按下 Tab 键两次
pyautogui.press('tab')
time.sleep(1)
pyautogui.press('tab')
# 模拟按下并释放向下箭头键三次
# for _ in range(2):
# pyautogui.keyDown('down')
# time.sleep(0.3) # 等待0.1秒,模拟按键持续时间
# pyautogui.keyUp('down')
# 模拟按下并释放向右箭头键一次
pyautogui.keyDown('right')
time.sleep(0.3) # 等待0.1秒,模拟按键持续时间
# pyautogui.keyUp('right')
# 移动鼠标到期望点击的位置(这里需要你根据实际情况指定坐标)
# 假设我们移动到屏幕中心位置点击
# pyautogui.moveTo(pyautogui.size().width / 2, pyautogui.size().height / 2)
# 模拟按下并释放 'Enter' 键
pyautogui.press('enter')
# 移动鼠标到指定位置
# pyautogui.moveTo(100, 100, duration=1) # 1秒内移动到(200, 200)
# 执行鼠标点击
# pyautogui.click() # 默认点击当前鼠标位置
time.sleep(1)
pyautogui.keyDown('left')
time.sleep(1)
pyautogui.press('enter')
Onekey.py
同时打开两个程序,不用等上一个结束
import subprocess
# pm2 start ecosystem.config.js --no-daemon
# 使用subprocess.Popen在后台运行第一个命令
# process1 = subprocess.Popen(["python", "manage.py", "runserver", "0.0.0.0:8000"])
process1 = subprocess.Popen('start_pm2.bat')
# 立即运行第二个命令
subprocess.run(["python", "move2.py"])
七、外网 穿透
Onekey-net.py
打开
复制 外网 网址
写入 语雀 笔记 (打开小记录入网址) 方便外网 穿透!!!
import pyautogui
import time
def Cpolar():
# 移动鼠标到指定位置
pyautogui.moveTo(x=1860, y=640) # # 第5个位置nas
# 双击鼠标
pyautogui.doubleClick()
# 等待5秒,给你时间切换到需要操作的窗口
time.sleep(3)
# 模拟按下Tab键
pyautogui.press('tab')
# 输入第一段文本内容
pyautogui.write('账号')
# 等待5秒,给你时间切换到需要操作的窗口
time.sleep(3)
# 模拟按下Enter键
pyautogui.press('enter')
# 再次模拟按下Tab键
pyautogui.press('tab')
# 等待5秒,给你时间切换到需要操作的窗口
time.sleep(1)
# 输入第二段文本内容
pyautogui.write('密码')
# 等待5秒,给你时间切换到需要操作的窗口
time.sleep(1)
# 再次模拟按下Tab键
pyautogui.press('tab')
# 模拟按下Enter键
pyautogui.press('enter')
# 移动鼠标到指定位置
pyautogui.moveTo(x=69, y=249) # # 第3个菜单位
time.sleep(1)
# 单击鼠标
pyautogui.click()
# 等待5秒,给你时间切换到需要操作的窗口
time.sleep(2)
# 移动鼠标到指定位置
pyautogui.moveTo(x=111, y=303) # # 第3个菜单位
# 单击鼠标
pyautogui.click()
# 等待5秒,给你时间切换到需要操作的窗口
time.sleep(3)
# 假设你想要选择的区域的左上角和右下角坐标如下
left_top_x, left_top_y = 631, 279 # 左上角坐标
right_bottom_x, right_bottom_y = 868, 313 # 右下角坐标
# 移动鼠标到左上角位置
pyautogui.moveTo(left_top_x, left_top_y)
# 按下鼠标左键开始选择
pyautogui.mouseDown()
# 移动鼠标到右下角位置
pyautogui.moveTo(right_bottom_x, right_bottom_y)
# 释放鼠标左键完成选择
pyautogui.mouseUp()
# 模拟按下 Ctrl+C 进行复制
pyautogui.hotkey('ctrl', 'c')
print('关闭浏览器')
# 等待5秒,给你时间切换到需要操作的窗口
time.sleep(1)
# 移动鼠标到指定位置
pyautogui.moveTo(x=1896, y=16) # 关闭浏览器
# 单击鼠标
pyautogui.click()
print('打开网络笔记')
# 等待5秒,给你时间切换到需要操作的窗口 笔记
time.sleep(1)
# 移动鼠标到指定位置
pyautogui.moveTo(x=1865, y=735) # # 第3个菜单位
# 双击鼠标
pyautogui.doubleClick()
# 等待5秒,给你时间切换到需要操作的窗口
time.sleep(8)
# 按下 Ctrl + Shift + Y 打开命令面板
pyautogui.hotkey('ctrl', 'shift', 'y')
# 等待5秒,给你时间切换到需要操作的窗口
time.sleep(2)
# 按下 Ctrl + v 粘贴内容
pyautogui.hotkey('ctrl', 'v')
# 按下回车键
pyautogui.press('enter')
# 等待5秒,给你时间切换到需要操作的窗口
time.sleep(13)
# 转换到需要操作的按钮上
pyautogui.moveTo(x=1190, y=610) # # 第3个菜单位
# 单击鼠标
pyautogui.click()
# 等待5秒,给你时间切换到需要操作的窗口
time.sleep(1)
# 移动鼠标到指定位置
pyautogui.moveTo(x=1696, y=119) # 关闭笔记
# 单击鼠标
pyautogui.click()
time.sleep(2)
Cpolar()
print('复制网址已完成')
八、Windows 配
在Windows 11上使用WSGI部署Django应用程序,你可以选择使用Waitress作为WSGI服务器,因为它兼容Windows环境。以下是部署步骤:
1. 安装Waitress
首先,确保你已经安装了Waitress。你可以使用pip进行安装:
bash
取消自动换行
复制
pip install waitress
2. 准备你的Django项目
确保你的Django项目已经设置好,并且可以正常运行。你需要知道Django项目的wsgi.py
文件的位置,它通常位于你的Django应用目录下。
3. 创建一个启动脚本
创建一个Python脚本(例如runserver.py
),用于启动Waitress服务器。脚本内容可能如下:
python
取消自动换行
复制
from waitress import serve
from myproject.wsgi import application # 替换为你的Django项目名
if __name__ == "__main__":
serve(application, host='localhost', port=8000)
确保替换myproject.wsgi.application
为你的Django项目的WSGI应用实例。
4. 运行Waitress服务器
在命令行中运行你刚才创建的脚本:
bash
取消自动换行
复制
python runserver.py
这将启动Waitress服务器,并在本地的8000端口上监听。
5. 测试你的Django应用
现在,你应该可以通过浏览器访问http://localhost:8000
来查看你的Django应用是否正常运行。
6. 配置Web服务器(可选)
虽然Waitress可以作为独立服务器运行,但在生产环境中,你可能希望使用Web服务器(如IIS或Nginx)作为反向代理服务器。对于IIS,你可以使用wfastcgi
模块来运行Python应用程序。对于Nginx,你可以配置它来代理请求到Waitress服务器。
7. 部署到生产环境
部署到生产环境时,你可能需要考虑以下因素:
- 使用更健壮的服务器配置(如使用多个工作进程)。
- 设置日志记录和错误处理。
- 使用HTTPS。
- 设置防火墙和安全组规则。
- 监控和自动重启机制。
总结
虽然在Windows上部署Django不如在Unix-like系统上那么常见,但通过使用Waitress这样的纯Python WSGI服务器,你仍然可以轻松地在Windows 11上部署和运行你的Django Web应用程序。确保在部署过程中考虑到性能和安全的最佳实践。
要隐藏命令窗口运行Waitress服务,通常有几种方法:
1. **使用批处理文件**:在Windows系统中,你可以创建一个批处理文件(`.bat`),在该文件中启动Waitress服务,并且使用`start`命令来运行,这样就不会显示命令窗口。例如:
```bat
@echo off
start /B python -m waitress --listen=*:8080 myapp:app
```
这里`/B`选项表示不创建新的命令行窗口。
2. **使用任务计划程序**:你可以使用Windows的任务计划程序来启动Waitress服务,并且设置为隐藏运行。
3. **使用专业软件**:有些软件如`NSSM`(Non-Sucking Service Manager)可以帮助你将Waitress服务设置为后台运行。
4. **使用Python脚本**:在Python脚本中使用`subprocess`模块启动Waitress服务,并且设置`creationflags`参数为`subprocess.CREATE_NO_WINDOW`来隐藏命令窗口。
runserver.py
from waitress import serve
from BitSite.wsgi import application # 替换为你的Django项目名
if __name__ == "__main__":
serve(application, host='localhost', port=8000)
run.py
import subprocess
# Waitress服务的启动命令
command = [
'waitress-serve', '--listen=*:8000', 'runserver:application'
]
# 使用subprocess.Popen启动Waitress服务,隐藏命令窗口
process = subprocess.Popen(command, creationflags=subprocess.CREATE_NO_WINDOW)
# 等待服务启动(可选,根据需要)
process.wait()
结束可找进程,直接结束
5. **使用服务包装器**:将你的Python应用程序包装成一个Windows服务,例如使用`pywin32`库中的`win32serviceutil`模块。
请注意,隐藏命令窗口通常用于生产环境,以提高用户体验和安全性。在开发环境中,通常不建议隐藏命令窗口,因为这样可以更容易地查看日志和调试信息。
八、 后台 内联显示(Inline Display)
参考例:
models.py
from django.db import models
class ComponentCategory(models.Model):
category_id = models.AutoField(primary_key=True, verbose_name="类别ID")
category_name = models.CharField(max_length=50, verbose_name="类别名称")
category_description = models.TextField(verbose_name="类别描述")
def __str__(self):
return self.category_name
class Meta:
verbose_name = "类别"
verbose_name_plural = verbose_name
class Component(models.Model):
component_id = models.AutoField(primary_key=True, verbose_name="配件ID")
category_id = models.ForeignKey(ComponentCategory, on_delete=models.CASCADE, verbose_name="分类ID")
component_name = models.CharField(max_length=100, verbose_name="配件名称")
purchase_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="采购价格")
selling_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="销售价格")
description = models.TextField(verbose_name="描述")
def __str__(self):
return self.component_name
class Meta:
verbose_name = "配件"
verbose_name_plural = verbose_name
class User(models.Model):
user_id = models.AutoField(primary_key=True, verbose_name="客户ID")
username = models.CharField(max_length=50, verbose_name="客户名")
password = models.CharField(max_length=255, verbose_name="密码")
email = models.CharField(max_length=100, verbose_name="邮箱")
def __str__(self):
return self.username
class Meta:
verbose_name = "客户"
verbose_name_plural = verbose_name
class ComputerConfiguration(models.Model):
config_id = models.AutoField(primary_key=True, verbose_name="配置ID")
user_id = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="用户ID")
config_name = models.CharField(max_length=100, verbose_name="配置名称")
creation_date = models.DateTimeField(auto_now_add=True, verbose_name='创建日期', blank=True, null=True)
def __str__(self):
return self.config_name
class Meta:
verbose_name = "组装电脑"
verbose_name_plural = verbose_name
class ConfigurationComponent(models.Model):
config_component_id = models.AutoField(primary_key=True, verbose_name="配置组件ID")
config_id = models.ForeignKey(ComputerConfiguration, on_delete=models.CASCADE, verbose_name="配置ID")
component_id = models.ForeignKey(Component, on_delete=models.CASCADE, verbose_name="组件ID")
quantity = models.IntegerField(verbose_name="数量")
selling_price_generated = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="生成售价")
def __str__(self):
return self.config_id.config_name + " - " + self.component_id.component_name
class Meta:
verbose_name = "配件单价"
verbose_name_plural = verbose_name
admin.py
from django.contrib import admin
from.models import ComponentCategory, Component, User, ComputerConfiguration, ConfigurationComponent
class ConfigurationComponentInline(admin.TabularInline):
model = ConfigurationComponent
fields = ('component_id', 'quantity', 'selling_price_generated')
classes = ('grp-collapse',)
extra = 1
class ComputerConfigurationAdmin(admin.ModelAdmin):
inlines = [ConfigurationComponentInline]
def total_selling_price(self, obj):
components = ConfigurationComponent.objects.filter(config_id=obj.config_id)
total = sum([component.selling_price_generated * component.quantity for component in components])
return total
total_selling_price.short_description = '合计销售价格'
list_display = ('config_id', 'user_id', 'config_name','creation_date', 'total_selling_price' )
list_display_links = ('config_name',)
search_fields = ('config_name',)
list_per_page = 4
class ComponentCategoryAdmin(admin.ModelAdmin):
list_display = ('category_id', 'category_name', 'category_description')
list_display_links = ('category_name',)
admin.site.register(ComponentCategory, ComponentCategoryAdmin)
@admin.register(Component)
class ComponentAdmin(admin.ModelAdmin):
list_display = ('component_id', 'category_id', 'component_name', 'purchase_price', 'selling_price', 'description')
list_display_links = ('component_name',)
search_fields = ('component_name',)
list_per_page = 4
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
list_display = ('user_id', 'username', 'password', 'email')
list_display_links = ('username',)
admin.site.register(ComputerConfiguration, ComputerConfigurationAdmin)
@admin.register(ConfigurationComponent)
class ConfigurationComponentAdmin(admin.ModelAdmin):
list_display = ('config_component_id', 'config_id', 'component_id', 'quantity', 'selling_price_generated')
list_display_links = ('config_component_id',)
search_fields = ('config_component_id',)
list_per_page = 4