Django 简易PACS读片系统

1、Django中写一个后端接口,给HTML提供dicom文件接口的方式

1、首先创建django项目

1、下载安装跨域的包
复制代码
pip3 install django-cors-headers
2、使用pycharm创建一个Django项目
3、点击创建在另一个窗口,这个都无所谓,怎么都行,就是打开这个项目
4、创建成功的项目就是下面这个样子
5、先修改几个选项,后面好操作

下面是我的settings设置,我把修改的地方标注出来

复制代码
"""
Django settings for pacsdemo project.

Generated by 'django-admin startproject' using Django 3.2.18.

For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""
# 添加这个import os
import os
from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-uv!_mka##8#citwx_q$o71)@!8tfaa-6wyrb!h8&4fm+m-=-d='

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
# 设置所有IP都可以访问,局域网
ALLOWED_HOSTS = ['*']

# Application definition

# 添加跨域设置
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'pacs.apps.PacsConfig',
    'corsheaders'  # 跨域设置
]

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',
]

# 新添加的设置
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_ALL_ORIGINS = False
CORS_ORIGIN_WHITELIST = [
    "http://192.168.0.30:8000",
    "http://localhost:63409",
]
CORS_ORIGIN_ALLOW_ALL = True

CORS_ALLOW_METHODS = (
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
    'VIEW'
)

CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
)


ROOT_URLCONF = 'pacsdemo.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates']
        ,
        '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',
            ],
        },
    },
]

WSGI_APPLICATION = 'pacsdemo.wsgi.application'

# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

# 连接本地的mysql数据库
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'pacsdemo',   #  你的数据库名称
        'USER': '******',  # 你的账户
        'PASSWORD': '******',  #你的密码
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

# Password validation
# https://docs.djangoproject.com/en/3.2/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.2/topics/i18n/

# 设置时间,上海的时间
LANGUAGE_CODE = 'zh-Hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = False

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/

# 加载静态文件的设置
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
6、把表结构映射到数据库中

连接数据库的设置,没有这个设置,数据库会连接失败

复制代码
import pymysql
pymysql.install_as_MySQLdb()
7、在终端运行两行命令
复制代码
python manage.py makemigrations
8、运行第二行命令
复制代码
python manage.py migrate
9、第一步完成,数据库连接成功,基础设置完成

2、写前端页面,并且和后端接口,传递单个dicom文件,并且显示出来

1、先添加一个路由

复制代码
from django.conf.urls import include

2、然后在pacs中写urls.py里面的内容

复制代码
from django.urls import path

from . import views

urlpatterns = [
    path("index/", views.index),  # 设置首页内容
    path("read/", views.read),  # 读dicom文件
    path("read1/", views.read1),  # 读dicom文件
]

3、写这个index的方法,在views.py中

复制代码
from django.shortcuts import render
from django.http import HttpResponse, FileResponse


# Create your views here.
def index(request):
    return render(request, 'index.html')


def read(request):
    file = open('static/dicom/C9214289', 'rb')
    response = FileResponse(file)
    response['Content-Type'] = 'application/octet-stream'
    response['Content-Disposition'] = 'attachment;filename="1.dcm"'
    return response


def read1(request):
    file = open('static/dicom/C9214530', 'rb')
    response = FileResponse(file)
    response['Content-Type'] = 'application/octet-stream'
    response['Content-Disposition'] = 'attachment;filename="2.dcm"'
    return response

4、写index.html的内容

我写的这个html,直接放进去就可以看,其中的内容你可以通过cornerstone.js查看

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>pacs</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>


    <script type="text/javascript">

        // 阻止右键点击事件的默认行为
        document.addEventListener('contextmenu', function (event) {
            event.preventDefault();
        });
    </script>
    <script>
        // 监听双击事件,并阻止默认的缩放行为
        document.addEventListener('dblclick', function (event) {
            event.preventDefault();
        });
        document.addEventListener('touchstart', function (event) {
            if (event.touches.length > 1) {
                event.preventDefault();
            }
        }, {passive: false});
    </script>
</head>
<body>
<div>
    <h2>全部都是鼠标左键的操作</h2>
    <button id="wwwc">切换窗宽窗位</button>
    <button id="length">切换测量长度</button>
    <button id="rotate">旋转</button>
    <button id="magnify">透视</button>
    <button id="pan">移动</button>
    <br/>
    <button id="scaleoverlay">尺度</button>
    <button id="zoom">放大</button>
    <button id="angle">测量角度</button>
    <button id="arrowannotate">添加备注</button>
    <button id="bidirectional">交叉线</button>
    <br/>
    <button id="cobbangle">心胸比</button>
    <button id="ellipticalroi">圆</button>
    <button id="freehandroi">随便画</button>
    <button id="probe">探针</button>
    <button id="rectangleroi">方形</button>
    <br/>
    <button id="circlescissors">画圆</button>
    <button id="rectanglescissors">画正方形</button>
</div>
<div id="dicomImage" style="width: 512px;height: 512px;position: absolute"></div>

</body>
<!-- 触控的方法 -->
<script src="https://unpkg.com/hammerjs@2.0.8/hammer.js"></script>
<!-- 基石包,核心包 -->
<script src="https://unpkg.com/cornerstone-core@2.6.1/dist/cornerstone.js"></script>
<!-- Math包,数学包 -->
<script src="https://unpkg.com/cornerstone-math@0.1.10/dist/cornerstoneMath.min.js"></script>
<!-- 图片解析包,解析dcm文件的 -->
<script src="https://unpkg.com/cornerstone-wado-image-loader@4.13.2/dist/cornerstoneWADOImageLoader.bundle.min.js"></script>
<!-- 解析普通图的方法 -->
<script src="https://unpkg.com/cornerstone-web-image-loader@2.1.1/dist/cornerstoneWebImageLoader.min.js"></script>
<!-- 写好方法的包 -->
<script src="https://unpkg.com/cornerstone-tools@6.0.10/dist/cornerstoneTools.js"></script>
<!-- 解析dicom的json信息 -->
<script src="https://unpkg.com/dicom-parser@1.8.21/dist/dicomParser.min.js"></script>

<script>
    cornerstoneTools.external.cornerstone = cornerstone;
    cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
    cornerstoneTools.external.Hammer = Hammer;
    cornerstoneWADOImageLoader.external.dicomParser = dicomParser;
    cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
    // 'dicomweb' 网页上的一种解析的包, http开头的网址 ,获取dicom的文件,并且显示出来
    var imageId = "wadouri:http://127.0.0.1:8000/read";
    var imageIds = ["wadouri:http://127.0.0.1:8000/read", "wadouri:http://127.0.0.1:8000/read1"]

    // 定义stack滚动工具
    const StackScrollMouseWheelTool = cornerstoneTools.StackScrollMouseWheelTool
    // Add our tool, and set it's mode
    const StackScrollTool = cornerstoneTools.StackScrollTool
    //define the stack
    // 设置一个栈
    const stack = {
        currentImageIdIndex: 0,
        imageIds
    }

    // 默认初始化tools
    cornerstoneTools.init()
    // 获取页面显示的dicom id
    var element = document.getElementById('dicomImage');
    cornerstone.enable(element)

    // 测量长度
    const LengthTool = cornerstoneTools.LengthTool;
    cornerstoneTools.addTool(LengthTool)
    // cornerstoneTools.setToolActive('Length', {mouseButtonMask: 1})
    // wwwc
    const WwwcTool = cornerstoneTools.WwwcTool;
    cornerstoneTools.addTool(WwwcTool)
    // cornerstoneTools.setToolActive('Wwwc', {mouseButtonMask: 1})

    // 旋转
    const RotateTool = cornerstoneTools.RotateTool;
    cornerstoneTools.addTool(RotateTool)
    // 透视
    const MagnifyTool = cornerstoneTools.MagnifyTool;
    cornerstoneTools.addTool(MagnifyTool)
    // 移动
    const PanTool = cornerstoneTools.PanTool;
    cornerstoneTools.addTool(PanTool)
    // 尺度
    const ScaleOverlayTool = cornerstoneTools.ScaleOverlayTool;
    cornerstoneTools.addTool(ScaleOverlayTool)
    // 放大
    const ZoomTool = cornerstoneTools.ZoomTool;
    cornerstoneTools.addTool(cornerstoneTools.ZoomTool, {
        // Optional configuration
        configuration: {
            invert: false,
            preventZoomOutsideImage: false,
            minScale: .1,
            maxScale: 20.0,
        }
    });
    // 测量角度
    const AngleTool = cornerstoneTools.AngleTool;
    cornerstoneTools.addTool(AngleTool)

    // 添加备注
    const ArrowAnnotateTool = cornerstoneTools.ArrowAnnotateTool;
    cornerstoneTools.addTool(ArrowAnnotateTool)
    // 交叉线
    const BidirectionalTool = cornerstoneTools.BidirectionalTool;
    cornerstoneTools.addTool(BidirectionalTool)
    // 心胸比
    const CobbAngleTool = cornerstoneTools.CobbAngleTool;
    cornerstoneTools.addTool(CobbAngleTool)
    // 圆
    const EllipticalRoiTool = cornerstoneTools.EllipticalRoiTool;
    cornerstoneTools.addTool(EllipticalRoiTool)
    // 画笔
    const FreehandRoiTool = cornerstoneTools.FreehandRoiTool;
    cornerstoneTools.addTool(FreehandRoiTool)
    // 探针
    const ProbeTool = cornerstoneTools.ProbeTool;
    cornerstoneTools.addTool(ProbeTool)
    // 正方形长方形
    const RectangleRoiTool = cornerstoneTools.RectangleRoiTool;
    cornerstoneTools.addTool(RectangleRoiTool)
    // 直接画圆
    const CircleScissorsTool = cornerstoneTools.CircleScissorsTool;
    cornerstoneTools.addTool(CircleScissorsTool)
    // 通过正方形涂
    const RectangleScissorsTool = cornerstoneTools.RectangleScissorsTool;

    cornerstoneTools.addTool(RectangleScissorsTool)


    // 鼠标中键滚动
    cornerstone.loadAndCacheImage(imageIds[0]).then(function (image) {
        cornerstone.displayImage(element, image)
        cornerstoneTools.addStackStateManager(element, ['stack'])
        cornerstoneTools.addToolState(element, 'stack', stack)
    })

    cornerstoneTools.addTool(StackScrollMouseWheelTool)
    cornerstoneTools.setToolActive('StackScrollMouseWheel', {})

    function disableAllTools() {
        // 取消左键的功能
        cornerstoneTools.setToolDisabled('Length')
        cornerstoneTools.setToolDisabled('Wwwc')
        cornerstoneTools.setToolDisabled('Rotate')
        cornerstoneTools.setToolDisabled('Magnify')
        cornerstoneTools.setToolDisabled('ScaleOverlay')
        cornerstoneTools.setToolDisabled('Zoom')
        cornerstoneTools.setToolDisabled('Angle')
        cornerstoneTools.setToolDisabled('ArrowAnnotate')
        cornerstoneTools.setToolDisabled('Pan')
        cornerstoneTools.setToolDisabled('Bidirectional')
        cornerstoneTools.setToolDisabled('CobbAngle')
        cornerstoneTools.setToolDisabled('EllipticalRoi')
        cornerstoneTools.setToolDisabled('FreehandRoi')
        cornerstoneTools.setToolDisabled('Probe')
        cornerstoneTools.setToolDisabled('RectangleRoi')
        cornerstoneTools.setToolDisabled('CircleScissors')
        cornerstoneTools.setToolDisabled('RectangleScissors')
    }

    document.getElementById("wwwc").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活窗宽窗位
        cornerstoneTools.setToolActive("Wwwc", {mouseButtonMask: 1})

    })
    document.getElementById("length").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活测量长度
        cornerstoneTools.setToolActive("Length", {mouseButtonMask: 1})

    })
    document.getElementById("rotate").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活旋转
        cornerstoneTools.setToolActive("Rotate", {mouseButtonMask: 1})

    })
    document.getElementById("magnify").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活透视
        cornerstoneTools.setToolActive("Magnify", {mouseButtonMask: 1})

    })
    document.getElementById("pan").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 移动
        cornerstoneTools.setToolActive("Pan", {mouseButtonMask: 1})

    })
    document.getElementById("scaleoverlay").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 尺子
        cornerstoneTools.setToolActive("ScaleOverlay", {mouseButtonMask: 1})

    })
    document.getElementById("zoom").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 放大
        cornerstoneTools.setToolActive("Zoom", {mouseButtonMask: 1})

    })
    document.getElementById("angle").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 角度
        cornerstoneTools.setToolActive("Angle", {mouseButtonMask: 1})

    })
    document.getElementById("arrowannotate").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 添加备注
        cornerstoneTools.setToolActive("ArrowAnnotate", {mouseButtonMask: 1})

    })
    document.getElementById("bidirectional").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活交叉线
        cornerstoneTools.setToolActive("Bidirectional", {mouseButtonMask: 1})

    })
    document.getElementById("cobbangle").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活心胸比
        cornerstoneTools.setToolActive("CobbAngle", {mouseButtonMask: 1})

    })
    document.getElementById("ellipticalroi").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 圆
        cornerstoneTools.setToolActive("EllipticalRoi", {mouseButtonMask: 1})

    })
    document.getElementById("freehandroi").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 随便画
        cornerstoneTools.setToolActive("FreehandRoi", {mouseButtonMask: 1})

    })
    document.getElementById("probe").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 探针
        cornerstoneTools.setToolActive("Probe", {mouseButtonMask: 1})

    })
    document.getElementById("rectangleroi").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 方形
        cornerstoneTools.setToolActive("RectangleRoi", {mouseButtonMask: 1})

    })
    document.getElementById("circlescissors").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 方形
        cornerstoneTools.setToolActive("CircleScissors", {mouseButtonMask: 1})

    })
    document.getElementById("rectanglescissors").addEventListener('click', function () {
        // 取消左键原来的功能
        disableAllTools();
        // 激活 方形
        cornerstoneTools.setToolActive("RectangleScissors", {mouseButtonMask: 1})

    })

</script>

</html>

5、启动项目

1、第一种,通过pycharm打开

2、第二种,命令行的方式
复制代码
python manage.py runserver

5、查看网页

其中的功能都可以进行操作,后续我进行优化,默认滚动条是切换dicom

复制代码
http://127.0.0.1:8000/index/

6、成功

相关推荐
qq_2290580112 小时前
运行djando项目 配置启动类 label_studio包含前后端启动方法
python·django
码界奇点15 小时前
基于Python与Django的白泽自动化运维系统设计与实现
运维·python·django·毕业设计·源代码管理
计算机毕业编程指导师15 小时前
【Python大数据选题】基于Spark+Django的电影评分人气数据可视化分析系统源码 毕业设计 选题推荐 毕设选题 数据分析 机器学习
大数据·hadoop·python·计算机·spark·django·电影评分人气
Python极客之家16 小时前
基于Django的高校二手市场与社交系统
后端·python·数据挖掘·django·毕业设计
码界奇点17 小时前
基于Django与Zabbix集成的运维故障管理系统设计与实现
运维·django·毕业设计·zabbix·源代码管理
码界奇点17 小时前
基于Django与Ansible的自动化运维管理系统设计与实现
运维·python·django·毕业设计·ansible·源代码管理
U盘失踪了17 小时前
Django 学生成绩管理系统
django
倔强青铜三3 天前
Django 6.0来袭!这些新特性,真的令人振奋!
人工智能·python·django
Java水解3 天前
Django实现接口token检测的实现方案
后端·django
飞Link3 天前
【Django】Django 调用外部 Python 程序的完整指南
后端·python·django·sqlite