用 Django 5 快速生成一个简单 进销存 系统 添加 个打印 按钮

一、前置条件:

1.安装好python 【关联网址

  1. 安装好vscode 【关联网址

插件

  1. 登陆海螺AI【关联网址
  1. 安装好 pip install django 【关联网址
python 复制代码
pip install django -i https://mirrors.aliyun.com/pypi/simple/

二、开始生成

1. 打开vscode 打开终端输入以下命令

python 复制代码
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

python 复制代码
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

python 复制代码
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

python 复制代码
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('', admin.site.urls),  # Django自带的管理界面URLs
]

设置:settings.py

四、输入命令 生成Django 数据库 db.sqlite3

bash 复制代码
# 生成模型转到数据库
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

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>
&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
&rsaquo; {% if has_view_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
&rsaquo; {% 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......更多的细节后面分解

运行起来

bash 复制代码
python manage.py runserver  

不想看到 下面的日志

就在settings.py 加入下面这个

bash 复制代码
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,
        },
    },
}
相关推荐
WangYaolove13147 分钟前
请解释Python中的装饰器是什么?如何使用它们?
linux·数据库·python
我是黄大仙27 分钟前
利用飞书多维表格自动发布版本
运维·服务器·数据库·飞书
曾经的三心草28 分钟前
Mysql之约束与事件
android·数据库·mysql·事件·约束
宋发元31 分钟前
如何使用正则表达式验证域名
python·mysql·正则表达式
WuMingf_35 分钟前
redis
数据库·redis
张某布响丸辣42 分钟前
SQL中的时间类型:深入解析与应用
java·数据库·sql·mysql·oracle
XMYX-01 小时前
Python 操作 Elasticsearch 全指南:从连接到数据查询与处理
python·elasticsearch·jenkins
正义的彬彬侠1 小时前
sklearn.datasets中make_classification函数
人工智能·python·机器学习·分类·sklearn
belldeep1 小时前
python:用 sklearn 转换器处理数据
python·机器学习·sklearn