Python物流运输管理系统源代码,基于Django实现,实现了运单录入、发车出库、到货签收、客户签收等基本功能,含测试账号
Python物流运输管理系统源代码,基于Django实现,实现了运单录入、发车出库、到货签收、客户签收等基本功能,含测试账号。拥有较为完善的报表功能和财务管理功能。可以通过后台界面对各个用户进行权限管理。
程序运行截图



核心代码:
"""
Django settings for PPWuLiu project.
Generated by 'django-admin startproject' using Django 3.1.2.
For more information on this file, see
https://docs.djangoproject.com/en/3.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.1/ref/settings/
"""
import os
from pathlib import Path
from django.contrib.messages import constants
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# 创建日志的路径
LOG_PATH = os.path.join(BASE_DIR, "logs")
if not os.path.isdir(LOG_PATH):
if os.path.isfile(LOG_PATH):
os.remove(LOG_PATH)
os.makedirs(LOG_PATH)
# 启用Django Debug Toolbar
ENABLE_DJANGO_TOOLBAR = False
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.getenv("DJANGO_TMS_SECRET_KEY")
#SECRET_KEY = os.environ["SECRET_KEY"]
PBKDF2_ITERATIONS = 3
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
# 'channels',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 'rest_framework',
# 'django_filters',
'wuliu.apps.WuliuConfig',
'utils',
]
if DEBUG:
try:
import django_extensions
INSTALLED_APPS.append('django_extensions')
# print SQL queries in shell_plus
SHELL_PLUS_PRINT_SQL = True
except ImportError:
pass
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# Pyinstrument, 暂时不用, 因为Django Debug Toolbar更好用更强大
# if DEBUG:
# try:
# import pyinstrument
# MIDDLEWARE.append('pyinstrument.middleware.ProfilerMiddleware')
# except ImportError:
# pass
# Django Debug Toolbar
if ENABLE_DJANGO_TOOLBAR:
# debug_toolbar依赖于django.contrib.staticfiles
if DEBUG and 'django.contrib.staticfiles' in INSTALLED_APPS:
try:
import debug_toolbar
INSTALLED_APPS.append('debug_toolbar')
MIDDLEWARE.append('debug_toolbar.middleware.DebugToolbarMiddleware')
# Internal IPs
INTERNAL_IPS = [
'127.0.0.1',
]
except ImportError:
pass
ROOT_URLCONF = 'PPWuLiu.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'wuliu.processor.pros'
],
},
},
]
WSGI_APPLICATION = 'PPWuLiu.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': os.getenv("DJANGO_TMS_MYSQL_DATABASE_NAME"),
'USER': os.getenv("DJANGO_TMS_MYSQL_USER"),
'PASSWORD': os.getenv("DJANGO_TMS_MYSQL_PASSWORD"),
'HOST': os.getenv("DJANGO_TMS_MYSQL_HOST"),
'PORT': os.getenv("DJANGO_TMS_MYSQL_PORT"),
}
}
# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static")
]
# Custom
CACHES = {
'default': {
# 基于本地内存的缓存
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
}
}
# 关闭浏览器使会话立即过期
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
MESSAGE_TAGS = {
constants.ERROR: "danger",
}
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse',
},
'require_debug_true': {
'()': 'django.utils.log.RequireDebugTrue',
},
},
'handlers': {
'console': {
'level': 'INFO',
'filters': ['require_debug_true'],
'class': 'logging.StreamHandler',
},
# Unused
'file': {
'level': 'INFO',
'class': 'logging.FileHandler',
'filename': '%s/log.txt' % LOG_PATH,
'encoding': 'utf-8',
},
'request_exceptions': {
'level': 'INFO',
'class': 'logging.FileHandler',
'filename': '%s/request_exceptions.txt' % LOG_PATH,
'encoding': 'utf-8',
},
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
}
},
'loggers': {
'django': {
'handlers': ['console', 'mail_admins'],
'level': 'INFO',
},
'wuliu.apps': {
'handlers': ['request_exceptions'],
'level': 'INFO',
'propagate': True,
},
'utils.common.expire_lru_cache': {
'handlers': ['console'],
'level': 'INFO',
'propagate': True,
},
},
}
'''
# channels相关配置, 暂时不用
ASGI_APPLICATION = "PPWuLiu.asgi.application"
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
'hosts': [('127.0.0.1', 6379)],
},
},
}
'''
commn.py
from functools import wraps from django.shortcuts import redirect from django.http import Http404, HttpResponseForbidden from django.utils import timezone from .models import ( User, Waybill, TransportOut, DepartmentPayment, CargoPricePayment, Permission, PermissionGroup, _get_global_settings, ) from utils.common import ExpireLruCache, model_to_dict_ expire_lru_cache_three_hours = ExpireLruCache(expire_time=timezone.timedelta(hours=3)) expire_lru_cache_one_minute = ExpireLruCache(expire_time=timezone.timedelta(minutes=1)) get_global_settings = expire_lru_cache_three_hours(_get_global_settings) @expire_lru_cache_one_minute def _get_logged_user_by_id(user_id: int) -> User: """ 根据用户名返回用户模型对象 """ return User.objects.get(id=user_id) def get_logged_user(request) -> User: """ 获取已登录的用户对象 """ return _get_logged_user_by_id(request.session["user"]["id"]) def get_logged_user_type(request) -> User.Types: """ 获取已登录的用户的用户类型 """ return get_logged_user(request).get_type @expire_lru_cache_one_minute def _get_user_permissions(user: User) -> set: """ 获取用户拥有的权限, 注意该方法返回的是集合而不是QuerySet """ return set(user.permission.all().values_list("name", flat=True)) def is_logged_user_has_perm(request, perm_name: str) -> bool: """ 检查已登录用户是否具有perm_name权限 :return: True或False """ if not perm_name: return True return perm_name in _get_user_permissions(get_logged_user(request)) def is_logged_user_is_goods_yard(request) -> bool: """ 判断已登录的用户是否属于货场 """ return get_logged_user_type(request) == User.Types.GoodsYard def _gen_permission_tree_list(root_pg_=PermissionGroup.objects.get(father__isnull=True)) -> list: """ 根据所有的权限组和权限的层级结构生成列表, 用于前端渲染 """ tree_list = [] for pg in PermissionGroup.objects.filter(father=root_pg_): tree_list.append({ "id": pg.id, "name": pg.name, "print_name": pg.print_name, "children": _gen_permission_tree_list(pg) }) for p in Permission.objects.filter(father=root_pg_): tree_list.append({ "id": p.id, "name": p.name, "print_name": p.print_name, }) return tree_list PERMISSION_TREE_LIST = _gen_permission_tree_list() def login_required(raise_404=False): """ 自定义装饰器, 用于装饰路由方法 若用户未登录, 则跳转到登录页面 raise_404为True时, 则跳转到404页面 """ def _login_required(func): @wraps(func) def login_check(request, *args, **kwargs): if not request.session.get("user"): if raise_404: raise Http404 return redirect("wuliu:login") return func(request, *args, **kwargs) return login_check return _login_required def check_permission(perm_name: str): """ 自定义装饰器, 用于在请求前检查用户是否具有perm_name权限 若无perm_name权限则跳转至403页面 """ def _check_permission(func): @wraps(func) def perm_check(request, *args, **kwargs): if perm_name and not is_logged_user_has_perm(request, perm_name): return HttpResponseForbidden() return func(request, *args, **kwargs) return perm_check return _check_permission def check_administrator(func): """ 自定义装饰器, 用于在请求前检查用户是否为管理员 若不是管理员则跳转至403页面 """ @wraps(func) def admin_check(request, *args, **kwargs): if not get_logged_user(request).administrator: return HttpResponseForbidden() return func(request, *args, **kwargs) return admin_check def waybill_to_dict(waybill_obj: Waybill) -> dict: """ 将Waybill对象转为字典 """ waybill_dic = model_to_dict_(waybill_obj) waybill_dic["id_"] = waybill_obj.get_full_id waybill_dic["fee_type_id"] = waybill_dic["fee_type"] waybill_dic["fee_type"] = waybill_obj.get_fee_type_display() waybill_dic["status_id"] = waybill_dic["status"] waybill_dic["status"] = waybill_obj.get_status_display() if waybill_obj.return_waybill is not None: waybill_dic["return_waybill"] = waybill_to_dict(waybill_obj.return_waybill) else: waybill_dic["return_waybill"] = None return waybill_dic def transport_out_to_dict(transport_out_obj: TransportOut) -> dict: """ 将TransportOut对象转为字典 """ to_dic = model_to_dict_(transport_out_obj) to_dic["id_"] = transport_out_obj.get_full_id to_dic["status_id"] = to_dic["status"] to_dic["status"] = transport_out_obj.get_status_display() to_dic.update(transport_out_obj.gen_waybills_info()) return to_dic def department_payment_to_dict(department_payment_obj: DepartmentPayment) -> dict: """ 将DepartmentPayment对象转为字典 """ dp_dic = model_to_dict_(department_payment_obj) dp_dic["id_"] = department_payment_obj.get_full_id dp_dic["status_id"] = dp_dic["status"] dp_dic["status"] = department_payment_obj.get_status_display() total_fee_dic = department_payment_obj.gen_total_fee() dp_dic["total_fee_now"] = total_fee_dic["fee_now"] dp_dic["total_fee_sign_for"] = total_fee_dic["fee_sign_for"] dp_dic["total_cargo_price"] = total_fee_dic["cargo_price"] dp_dic["final_total_fee"] = sum(total_fee_dic.values()) return dp_dic def cargo_price_payment_to_dict(cargo_price_payment_obj: CargoPricePayment) -> dict: """ 将CargoPricePayment对象转为字典 """ cpp_dic = model_to_dict_(cargo_price_payment_obj) cpp_dic["id_"] = cargo_price_payment_obj.get_full_id cpp_dic["status_id"] = cpp_dic["status"] cpp_dic["status"] = cargo_price_payment_obj.get_status_display() total_fee_dic = cargo_price_payment_obj.gen_total_fee() cpp_dic["total_cargo_price"] = total_fee_dic["cargo_price"] cpp_dic["total_deduction_fee"] = total_fee_dic["deduction_fee"] cpp_dic["total_cargo_handling_fee"] = total_fee_dic["cargo_handling_fee"] cpp_dic["final_fee"] = ( total_fee_dic["cargo_price"] - total_fee_dic["deduction_fee"] - total_fee_dic["cargo_handling_fee"] ) return cpp_dic
测试数据账号密码如下:
#用户名 密码 用户类型 #csshd 666666 收货点 #csfgs 666666 分公司(到货点) #kj_1 666666 会计(财务部) #zxg_1 666666 货物装卸工1(货台) #zxg_2 666666 货物装卸工2(货台) #pzqqt 88888888 管理员

浙公网安备 33010602011771号