有了产品信息之后,下面来写库存信息部分

每一个库存的入库和出库都需要对应一个产品,所以产品信息是它的外键

库存信息

创建App

python manage.py startapp warehouse

warehouse文件夹移动到backend/apps/warehouse

注册App

backend/LightSeeking/settings.pyINSTALLED_APPS中添加

INSTALLED_APPS = [...'users.apps.UsersConfig','product.apps.ProductConfig','warehouse.apps.WarehouseConfig'
]

表结构设计

库存信息包含了

  • 产品信息

  • 单价

  • 生产日期

  • 保质期天数

  • 数量

  • 库存状态

  • 订单号

  • 供应商

  • 备注

产品信息使用外键的方式,并且两个键之间不互相影响

product = models.ForeignKey(Product, verbose_name="产品信息", on_delete=models.DO_NOTHING, help_text="产品信息")

其他都是普通的字段

from django.db import modelsfrom product.models import Product
from utils.models import BaseModelclass Warehouse(BaseModel):STOCKSTATUS = ((1, "入库"),(2, "出库"),(3, "报废"),)product = models.ForeignKey(Product, verbose_name="产品信息", on_delete=models.DO_NOTHING, help_text="产品信息")price = models.DecimalField('成本单价', max_digits=10, decimal_places=2, default=0, help_text='成本单价')date_of_manufacture = models.DateTimeField("生产日期", help_text="生产日期")quality_guarantee = models.IntegerField("保质期天数", help_text="保质期天数")num = models.IntegerField("数量", default=0, help_text="数量")stock_status = models.CharField("库存状态", max_length=2, choices=STOCKSTATUS, default=1,help_text='库存状态:1-入库,2-出库,3-报废')order_id = models.CharField("订单号", max_length=200, null=True, blank=True, default='', help_text='订单号')supplier = models.CharField("供应商", max_length=200, null=True, blank=True, default='', help_text='供应商')desc = models.CharField('备注', max_length=1000, null=True, blank=True, default='', help_text='备注')class Meta:db_table = 'tb_warehouse'verbose_name = '库存信息'verbose_name_plural = verbose_namedef __str__(self):return self.id

数据迁移

python manage.py makemigrations
python manage.py migrate

序列化器

在库存序列化器中需要指定产品来进行新增,查看的时候需要返回全部的产品信息

所以先新建一个包含全部产品的序列化器

backend/apps/product/serializers.py

class ProductAllModelSerializer(serializers.ModelSerializer):class Meta:model = Productfields = '__all__'

添加产品的时候使用的是产品的id,这时候就需要判断一下这个产品是否存在了

编写whether_existed_product_id方法来进行判断

def whether_existed_product_id(value):"""检查产品id是否存在:param value::return:"""if value != 0:if not isinstance(value, int):raise serializers.ValidationError('所选产品信息有误!')elif not Product.objects.filter(is_delete=False, id=value).exists():raise serializers.ValidationError('所选产品信息不存在!')

所以库存的序列化器基础版本为

class WarehouseModelSerializer(serializers.ModelSerializer):product_id = serializers.IntegerField(write_only=True,help_text='产品信息ID',validators=[validates.whether_existed_product_id])product = ProductAllModelSerializer(read_only=True, many=False)class Meta:model = Warehouseexclude = ('is_delete',)extra_kwargs = {'c_time': {'read_only': True},}

重点

下面是序列化器中的一个神奇的操作,也就是它可以逐行处理返回的数据,根据逻辑给每行添加需要的数据

在这个序列化器中需要顺便计算一下产品的保质期相关数据

新加两个字段剩余天数保质期日期

剩余天数 = 保质期天数 - (当前日期 - 生产日期)

保质期日期 = 生产日期+剩余天数

remaining = serializers.SerializerMethodField(label="剩余天数", read_only=True, help_text="剩余天数")
remaining_day = serializers.SerializerMethodField(label="保质期日期", read_only=True, help_text="保质期日期")

使用serializers.SerializerMethodField可以在WarehouseModelSerializer类中编写get_xxx方法来计算这个值

def get_remaining(self, warehouse):"""剩余天数 = 保质期天数 - (当前日期 - 生产日期):param warehouse::return:"""return warehouse.quality_guarantee - (warehouse.date_of_manufacture - datetime.datetime.now(tz=pytz.UTC)).daysdef get_remaining_day(self, warehouse):"""保质期日期 = 生产日期+剩余天数"""return warehouse.date_of_manufacture + datetime.timedelta(days=warehouse.quality_guarantee)

同理再根据需求添加几个字段

  • 总库存

  • 出库

  • 入库

  • 已经出库时间

  • 已经入库时间

total = serializers.SerializerMethodField(label="总库存", read_only=True, help_text="一个产品的总库存")
warehouse1 = serializers.SerializerMethodField(label="出库", read_only=True, help_text="一个产品的总出库")
warehouse2 = serializers.SerializerMethodField(label="入库", read_only=True, help_text="一个产品的总入库")
warehouse1_time = serializers.SerializerMethodField(label="已经出库时间", read_only=True, help_text="出库距离当前的时间")
warehouse2_time = serializers.SerializerMethodField(label="已经入库时间", read_only=True, help_text="入库距离当前的时间")

实现字段的计算

def get_total(self, warehouse):total = self.get_warehouse1(warehouse) - self.get_warehouse2(warehouse)return totaldef get_warehouse1(self, warehouse):product_id = warehouse.product_idwarehouse_info = Warehouse.objects.filter(stock_status=1).values("product").annotate(total=Sum("num")).all()total = warehouse_info.filter(product_id=product_id) and \warehouse_info.filter(product_id=product_id).get()["total"] or 0return totaldef get_warehouse2(self, warehouse):product_id = warehouse.product_idwarehouse_info = Warehouse.objects.filter(stock_status=2).values("product").annotate(total=Sum("num")).all()total = warehouse_info.filter(product_id=product_id) and \warehouse_info.filter(product_id=product_id).get()["total"] or 0return totaldef get_warehouse1_time(self, warehouse):warehouse2_time = warehouse.c_time - datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=+8)))return warehouse2_time.daysdef get_warehouse2_time(self, warehouse):warehouse2_time = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=+8))) - warehouse.c_timereturn warehouse2_time.days

视图

from rest_framework.viewsets import ModelViewSetfrom utils.pagination import TenItemPerPagePagination
from warehouse.models import Warehouse
from warehouse.serializers import WarehouseModelSerializerclass WarehouseViewSet(ModelViewSet):queryset = Warehouse.objects.filter(is_delete=False).order_by("-c_time")serializer_class = WarehouseModelSerializerpagination_class = TenItemPerPagePaginationordering_fields = ['c_time']def perform_destroy(self, instance):instance.is_delete = Trueinstance.save()  # 逻辑删除

路由

backend/apps/warehouse/urls.py

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import viewsrouter = DefaultRouter()
router.register("warehouse", views.WarehouseViewSet)urlpatterns = [path('', include(router.urls))
]

backend/LightSeeking/urls.py

urlpatterns = [...path('', include('warehouse.urls')),
]

代码

本次代码修改见:

https://gitee.com/zx660644/light-seeking/commit/2a5f9e4a26ff56e7cef5e6d4bdaf0adc63bb37b0

测试

先添加一个产品信息

访问http://127.0.0.1:8000/product/

填入产品信息后点击POST

再访问http://127.0.0.1:8000/warehouse/

添加一个库存信息

查看结果

{"id": 1,"product": {"id": 1,"c_time": "2022-09-02T12:14:32.356282+08:00","u_time": "2022-09-02T12:14:32.356417+08:00","is_delete": false,"product_id": "0001","category": "饮料","brand": "可口可乐","name": "可乐","price": "3.00","sample_png": "","desc": "无"},"remaining": 367,"remaining_day": "2023-09-01T12:15:00+08:00","total": 998,"warehouse1": 998,"warehouse2": 0,"warehouse1_time": -1,"warehouse2_time": 0,"c_time": "2022-09-02T12:15:46.366239+08:00","u_time": "2022-09-02T12:15:46.366352+08:00","price": "2.50","date_of_manufacture": "2022-09-01T12:15:00+08:00","quality_guarantee": 365,"num": 998,"stock_status": 1,"order_id": "","supplier": "测试供应商","desc": ""
}

其中product字段包含了我们入库的产品信息

另外之前序列化器中添加的几个字段也出现了

bug修复

不过从这里看出来,之前写了个bug,之前把日期计算写反了

def get_remaining(self, warehouse):"""剩余天数 = 保质期天数 - (当前日期 - 生产日期):param warehouse::return:"""return warehouse.quality_guarantee - (datetime.datetime.now(tz=pytz.UTC) - warehouse.date_of_manufacture).days

再次刷新后查看 remaining变为了364

{"data": {"page": 1,"pageSize": 20,"rows": [{"id": 1,"product": {"id": 1,"c_time": "2022-09-02T12:14:32.356282+08:00","u_time": "2022-09-02T12:14:32.356417+08:00","is_delete": false,"product_id": "0001","category": "饮料","brand": "可口可乐","name": "可乐","price": "3.00","sample_png": "","desc": "无"},"remaining": 364,"remaining_day": "2023-09-01T04:15:00Z","total": 998,"warehouse1": 998,"warehouse2": 0,"warehouse1_time": -1,"warehouse2_time": 0,"c_time": "2022-09-02T12:15:46.366239+08:00","u_time": "2022-09-02T12:15:46.366352+08:00","price": "2.50","date_of_manufacture": "2022-09-01T12:15:00+08:00","quality_guarantee": 365,"num": 998,"stock_status": 1,"order_id": "","supplier": "测试供应商","desc": ""}],"total": 1},"message": "","code": 200,"next": null,"previous": null
}

12.寻光集后台管理系统-库存信息(后端)相关推荐

  1. 12个免费开源后台管理系统模板

    当你写项目的时候,如何快速的完成一个项目的搭建,这个时候就需要借助到一些模板了,前端开发的一个好处就是,各类UI模板都是相当的齐全的,直接拿来用就可以了,脱离了一行又一行垒代码的繁琐的工作,以下的开源 ...

  2. 开源的微信商城,含小程序端,后台管理系统,服务器后端,附完整源码

    微信小程序商城 项目概述 一个完整的微信小程序商城,包含微信小程序,管理系统,服务端后台,项目预览如下: 微信小程序 -微信小程序包含主页.商品分类.商品详情.加购物车,微信授权登录,微信支付,个人中 ...

  3. 12个开源的后台管理系统

    1. D2admin 开源地址:https://github.com/d2-projects/d2-admin 文档地址:https://d2.pub/zh/doc/d2-admin/ 效果预览:ht ...

  4. 12 款做Java后台管理系统的项目,超级无敌好用!

    1.D2admin 文档地址:https://d2.pub/zh/doc/d2-admin/ 效果预览:https://d2.pub/d2-admin/preview/#/index 开源协议:MIT ...

  5. 12套高大上的后台管理系统模板,总有一套适合你

    1.D2admin 开源地址: https://github.com/d2-projects/d2-admin 文档地址: https://d2.pub/zh/doc/d2-admin/ 效果预览: ...

  6. Axure高保真web端后台管理系统/垃圾回收分类系统/垃圾回收高保真原型设计 /垃圾分类后台管理系统/垃圾回收分类平台//垃圾回收分类智慧管理系统/订单管理/财务管理/系统管理/库存管理/设备管理

    Axure高保真web端后台管理系统/垃圾回收分类系统/垃圾回收高保真原型设计 /垃圾分类后台管理系统/垃圾回收分类平台//垃圾回收分类智慧管理系统/订单管理/财务管理/系统管理/库存管理/设备管理 ...

  7. 垃圾回收分类系统、垃圾回收高保真原型设计 、垃圾分类后台管理系统、垃圾回收分类平台、垃圾回收分类、智慧管理系统、订单管理、财务管理、系统管理、库存管理、设备管理、Axure原型、rp原型

    Axure高保真web端后台管理系统.垃圾回收分类系统.垃圾回收高保真原型设计 .垃圾分类后台管理系统.垃圾回收分类平台.垃圾回收分类.智慧管理系统.订单管理.财务管理.系统管理.库存管理.设备管理 ...

  8. springboot外委员工后台管理系统毕业设计源码101157

    基于springboot外委员工后台管理系统 摘  要 随着互联网大趋势的到来,社会的方方面面,各行各业都在考虑利用互联网作为媒介将自己的信息更及时有效地推广出去,而其中最好的方式就是建立网络管理系统 ...

  9. springboot外委员工后台管理系统 毕业设计-附源码101157

    基于springboot外委员工后台管理系统 摘 要 随着互联网大趋势的到来,社会的方方面面,各行各业都在考虑利用互联网作为媒介将自己的信息更及时有效地推广出去,而其中最好的方式就是建立网络管理系统, ...

最新文章

  1. java 和 flash socket通信封装
  2. python编写安装脚本_LAMP一键安装脚本(Python编写)
  3. 对NumPy中dot()函数的理解(亲测,矩阵算法)
  4. IDEA下的使用git
  5. 如何通过自动增加索引,实现数据库查询耗时降低50%
  6. redhat linux 7 安装,Redhat Linux 7.3 快速安装指引 *
  7. zepto 事件分析4(事件队列)
  8. 用户推广成果总结会议
  9. 使用反射创建实例/对象的两种方法
  10. PHP输出100以内的质数(包括普通写法和数组形式输出)
  11. 放大图片模糊怎么变清晰?
  12. android -------- ConstraintLayout 宽高比和偏移量比(三)
  13. win7更新错误代码80072efe的解决方法
  14. 使用xpath爬取腾讯招聘python岗位信息
  15. php中ne,eq相等 ne、neq不相等, gt大于, lt小于
  16. 困难时拉你一把的图片_人,最不能忘记的,是在你困难时拉你一把的人,句句现实经典...
  17. C/C++编程学习 - 第7周 ⑥ 合影效果
  18. python图像音频处理-通过图像傅里叶变换判断相位和幅度的重要性
  19. macOS 开发 - AppleScript 简介
  20. 服务器事件查看器根据登录id如何查找信息,Windows中如何查看日志(如查看远程登陆的IP地址)以及常用日志ID...

热门文章

  1. python爬虫笔记——Scrapy框架(浅学)
  2. java获得程序运行时间_java中获得程序运行时间的方法(转)
  3. Elasticsearch7.x证书过期简单解决方法
  4. 小鸭五笔 3.3 版
  5. android 自定义 对号,【Android】自定义progressBar和动画显示对号
  6. VB.net byval和byref
  7. echarts 水滴图实现方式。
  8. 提升汽车APP用户体验,火山引擎APMPlus的“独家秘笈”
  9. 第六次作业·团队作业
  10. 南京标志设计-logo设计(品牌形象核心部分)