用 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,
        },
    },
}
相关推荐
chao_7891 小时前
二分查找篇——搜索旋转排序数组【LeetCode】一次二分查找
数据结构·python·算法·leetcode·二分查找
烛阴2 小时前
Python装饰器解除:如何让被装饰的函数重获自由?
前端·python
workflower2 小时前
MDSE和敏捷开发相互矛盾之处:方法论本质的冲突
数据库·软件工程·敏捷流程·极限编程
Tony小周2 小时前
实现一个点击输入框可以弹出的数字软键盘控件 qt 5.12
开发语言·数据库·qt
noravinsc2 小时前
django 一个表中包括id和parentid,如何通过parentid找到全部父爷id
python·django·sqlite
lifallen2 小时前
Paimon 原子提交实现
java·大数据·数据结构·数据库·后端·算法
ajassi20002 小时前
开源 python 应用 开发(三)python语法介绍
linux·python·开源·自动化
沉默媛3 小时前
如何安装python以及jupyter notebook
开发语言·python·jupyter
TDengine (老段)3 小时前
TDengine 数据库建模最佳实践
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
Elastic 中国社区官方博客3 小时前
Elasticsearch 字符串包含子字符串:高级查询技巧
大数据·数据库·elasticsearch·搜索引擎·全文检索·lucene