mirror of
https://github.com/leaders-of-digital-9-task/backend.git
synced 2024-11-22 01:16:33 +03:00
major fixes and updates
This commit is contained in:
parent
8c53cb6745
commit
dcac066a18
|
@ -1,11 +1,19 @@
|
|||
from dicom.api.views import (
|
||||
AddDicomProjectApi,
|
||||
CreateCircleApi,
|
||||
CreateFreeHandApi,
|
||||
CreateRoiApi,
|
||||
CreateRulerApi,
|
||||
DeleteDicomProjectApi,
|
||||
ListCreateDicomApi,
|
||||
ListCreateProjectApi,
|
||||
ListUpdateDicomImageNumberApi,
|
||||
RetrieveUpdateDeleteCircleApi,
|
||||
RetrieveUpdateDeleteDicomApi,
|
||||
RetrieveUpdateDeleteFreeHandApi,
|
||||
RetrieveUpdateDeleteProjectApi,
|
||||
RetrieveUpdateDeleteRoiApi,
|
||||
RetrieveUpdateDeleteRulerApi,
|
||||
SmartFileUploadApi,
|
||||
)
|
||||
from django.urls import include, path
|
||||
|
@ -39,11 +47,21 @@ urlpatterns = [
|
|||
CreateRoiApi.as_view(),
|
||||
name="create_roi",
|
||||
),
|
||||
path(
|
||||
"<str:slug>/free_hand",
|
||||
CreateFreeHandApi.as_view(),
|
||||
name="create_free_hand",
|
||||
),
|
||||
path(
|
||||
"<str:slug>/circle",
|
||||
CreateCircleApi.as_view(),
|
||||
name="create_circle",
|
||||
),
|
||||
path(
|
||||
"<str:slug>/ruler",
|
||||
CreateRulerApi.as_view(),
|
||||
name="create_ruler",
|
||||
),
|
||||
path(
|
||||
"<str:slug>/<int:layer>",
|
||||
ListUpdateDicomImageNumberApi.as_view(),
|
||||
|
@ -61,11 +79,44 @@ urlpatterns = [
|
|||
RetrieveUpdateDeleteRoiApi.as_view(),
|
||||
name="get_update_delete_roi",
|
||||
),
|
||||
path(
|
||||
"free_hand/<int:id>",
|
||||
RetrieveUpdateDeleteFreeHandApi.as_view(),
|
||||
name="get_update_delete_free_hand",
|
||||
),
|
||||
path(
|
||||
"circle/<int:id>",
|
||||
RetrieveUpdateDeleteCircleApi.as_view(),
|
||||
name="get_update_delete_circle",
|
||||
),
|
||||
path(
|
||||
"ruler/<int:id>",
|
||||
RetrieveUpdateDeleteRulerApi.as_view(),
|
||||
name="get_update_delete_ruler",
|
||||
),
|
||||
]
|
||||
),
|
||||
),
|
||||
path(
|
||||
"project/",
|
||||
include(
|
||||
[
|
||||
path("", ListCreateProjectApi.as_view(), name="list_create_project"),
|
||||
path(
|
||||
"<str:slug>",
|
||||
RetrieveUpdateDeleteProjectApi.as_view(),
|
||||
name="get_update_delete_project",
|
||||
),
|
||||
path(
|
||||
"<str:slug>/upload",
|
||||
AddDicomProjectApi.as_view(),
|
||||
name="add_dicom_api",
|
||||
),
|
||||
path(
|
||||
"<str:slug>/<str:dicom_slug>",
|
||||
DeleteDicomProjectApi.as_view(),
|
||||
name="delete_dicom_api",
|
||||
),
|
||||
]
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from dicom.models import Circle, Dicom, Roi
|
||||
from dicom.models import Circle, Dicom, FreeHand, Roi
|
||||
from django.contrib import admin
|
||||
|
||||
admin.site.register(Dicom)
|
||||
admin.site.register(Circle)
|
||||
admin.site.register(Roi)
|
||||
admin.site.register(FreeHand)
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
from dicom.models import Circle, Coordinate, Dicom, Roi
|
||||
from dicom.models import (
|
||||
BaseShape,
|
||||
Circle,
|
||||
Coordinate,
|
||||
Dicom,
|
||||
FreeHand,
|
||||
Project,
|
||||
Roi,
|
||||
Ruler,
|
||||
)
|
||||
from dicom.services import create_coordinate
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
from rest_framework import serializers
|
||||
from rest_framework.generics import get_object_or_404
|
||||
|
||||
|
||||
def create_coordinate(coordinates, obj):
|
||||
for coordinate in coordinates:
|
||||
Coordinate.objects.create(
|
||||
x=coordinate["x"],
|
||||
y=coordinate["y"],
|
||||
shape=obj,
|
||||
)
|
||||
|
||||
|
||||
class CoordinateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Coordinate
|
||||
|
@ -34,13 +35,43 @@ class ListDicomSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class BaseShapeSerializer(serializers.Serializer):
|
||||
type = serializers.ChoiceField(choices=["circle", "roi"])
|
||||
model = BaseShape
|
||||
|
||||
type = serializers.ChoiceField(choices=["circle", "roi", "free_hand"])
|
||||
image_number = serializers.IntegerField()
|
||||
coordinates = CoordinateSerializer(many=True)
|
||||
|
||||
def create(self, validated_data):
|
||||
if self.model.max_coordinates:
|
||||
if len(validated_data["coordinates"]) > self.model.max_coordinates:
|
||||
raise serializers.ValidationError
|
||||
if self.model.min_coordinates:
|
||||
if len(validated_data["coordinates"]) < self.model.min_coordinates:
|
||||
raise serializers.ValidationError
|
||||
dicom = get_object_or_404(
|
||||
Dicom, slug=self.context["request"].parser_context["kwargs"]["slug"]
|
||||
)
|
||||
obj = self.model.objects.create(
|
||||
dicom=dicom, image_number=validated_data["image_number"]
|
||||
)
|
||||
|
||||
create_coordinate(validated_data["coordinates"], obj)
|
||||
return obj
|
||||
|
||||
def update(self, obj, validated_data):
|
||||
Coordinate.objects.filter(shape=obj).delete()
|
||||
if self.model.max_coordinates:
|
||||
if len(validated_data["coordinates"]) > self.model.max_coordinates:
|
||||
raise serializers.ValidationError
|
||||
if self.model.min_coordinates:
|
||||
if len(validated_data["coordinates"]) < self.model.min_coordinates:
|
||||
raise serializers.ValidationError
|
||||
create_coordinate(validated_data["coordinates"], obj)
|
||||
return obj
|
||||
|
||||
|
||||
class BaseShapeLayerSerializer(serializers.Serializer):
|
||||
type = serializers.ChoiceField(choices=["circle", "roi"])
|
||||
type = serializers.ChoiceField(choices=["circle", "roi", "free_hand"])
|
||||
radius = serializers.FloatField(required=False)
|
||||
coordinates = CoordinateSerializer(many=True)
|
||||
|
||||
|
@ -58,31 +89,34 @@ class DicomSerializer(serializers.ModelSerializer):
|
|||
fields = ["file", "uploaded", "pathology_type", "shapes"]
|
||||
|
||||
|
||||
class RoiSerializer(serializers.ModelSerializer):
|
||||
class RoiSerializer(BaseShapeSerializer, serializers.ModelSerializer):
|
||||
coordinates = CoordinateSerializer(many=True)
|
||||
model = Roi
|
||||
|
||||
class Meta:
|
||||
model = Roi
|
||||
fields = ["id", "image_number", "coordinates"]
|
||||
extra_kwargs = {"id": {"read_only": True}}
|
||||
|
||||
def create(self, validated_data):
|
||||
if "coordinates" not in validated_data:
|
||||
raise serializers.ValidationError
|
||||
dicom = get_object_or_404(
|
||||
Dicom, slug=self.context["request"].parser_context["kwargs"]["slug"]
|
||||
)
|
||||
roi = Roi.objects.create(
|
||||
dicom=dicom, image_number=validated_data["image_number"]
|
||||
)
|
||||
|
||||
create_coordinate(validated_data["coordinates"], roi)
|
||||
return roi
|
||||
class FreeHandSerializer(BaseShapeSerializer, serializers.ModelSerializer):
|
||||
coordinates = CoordinateSerializer(many=True)
|
||||
model = FreeHand
|
||||
|
||||
def update(self, obj: Circle, validated_data):
|
||||
Coordinate.objects.filter(shape=obj).delete()
|
||||
create_coordinate(validated_data["coordinates"], obj)
|
||||
return obj
|
||||
class Meta:
|
||||
model = FreeHand
|
||||
fields = ["id", "image_number", "coordinates"]
|
||||
extra_kwargs = {"id": {"read_only": True}}
|
||||
|
||||
|
||||
class RulerSerializer(BaseShapeSerializer, serializers.ModelSerializer):
|
||||
coordinates = CoordinateSerializer(many=True)
|
||||
model = Ruler
|
||||
|
||||
class Meta:
|
||||
model = FreeHand
|
||||
fields = ["id", "image_number", "coordinates"]
|
||||
extra_kwargs = {"id": {"read_only": True}}
|
||||
|
||||
|
||||
class CircleSerializer(serializers.ModelSerializer):
|
||||
|
@ -122,3 +156,24 @@ class CircleSerializer(serializers.ModelSerializer):
|
|||
|
||||
class SmartFileUploadSerializer(serializers.Serializer):
|
||||
file = serializers.FileField()
|
||||
|
||||
|
||||
class ListProjectSerializer(serializers.ModelSerializer):
|
||||
url = serializers.HyperlinkedIdentityField(
|
||||
view_name="get_update_delete_project", lookup_field="slug"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Project
|
||||
fields = ["url", "created"]
|
||||
extra_kwargs = {
|
||||
"created": {"read_only": True},
|
||||
}
|
||||
|
||||
|
||||
class ProjectSerializer(serializers.ModelSerializer):
|
||||
files = ListDicomSerializer(many=True)
|
||||
|
||||
class Meta:
|
||||
model = Project
|
||||
fields = ["files", "created"]
|
||||
|
|
|
@ -5,15 +5,19 @@ from rest_framework.generics import GenericAPIView, get_object_or_404
|
|||
from rest_framework.parsers import FormParser, MultiPartParser
|
||||
from rest_framework.response import Response
|
||||
|
||||
from ..models import Circle, Dicom, Roi
|
||||
from ..models import Circle, Dicom, Project, Roi
|
||||
from ..services import process_files
|
||||
from .serializers import (
|
||||
BaseShapeLayerSerializer,
|
||||
BaseShapeSerializer,
|
||||
CircleSerializer,
|
||||
DicomSerializer,
|
||||
FreeHandSerializer,
|
||||
ListDicomSerializer,
|
||||
ListProjectSerializer,
|
||||
ProjectSerializer,
|
||||
RoiSerializer,
|
||||
RulerSerializer,
|
||||
SmartFileUploadSerializer,
|
||||
create_coordinate,
|
||||
)
|
||||
|
@ -41,55 +45,110 @@ class CreateRoiApi(generics.CreateAPIView):
|
|||
serializer_class = RoiSerializer
|
||||
|
||||
|
||||
class CreateFreeHandApi(generics.CreateAPIView):
|
||||
serializer_class = FreeHandSerializer
|
||||
|
||||
|
||||
class CreateCircleApi(generics.CreateAPIView):
|
||||
serializer_class = CircleSerializer
|
||||
|
||||
|
||||
class RetrieveUpdateDeleteRoiApi(generics.RetrieveUpdateDestroyAPIView):
|
||||
class CreateRulerApi(generics.CreateAPIView):
|
||||
serializer_class = RulerSerializer
|
||||
|
||||
|
||||
class RetrieveUpdateDeleteBaseShape(generics.RetrieveUpdateDestroyAPIView):
|
||||
def get_object(self):
|
||||
return get_object_or_404(
|
||||
self.serializer_class.Meta.model,
|
||||
id=self.request.parser_context["kwargs"]["id"],
|
||||
)
|
||||
|
||||
@extend_schema(description="Note: coordinated are dropped on update")
|
||||
def put(self, request, *args, **kwargs):
|
||||
return self.update(request, *args, **kwargs)
|
||||
|
||||
@extend_schema(description="Note: coordinated are dropped on update")
|
||||
def patch(self, request, *args, **kwargs):
|
||||
return self.partial_update(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RetrieveUpdateDeleteRoiApi(RetrieveUpdateDeleteBaseShape):
|
||||
serializer_class = RoiSerializer
|
||||
|
||||
def get_object(self):
|
||||
return get_object_or_404(Roi, id=self.request.parser_context["kwargs"]["id"])
|
||||
|
||||
@extend_schema(description="Note: coordinated are dropped on update")
|
||||
def put(self, request, *args, **kwargs):
|
||||
return self.update(request, *args, **kwargs)
|
||||
|
||||
@extend_schema(description="Note: coordinated are dropped on update")
|
||||
def patch(self, request, *args, **kwargs):
|
||||
return self.partial_update(request, *args, **kwargs)
|
||||
class RetrieveUpdateDeleteFreeHandApi(RetrieveUpdateDeleteBaseShape):
|
||||
serializer_class = FreeHandSerializer
|
||||
|
||||
|
||||
class RetrieveUpdateDeleteCircleApi(generics.RetrieveUpdateDestroyAPIView):
|
||||
class RetrieveUpdateDeleteCircleApi(RetrieveUpdateDeleteBaseShape):
|
||||
serializer_class = CircleSerializer
|
||||
|
||||
def get_object(self):
|
||||
return get_object_or_404(Circle, id=self.request.parser_context["kwargs"]["id"])
|
||||
|
||||
@extend_schema(description="Note: coordinated are dropped on update")
|
||||
def patch(self, request, *args, **kwargs):
|
||||
return self.partial_update(request, *args, **kwargs)
|
||||
|
||||
@extend_schema(description="Note: coordinated are dropped on update")
|
||||
def put(self, request, *args, **kwargs):
|
||||
return self.update(request, *args, **kwargs)
|
||||
class RetrieveUpdateDeleteRulerApi(RetrieveUpdateDeleteBaseShape):
|
||||
serializer_class = CircleSerializer
|
||||
|
||||
|
||||
class SmartFileUploadApi(GenericAPIView):
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
serializer_class = SmartFileUploadSerializer
|
||||
|
||||
@extend_schema(responses={201: DicomSerializer(many=True)})
|
||||
@extend_schema(responses={201: ListDicomSerializer(many=True)})
|
||||
def post(self, request):
|
||||
if "file" not in request.data:
|
||||
raise ValidationError("no files")
|
||||
d_list = process_files(request.FILES.getlist("file"), request.user)
|
||||
project = process_files(
|
||||
request.FILES.getlist("file"),
|
||||
request.user,
|
||||
)
|
||||
return Response(
|
||||
DicomSerializer(d_list.files.all(), many=True).data,
|
||||
ListDicomSerializer(project.files.all(), many=True).data,
|
||||
status=status.HTTP_201_CREATED,
|
||||
)
|
||||
|
||||
|
||||
class AddDicomProjectApi(GenericAPIView):
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
serializer_class = SmartFileUploadSerializer
|
||||
|
||||
@extend_schema(
|
||||
operation_id="add_dicom_to_project",
|
||||
responses={201: ListDicomSerializer(many=True)},
|
||||
)
|
||||
def post(self, request, slug):
|
||||
if "file" not in request.data:
|
||||
raise ValidationError("no files")
|
||||
get_object_or_404(Project, slug=slug)
|
||||
project = process_files(
|
||||
request.FILES.getlist("file"),
|
||||
request.user,
|
||||
slug,
|
||||
)
|
||||
return Response(
|
||||
ListDicomSerializer(project.files.all(), many=True).data,
|
||||
status=status.HTTP_201_CREATED,
|
||||
)
|
||||
|
||||
|
||||
class DeleteDicomProjectApi(GenericAPIView):
|
||||
serializer_class = SmartFileUploadSerializer
|
||||
|
||||
@extend_schema(
|
||||
operation_id="add_dicom_to_project",
|
||||
request=None,
|
||||
responses={200: ListDicomSerializer(many=True)},
|
||||
)
|
||||
def delete(self, request, slug, dicom_slug):
|
||||
project = get_object_or_404(Project, slug=slug)
|
||||
project.files.filter(slug=dicom_slug).delete()
|
||||
return Response(
|
||||
ListDicomSerializer(
|
||||
project.files.all(), many=True, context={"request": request}
|
||||
).data,
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
|
||||
class ListUpdateDicomImageNumberApi(GenericAPIView):
|
||||
serializer_class = BaseShapeSerializer(many=True)
|
||||
|
||||
|
@ -134,3 +193,27 @@ class ListUpdateDicomImageNumberApi(GenericAPIView):
|
|||
)
|
||||
]
|
||||
return Response(shapes, status=status.HTTP_200_OK)
|
||||
|
||||
@extend_schema(
|
||||
request=None,
|
||||
responses={204: None},
|
||||
operation_id="delete_dicom_layer",
|
||||
)
|
||||
def delete(self, request, slug, layer):
|
||||
dicom = get_object_or_404(Dicom, slug=slug)
|
||||
dicom.shapes.filter(image_number=layer).delete()
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
class ListCreateProjectApi(generics.ListCreateAPIView):
|
||||
serializer_class = ListProjectSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return Project.objects.filter(user=self.request.user)
|
||||
|
||||
|
||||
class RetrieveUpdateDeleteProjectApi(generics.RetrieveUpdateDestroyAPIView):
|
||||
serializer_class = ProjectSerializer
|
||||
queryset = Project.objects.all()
|
||||
|
||||
lookup_field = "slug"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# flake8: noqa
|
||||
from .base import Dicom, ListOfDicom
|
||||
from .blocks import BaseShape, Circle, Coordinate, Roi
|
||||
from .base import Dicom, Project
|
||||
from .shapes import BaseShape, Circle, Coordinate, FreeHand, Roi, Ruler
|
||||
|
|
|
@ -6,8 +6,14 @@ from utils.files import media_upload_path
|
|||
User = get_user_model()
|
||||
|
||||
|
||||
class ListOfDicom(models.Model):
|
||||
pass
|
||||
class Project(models.Model):
|
||||
user = models.ForeignKey(User, related_name="projects", on_delete=models.CASCADE)
|
||||
slug = models.SlugField(max_length=10)
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.user.username}'s project"
|
||||
|
||||
|
||||
class Dicom(models.Model):
|
||||
|
@ -22,8 +28,8 @@ class Dicom(models.Model):
|
|||
uploaded = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
pathology_type = models.IntegerField(choices=PathologyType.choices, default=0)
|
||||
list = models.ForeignKey(
|
||||
ListOfDicom, related_name="files", null=True, on_delete=models.SET_NULL
|
||||
project = models.ForeignKey(
|
||||
Project, related_name="files", null=True, on_delete=models.SET_NULL
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
@ -4,11 +4,26 @@ from polymorphic.models import PolymorphicModel
|
|||
|
||||
|
||||
class BaseShape(PolymorphicModel):
|
||||
TYPE = "no_type"
|
||||
min_coordinates = None
|
||||
max_coordinates = None
|
||||
dicom = models.ForeignKey(Dicom, related_name="shapes", on_delete=models.CASCADE)
|
||||
image_number = models.IntegerField()
|
||||
|
||||
def serialize_self(self):
|
||||
raise NotImplementedError
|
||||
return {
|
||||
"id": self.id,
|
||||
"type": self.TYPE,
|
||||
"image_number": self.image_number,
|
||||
"coordinates": self.coordinates,
|
||||
}
|
||||
|
||||
def serialize_self_without_layer(self):
|
||||
return {
|
||||
"id": self.id,
|
||||
"type": self.TYPE,
|
||||
"coordinates": self.coordinates,
|
||||
}
|
||||
|
||||
@property
|
||||
def coordinates(self) -> [(int, int)]:
|
||||
|
@ -33,6 +48,7 @@ class Coordinate(models.Model):
|
|||
|
||||
class Circle(BaseShape):
|
||||
radius = models.FloatField()
|
||||
max_coordinates = 1
|
||||
|
||||
def serialize_self(self):
|
||||
return {
|
||||
|
@ -56,21 +72,23 @@ class Circle(BaseShape):
|
|||
|
||||
|
||||
class Roi(BaseShape):
|
||||
def serialize_self(self):
|
||||
return {
|
||||
"id": self.id,
|
||||
"type": "roi",
|
||||
"image_number": self.image_number,
|
||||
"coordinates": self.coordinates,
|
||||
}
|
||||
|
||||
def serialize_self_without_layer(self):
|
||||
return {
|
||||
"id": self.id,
|
||||
"type": "roi",
|
||||
"radius": self.radius,
|
||||
"coordinates": self.coordinates,
|
||||
}
|
||||
TYPE = "roi"
|
||||
|
||||
def __str__(self):
|
||||
return f"Roi on {self.dicom.file.name}"
|
||||
|
||||
|
||||
class FreeHand(BaseShape):
|
||||
TYPE = "free_hand"
|
||||
|
||||
def __str__(self):
|
||||
return f"FreeHand on {self.dicom.file.name}"
|
||||
|
||||
|
||||
class Ruler(BaseShape):
|
||||
TYPE = "ruler"
|
||||
max_coordinates = 2
|
||||
min_coordinates = 2
|
||||
|
||||
def __str__(self):
|
||||
return f"Ruler on {self.dicom.file.name}"
|
|
@ -5,18 +5,23 @@ import zipfile
|
|||
from pathlib import Path
|
||||
|
||||
import magic
|
||||
from dicom.models import Dicom, ListOfDicom
|
||||
from dicom.models import Coordinate, Dicom, Project
|
||||
from django.core.files import File
|
||||
from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile
|
||||
from utils.generators import generate_charset
|
||||
|
||||
|
||||
def process_files(files: list[TemporaryUploadedFile | InMemoryUploadedFile], user):
|
||||
d_list = ListOfDicom.objects.create()
|
||||
def process_files(
|
||||
files: list[TemporaryUploadedFile | InMemoryUploadedFile], user, slug=None
|
||||
):
|
||||
if slug:
|
||||
project = Project.objects.get(slug=slug)
|
||||
else:
|
||||
project = Project.objects.create(user=user)
|
||||
for file in files:
|
||||
content_type = magic.from_file(file.temporary_file_path())
|
||||
if content_type == "DICOM medical imaging data":
|
||||
Dicom.objects.create(file=file, list=d_list, user=user)
|
||||
Dicom.objects.create(file=file, project=project, user=user)
|
||||
elif "Zip" in content_type:
|
||||
dit_path = f"/tmp/{generate_charset(10)}"
|
||||
os.mkdir(dit_path)
|
||||
|
@ -32,8 +37,17 @@ def process_files(files: list[TemporaryUploadedFile | InMemoryUploadedFile], use
|
|||
with path.open(mode="rb") as f:
|
||||
Dicom.objects.create(
|
||||
file=File(f, name=file_in_d.split("/")[-1]),
|
||||
list=d_list,
|
||||
project=project,
|
||||
user=user,
|
||||
)
|
||||
shutil.rmtree(dit_path)
|
||||
return d_list
|
||||
return project
|
||||
|
||||
|
||||
def create_coordinate(coordinates, obj):
|
||||
for coordinate in coordinates:
|
||||
Coordinate.objects.create(
|
||||
x=coordinate["x"],
|
||||
y=coordinate["y"],
|
||||
shape=obj,
|
||||
)
|
||||
|
|
|
@ -1,12 +1,24 @@
|
|||
from dicom.models import Dicom
|
||||
from django.db.models.signals import pre_save
|
||||
from dicom.models import Dicom, Project
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from utils.generators import generate_charset
|
||||
|
||||
|
||||
@receiver(pre_save, sender=Dicom)
|
||||
def create_dicom(sender, instance: Dicom, **kwargs):
|
||||
slug = generate_charset(5)
|
||||
while Dicom.objects.filter(slug=slug):
|
||||
@receiver(post_save, sender=Project)
|
||||
def create_project(sender, instance: Project, created, **kwargs):
|
||||
if created:
|
||||
slug = generate_charset(5)
|
||||
instance.slug = slug
|
||||
while Project.objects.filter(slug=slug):
|
||||
slug = generate_charset(5)
|
||||
instance.slug = slug
|
||||
instance.save()
|
||||
|
||||
|
||||
@receiver(post_save, sender=Dicom)
|
||||
def create_dicom(sender, instance: Dicom, created, **kwargs):
|
||||
if created:
|
||||
slug = generate_charset(5)
|
||||
while Dicom.objects.filter(slug=slug):
|
||||
slug = generate_charset(5)
|
||||
instance.slug = slug
|
||||
instance.save()
|
||||
|
|
Loading…
Reference in New Issue
Block a user