bx-865-apps #1

Merged
ksenia_mikhailova merged 140 commits from bx-865-apps into main 2024-06-27 15:03:27 +03:00
14 changed files with 404 additions and 101 deletions
Showing only changes of commit 85e55282a0 - Show all commits

View File

@ -392,6 +392,15 @@
"detail": "unittest", "detail": "unittest",
"documentation": {} "documentation": {}
}, },
{
"label": "io",
"kind": 6,
"isExtraImport": true,
"importPath": "io",
"description": "io",
"detail": "io",
"documentation": {}
},
{ {
"label": "StringIO", "label": "StringIO",
"importPath": "io", "importPath": "io",
@ -1612,6 +1621,54 @@
"detail": "django.db", "detail": "django.db",
"documentation": {} "documentation": {}
}, },
{
"label": "migrations",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "models",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "migrations",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "models",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "migrations",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{
"label": "models",
"importPath": "django.db",
"description": "django.db",
"isExtraImport": true,
"detail": "django.db",
"documentation": {}
},
{ {
"label": "models", "label": "models",
"importPath": "django.db", "importPath": "django.db",
@ -1677,35 +1734,30 @@
"documentation": {} "documentation": {}
}, },
{ {
"label": "Image", "label": "base64",
"importPath": "PIL", "kind": 6,
"description": "PIL",
"isExtraImport": true, "isExtraImport": true,
"detail": "PIL", "importPath": "base64",
"description": "base64",
"detail": "base64",
"documentation": {} "documentation": {}
}, },
{ {
"label": "Bitmap", "label": "cv2",
"importPath": "potrace", "kind": 6,
"description": "potrace",
"isExtraImport": true, "isExtraImport": true,
"detail": "potrace", "importPath": "cv2",
"description": "cv2",
"detail": "cv2",
"documentation": {} "documentation": {}
}, },
{ {
"label": "POTRACE_TURNPOLICY_MINORITY", "label": "numpy",
"importPath": "potrace", "kind": 6,
"description": "potrace",
"isExtraImport": true, "isExtraImport": true,
"detail": "potrace", "importPath": "numpy",
"documentation": {} "description": "numpy",
}, "detail": "numpy",
{
"label": "render",
"importPath": "django.shortcuts",
"description": "django.shortcuts",
"isExtraImport": true,
"detail": "django.shortcuts",
"documentation": {} "documentation": {}
}, },
{ {
@ -1717,19 +1769,19 @@
"documentation": {} "documentation": {}
}, },
{ {
"label": "csrf_exempt", "label": "MultiPartParser",
"importPath": "django.views.decorators.csrf", "importPath": "rest_framework.parsers",
"description": "django.views.decorators.csrf", "description": "rest_framework.parsers",
"isExtraImport": true, "isExtraImport": true,
"detail": "django.views.decorators.csrf", "detail": "rest_framework.parsers",
"documentation": {} "documentation": {}
}, },
{ {
"label": "HttpResponse", "label": "APIView",
"importPath": "django.http", "importPath": "rest_framework.views",
"description": "django.http", "description": "rest_framework.views",
"isExtraImport": true, "isExtraImport": true,
"detail": "django.http", "detail": "rest_framework.views",
"documentation": {} "documentation": {}
}, },
{ {
@ -1740,6 +1792,30 @@
"detail": "django.http", "detail": "django.http",
"documentation": {} "documentation": {}
}, },
{
"label": "parse_image",
"importPath": "api.tracer",
"description": "api.tracer",
"isExtraImport": true,
"detail": "api.tracer",
"documentation": {}
},
{
"label": "read_image",
"importPath": "api.tracer",
"description": "api.tracer",
"isExtraImport": true,
"detail": "api.tracer",
"documentation": {}
},
{
"label": "numpy_zip_str_to_arr",
"importPath": "api.tracer",
"description": "api.tracer",
"isExtraImport": true,
"detail": "api.tracer",
"documentation": {}
},
{ {
"label": "get_asgi_application", "label": "get_asgi_application",
"importPath": "django.core.asgi", "importPath": "django.core.asgi",
@ -1788,6 +1864,14 @@
"detail": "api", "detail": "api",
"documentation": {} "documentation": {}
}, },
{
"label": "csrf_exempt",
"importPath": "django.views.decorators.csrf",
"description": "django.views.decorators.csrf",
"isExtraImport": true,
"detail": "django.views.decorators.csrf",
"documentation": {}
},
{ {
"label": "get_wsgi_application", "label": "get_wsgi_application",
"importPath": "django.core.wsgi", "importPath": "django.core.wsgi",
@ -8344,10 +8428,37 @@
"kind": 6, "kind": 6,
"importPath": "back.api.migrations.0007_floorplan_alter_product_image1_alter_product_image2_and_more", "importPath": "back.api.migrations.0007_floorplan_alter_product_image1_alter_product_image2_and_more",
"description": "back.api.migrations.0007_floorplan_alter_product_image1_alter_product_image2_and_more", "description": "back.api.migrations.0007_floorplan_alter_product_image1_alter_product_image2_and_more",
"peekOfCode": "class Migration(migrations.Migration):\n dependencies = [\n ('api', '0006_product_image2_product_image3'),\n ]\n operations = [\n migrations.CreateModel(\n name='FloorPlan',\n fields=[\n ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n ('title', models.CharField(max_length=200)),", "peekOfCode": "class Migration(migrations.Migration):\n dependencies = [\n ('api', '0006_product_image2_product_image3'),\n ]\n operations = [\n migrations.CreateModel(\n name='Floorplan',\n fields=[\n ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),\n ('title', models.CharField(max_length=200)),",
"detail": "back.api.migrations.0007_floorplan_alter_product_image1_alter_product_image2_and_more", "detail": "back.api.migrations.0007_floorplan_alter_product_image1_alter_product_image2_and_more",
"documentation": {} "documentation": {}
}, },
{
"label": "Migration",
"kind": 6,
"importPath": "back.api.migrations.0008_alter_floorplan_np_field",
"description": "back.api.migrations.0008_alter_floorplan_np_field",
"peekOfCode": "class Migration(migrations.Migration):\n dependencies = [\n ('api', '0007_floorplan_alter_product_image1_alter_product_image2_and_more'),\n ]\n operations = [\n migrations.AlterField(\n model_name='floorplan',\n name='np_field',\n field=models.TextField(),\n ),",
"detail": "back.api.migrations.0008_alter_floorplan_np_field",
"documentation": {}
},
{
"label": "Migration",
"kind": 6,
"importPath": "back.api.migrations.0009_alter_floorplan_np_field",
"description": "back.api.migrations.0009_alter_floorplan_np_field",
"peekOfCode": "class Migration(migrations.Migration):\n dependencies = [\n ('api', '0008_alter_floorplan_np_field'),\n ]\n operations = [\n migrations.AlterField(\n model_name='floorplan',\n name='np_field',\n field=models.BinaryField(),\n ),",
"detail": "back.api.migrations.0009_alter_floorplan_np_field",
"documentation": {}
},
{
"label": "Migration",
"kind": 6,
"importPath": "back.api.migrations.0010_alter_floorplan_np_field",
"description": "back.api.migrations.0010_alter_floorplan_np_field",
"peekOfCode": "class Migration(migrations.Migration):\n dependencies = [\n ('api', '0009_alter_floorplan_np_field'),\n ]\n operations = [\n migrations.AlterField(\n model_name='floorplan',\n name='np_field',\n field=models.TextField(),\n ),",
"detail": "back.api.migrations.0010_alter_floorplan_np_field",
"documentation": {}
},
{ {
"label": "ApiConfig", "label": "ApiConfig",
"kind": 6, "kind": 6,
@ -8366,6 +8477,15 @@
"detail": "back.api.models", "detail": "back.api.models",
"documentation": {} "documentation": {}
}, },
{
"label": "Floorplan",
"kind": 6,
"importPath": "back.api.models",
"description": "back.api.models",
"peekOfCode": "class Floorplan(models.Model):\n title = models.CharField(max_length=200)\n np_field = models.TextField()",
"detail": "back.api.models",
"documentation": {}
},
{ {
"label": "ProductSerializer", "label": "ProductSerializer",
"kind": 6, "kind": 6,
@ -8376,20 +8496,74 @@
"documentation": {} "documentation": {}
}, },
{ {
"label": "file_to_svg", "label": "FloorplanSerializer",
"kind": 6,
"importPath": "back.api.serializers",
"description": "back.api.serializers",
"peekOfCode": "class FloorplanSerializer(serializers.Serializer):\n title = serializers.CharField(max_length=200)\n np_field = serializers.CharField()\n def create(self,validated_data):\n return Floorplan.objects.create(**validated_data)",
"detail": "back.api.serializers",
"documentation": {}
},
{
"label": "numpy_arr_to_zip_str",
"kind": 2, "kind": 2,
"importPath": "back.api.tracer", "importPath": "back.api.tracer",
"description": "back.api.tracer", "description": "back.api.tracer",
"peekOfCode": "def file_to_svg(filename: str):\n try:\n image = Image.open(filename)\n except IOError:\n print(\"Image (%s) could not be loaded.\" % filename)\n return\n bm = Bitmap(image, blacklevel=0.5)\n # bm.invert()\n plist = bm.trace(\n turdsize=2,", "peekOfCode": "def numpy_arr_to_zip_str(arr):\n f = io.BytesIO()\n np.savez_compressed(f, arr=arr)\n return base64.b64encode(f.getvalue())\ndef numpy_zip_str_to_arr(zip_str):\n f = io.BytesIO(base64.b64decode(zip_str))\n return np.load(f)['arr'].tolist()\ndef read_image(content: bytes) -> np.ndarray:\n \"\"\"\n Image bytes to OpenCV image",
"detail": "back.api.tracer", "detail": "back.api.tracer",
"documentation": {} "documentation": {}
}, },
{ {
"label": "products", "label": "numpy_zip_str_to_arr",
"kind": 2, "kind": 2,
"importPath": "back.api.tracer",
"description": "back.api.tracer",
"peekOfCode": "def numpy_zip_str_to_arr(zip_str):\n f = io.BytesIO(base64.b64decode(zip_str))\n return np.load(f)['arr'].tolist()\ndef read_image(content: bytes) -> np.ndarray:\n \"\"\"\n Image bytes to OpenCV image\n :param content: Image bytes\n :returns OpenCV image\n :raises TypeError: If content is not bytes\n :raises ValueError: If content does not represent an image",
"detail": "back.api.tracer",
"documentation": {}
},
{
"label": "read_image",
"kind": 2,
"importPath": "back.api.tracer",
"description": "back.api.tracer",
"peekOfCode": "def read_image(content: bytes) -> np.ndarray:\n \"\"\"\n Image bytes to OpenCV image\n :param content: Image bytes\n :returns OpenCV image\n :raises TypeError: If content is not bytes\n :raises ValueError: If content does not represent an image\n \"\"\"\n if not isinstance(content, bytes):\n raise TypeError(f\"Expected 'content' to be bytes, received: {type(content)}\")",
"detail": "back.api.tracer",
"documentation": {}
},
{
"label": "parse_image",
"kind": 2,
"importPath": "back.api.tracer",
"description": "back.api.tracer",
"peekOfCode": "def parse_image(img):\n (img_h, img_w) = img.shape[:2]\n t = 1200\n w = t\n h = int((img_h / img_w) * t)\n img = cv2.resize(img, (w, h))\n gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n gray = 255 - gray\n gray = cv2.threshold(gray, 250, 255, cv2.THRESH_BINARY)[1]\n gray = cv2.blur(gray, (10, 5))",
"detail": "back.api.tracer",
"documentation": {}
},
{
"label": "Products",
"kind": 6,
"importPath": "back.api.views", "importPath": "back.api.views",
"description": "back.api.views", "description": "back.api.views",
"peekOfCode": "def products(request):\n \"\"\"\n List all task snippets\n \"\"\"\n if request.method == \"GET\":\n tasks = Product.objects.all()\n serializer = ProductSerializer(tasks, many=True)\n return JsonResponse(serializer.data, safe=False)\n elif request.method == \"POST\":\n data = JSONParser().parse(request)", "peekOfCode": "class Products(APIView):\n def get(self, request):\n tasks = Product.objects.all()\n serializer = ProductSerializer(tasks, many=True)\n return JsonResponse(serializer.data, safe=False)\n def post(self, request):\n data = JSONParser().parse(request)\n serializer = ProductSerializer(data=data)\n if serializer.is_valid():\n serializer.save()",
"detail": "back.api.views",
"documentation": {}
},
{
"label": "FloorplanView",
"kind": 6,
"importPath": "back.api.views",
"description": "back.api.views",
"peekOfCode": "class FloorplanView(APIView):\n parser_classes = (MultiPartParser,)\n def post(self, request):\n try:\n file = request.FILES[\"demo\"]\n logger.info(file.__dict__)\n res = parse_image(read_image(file.read()))\n serializer = FloorplanSerializer(\n data={\"title\": file.name, \"np_field\": res[\"b64\"].decode()}\n )",
"detail": "back.api.views",
"documentation": {}
},
{
"label": "logger",
"kind": 5,
"importPath": "back.api.views",
"description": "back.api.views",
"peekOfCode": "logger = logging.getLogger(\"root\")\nclass Products(APIView):\n def get(self, request):\n tasks = Product.objects.all()\n serializer = ProductSerializer(tasks, many=True)\n return JsonResponse(serializer.data, safe=False)\n def post(self, request):\n data = JSONParser().parse(request)\n serializer = ProductSerializer(data=data)\n if serializer.is_valid():",
"detail": "back.api.views", "detail": "back.api.views",
"documentation": {} "documentation": {}
}, },
@ -8443,7 +8617,7 @@
"kind": 5, "kind": 5,
"importPath": "back.back.settings", "importPath": "back.back.settings",
"description": "back.back.settings", "description": "back.back.settings",
"peekOfCode": "CSRF_TRUSTED_ORIGINS = (\n \"https://demo.kustarshina.ru\",\n \"http://localhost\",\n \"http://192.168.103.159\",\n)\nCORS_ORIGIN_ALLOW_ALL = False\nCORS_ORIGIN_WHITELIST = [\n \"null\",\n \"http://localhost\",\n \"http://localhost:4173\",", "peekOfCode": "CSRF_TRUSTED_ORIGINS = (\n \"https://demo.kustarshina.ru\",\n \"http://localhost\",\n \"http://localhost:3011\",\n \"http://192.168.103.159\",\n)\nCORS_ORIGIN_ALLOW_ALL = False\nCORS_ORIGIN_WHITELIST = [\n \"null\",\n \"http://localhost\",",
"detail": "back.back.settings", "detail": "back.back.settings",
"documentation": {} "documentation": {}
}, },
@ -8452,7 +8626,7 @@
"kind": 5, "kind": 5,
"importPath": "back.back.settings", "importPath": "back.back.settings",
"description": "back.back.settings", "description": "back.back.settings",
"peekOfCode": "CORS_ORIGIN_ALLOW_ALL = False\nCORS_ORIGIN_WHITELIST = [\n \"null\",\n \"http://localhost\",\n \"http://localhost:4173\",\n \"http://localhost:5173\",\n \"http://localhost:8000\",\n \"http://127.0.0.1\",\n \"http://192.168.103.159\",\n \"http://192.168.103.159:8000\",", "peekOfCode": "CORS_ORIGIN_ALLOW_ALL = False\nCORS_ORIGIN_WHITELIST = [\n \"null\",\n \"http://localhost\",\n \"http://localhost:3000\",\n \"http://localhost:3011\",\n \"http://localhost:4173\",\n \"http://localhost:5173\",\n \"http://localhost:8000\",\n \"http://127.0.0.1\",",
"detail": "back.back.settings", "detail": "back.back.settings",
"documentation": {} "documentation": {}
}, },
@ -8461,7 +8635,7 @@
"kind": 5, "kind": 5,
"importPath": "back.back.settings", "importPath": "back.back.settings",
"description": "back.back.settings", "description": "back.back.settings",
"peekOfCode": "CORS_ORIGIN_WHITELIST = [\n \"null\",\n \"http://localhost\",\n \"http://localhost:4173\",\n \"http://localhost:5173\",\n \"http://localhost:8000\",\n \"http://127.0.0.1\",\n \"http://192.168.103.159\",\n \"http://192.168.103.159:8000\",\n \"http://front:4173\",", "peekOfCode": "CORS_ORIGIN_WHITELIST = [\n \"null\",\n \"http://localhost\",\n \"http://localhost:3000\",\n \"http://localhost:3011\",\n \"http://localhost:4173\",\n \"http://localhost:5173\",\n \"http://localhost:8000\",\n \"http://127.0.0.1\",\n \"http://192.168.103.159\",",
"detail": "back.back.settings", "detail": "back.back.settings",
"documentation": {} "documentation": {}
}, },
@ -8596,7 +8770,7 @@
"kind": 5, "kind": 5,
"importPath": "back.back.urls", "importPath": "back.back.urls",
"description": "back.back.urls", "description": "back.back.urls",
"peekOfCode": "urlpatterns = [\n path(\"admin/\", admin.site.urls),\n path(\"api/products\", views.products),\n] + static('/files', document_root='files')", "peekOfCode": "urlpatterns = [\n path(\"admin/\", admin.site.urls),\n path(\"api/products\", csrf_exempt(views.Products.as_view())),\n path(\"api/floorplan\", csrf_exempt(views.FloorplanView.as_view())),\n] + static('/files', document_root='files')",
"detail": "back.back.urls", "detail": "back.back.urls",
"documentation": {} "documentation": {}
}, },

View File

@ -1,5 +1,6 @@
from django.contrib import admin from django.contrib import admin
from .models import Product from .models import Product, Floorplan
# Register your models here. # Register your models here.
admin.site.register(Product) admin.site.register(Product)
admin.site.register(Floorplan)

View File

@ -20,3 +20,8 @@ class Product(models.Model):
def __str__(self): def __str__(self):
return self.title return self.title
class Floorplan(models.Model):
title = models.CharField(max_length=200)
np_field = models.TextField()

View File

@ -1,5 +1,5 @@
from rest_framework import routers, serializers, viewsets from rest_framework import routers, serializers, viewsets
from .models import Product from .models import Product, Floorplan
class ProductSerializer(serializers.HyperlinkedModelSerializer): class ProductSerializer(serializers.HyperlinkedModelSerializer):
@ -14,3 +14,11 @@ class ProductSerializer(serializers.HyperlinkedModelSerializer):
"image2", "image2",
"image3", "image3",
] ]
class FloorplanSerializer(serializers.Serializer):
title = serializers.CharField(max_length=200)
np_field = serializers.CharField()
def create(self,validated_data):
return Floorplan.objects.create(**validated_data)

View File

@ -1,44 +1,66 @@
from PIL import Image import io
from potrace import Bitmap, POTRACE_TURNPOLICY_MINORITY # `potracer` library import base64
import cv2
import numpy as np
def numpy_arr_to_zip_str(arr):
f = io.BytesIO()
np.savez_compressed(f, arr=arr)
return base64.b64encode(f.getvalue())
def numpy_zip_str_to_arr(zip_str):
f = io.BytesIO(base64.b64decode(zip_str))
return np.load(f)['arr'].tolist()
def read_image(content: bytes) -> np.ndarray:
"""
Image bytes to OpenCV image
:param content: Image bytes
:returns OpenCV image
:raises TypeError: If content is not bytes
:raises ValueError: If content does not represent an image
"""
if not isinstance(content, bytes):
raise TypeError(f"Expected 'content' to be bytes, received: {type(content)}")
image = cv2.imdecode(np.frombuffer(content, dtype=np.uint8), cv2.IMREAD_COLOR)
if image is None:
raise ValueError(f"Expected 'content' to be image bytes")
return image
def file_to_svg(filename: str): def parse_image(img):
try: (img_h, img_w) = img.shape[:2]
t = 1200
w = t
h = int((img_h / img_w) * t)
img = cv2.resize(img, (w, h))
image = Image.open(filename) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
except IOError: gray = 255 - gray
print("Image (%s) could not be loaded." % filename) gray = cv2.threshold(gray, 250, 255, cv2.THRESH_BINARY)[1]
return gray = cv2.blur(gray, (10, 5))
bm = Bitmap(image, blacklevel=0.5) contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
# bm.invert()
plist = bm.trace(
turdsize=2,
turnpolicy=POTRACE_TURNPOLICY_MINORITY,
alphamax=1,
opticurve=False,
opttolerance=0.2,
)
with open(f"{filename}.svg", "w") as fp:
fp.write(
f'''<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{image.width}" height="{image.height}" viewBox="0 0 {image.width} {image.height}">''')
parts = []
for curve in plist:
fs = curve.start_point
parts.append(f"M{fs.x},{fs.y}")
for segment in curve.segments:
if segment.is_corner:
a = segment.c
b = segment.end_point
parts.append(f"L{a.x},{a.y}L{b.x},{b.y}")
else:
a = segment.c1
b = segment.c2
c = segment.end_point
parts.append(f"C{a.x},{a.y} {b.x},{b.y} {c.x},{c.y}")
parts.append("z")
fp.write(f'<path stroke="none" fill="black" fill-rule="evenodd" d="{"".join(parts)}"/>')
fp.write("</svg>")
for cnt in contours:
area = cv2.contourArea(cnt)
# if area > 150000 and area < 500000:
cv2.drawContours(img, [cnt], 0, (255, 0, 0), 2)
if __name__ == '__main__': svg_paths = []
file_to_svg('plan.png')
for cnt in contours:
if len(cnt) > 80:
svg_path = "M"
for i in range(len(cnt)):
x, y = cnt[i][0]
svg_path += f"{x} {y} "
svg_paths.append(svg_path)
return {
"width": w,
"height": h,
"paths": svg_paths,
"array": gray.tolist(),
"b64": numpy_arr_to_zip_str(gray),
}

View File

@ -1,21 +1,24 @@
from django.shortcuts import render
from rest_framework.parsers import JSONParser from rest_framework.parsers import JSONParser, MultiPartParser
from django.views.decorators.csrf import csrf_exempt from rest_framework.views import APIView
from django.http import HttpResponse, JsonResponse from django.http import JsonResponse
from .serializers import ProductSerializer
from .models import Product from api.tracer import parse_image, read_image, numpy_zip_str_to_arr
from .serializers import FloorplanSerializer, ProductSerializer
from .models import Floorplan, Product
import logging
logger = logging.getLogger("root")
@csrf_exempt class Products(APIView):
def products(request): def get(self, request):
"""
List all task snippets
"""
if request.method == "GET":
tasks = Product.objects.all() tasks = Product.objects.all()
serializer = ProductSerializer(tasks, many=True) serializer = ProductSerializer(tasks, many=True)
return JsonResponse(serializer.data, safe=False) return JsonResponse(serializer.data, safe=False)
elif request.method == "POST":
def post(self, request):
data = JSONParser().parse(request) data = JSONParser().parse(request)
serializer = ProductSerializer(data=data) serializer = ProductSerializer(data=data)
if serializer.is_valid(): if serializer.is_valid():
@ -23,3 +26,38 @@ def products(request):
return JsonResponse(serializer.data, status=201) return JsonResponse(serializer.data, status=201)
return JsonResponse(serializer.errors, status=400) return JsonResponse(serializer.errors, status=400)
class FloorplanView(APIView):
parser_classes = (MultiPartParser,)
def post(self, request):
try:
file = request.FILES["demo"]
logger.info(file.__dict__)
res = parse_image(read_image(file.read()))
serializer = FloorplanSerializer(
data={"title": file.name, "np_field": res["b64"].decode()}
)
logger.info(res["b64"])
if serializer.is_valid():
serializer.save()
return JsonResponse(
data={"response": {"array": res["array"]}}, status=201
)
return JsonResponse(serializer.errors, status=500)
except Exception as e:
logger.error(e)
raise e
def get(self, request):
try:
item = Floorplan.objects.last()
serializer = FloorplanSerializer(item, many=False)
data = serializer.data
data["np_field"] = numpy_zip_str_to_arr(data["np_field"])
return JsonResponse(data, safe=False)
except Exception as e:
logger.error(e)
raise e

View File

@ -13,6 +13,7 @@ https://docs.djangoproject.com/en/5.0/ref/settings/
from pathlib import Path from pathlib import Path
import os import os
from dotenv import load_dotenv from dotenv import load_dotenv
load_dotenv() load_dotenv()
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
@ -42,17 +43,21 @@ ALLOWED_HOSTS = [
CSRF_TRUSTED_ORIGINS = ( CSRF_TRUSTED_ORIGINS = (
"https://demo.kustarshina.ru", "https://demo.kustarshina.ru",
"http://localhost", "http://localhost",
"http://localhost:3011",
"http://192.168.103.159", "http://192.168.103.159",
) )
CORS_ORIGIN_ALLOW_ALL = False CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = [ CORS_ORIGIN_WHITELIST = [
"null", "null",
"http://localhost", "http://localhost",
"http://localhost:3000",
"http://localhost:3011",
"http://localhost:4173", "http://localhost:4173",
"http://localhost:5173", "http://localhost:5173",
"http://localhost:8000", "http://localhost:8000",
"http://127.0.0.1", "http://127.0.0.1",
"http://192.168.103.159", "http://192.168.103.159",
"http://192.168.103.159:3000",
"http://192.168.103.159:8000", "http://192.168.103.159:8000",
"http://front:4173", "http://front:4173",
"http://front:5173", "http://front:5173",

View File

@ -18,8 +18,10 @@ from django.contrib import admin
from django.urls import path from django.urls import path
from django.conf.urls.static import static from django.conf.urls.static import static
from api import views from api import views
from django.views.decorators.csrf import csrf_exempt
urlpatterns = [ urlpatterns = [
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
path("api/products", views.products), path("api/products", csrf_exempt(views.Products.as_view())),
path("api/floorplan", csrf_exempt(views.FloorplanView.as_view())),
] + static('/files', document_root='files') ] + static('/files', document_root='files')

View File

@ -7,6 +7,8 @@ export {}
declare module 'vue' { declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
copy: typeof import('./src/components/Home copy.vue')['default']
Floorplan: typeof import('./src/components/Floorplan.vue')['default']
Game: typeof import('./src/components/Game.vue')['default'] Game: typeof import('./src/components/Game.vue')['default']
Home: typeof import('./src/components/Home.vue')['default'] Home: typeof import('./src/components/Home.vue')['default']
IMdi3dRotation: typeof import('~icons/mdi/3d-rotation')['default'] IMdi3dRotation: typeof import('~icons/mdi/3d-rotation')['default']

View File

@ -0,0 +1,17 @@
<style lang="scss" scoped>
</style>
<script setup lang="ts">
import { onMounted } from 'vue';
import { useFloorplanStore } from '../stores/floorplan';
const floorplan = useFloorplanStore()
onMounted(()=>{
floorplan.getData()
})
</script>
<template>
<div class="container">
</div>
</template>

View File

@ -15,6 +15,9 @@
<li> <li>
<RouterLink to="game">Игра</RouterLink> <RouterLink to="game">Игра</RouterLink>
</li> </li>
<li>
<RouterLink to="floorplan">План помещения и маршрут</RouterLink>
</li>
<li> <li>
<a href="https://timesheet.kustarshina.ru/">Табель рабочего времени</a> <a href="https://timesheet.kustarshina.ru/">Табель рабочего времени</a>
</li> </li>

View File

@ -8,11 +8,13 @@ import App from './App.vue'
import Home from './components/Home.vue' import Home from './components/Home.vue'
import Projects from './components/Projects.vue' import Projects from './components/Projects.vue'
import Game from './components/Game.vue' import Game from './components/Game.vue'
import Floorplan from './components/Floorplan.vue'
const routes = [ const routes = [
{ path: '/', component: Home }, { path: '/', component: Home },
{ path: '/projects', component: Projects }, { path: '/projects', component: Projects },
{ path: '/game', component: Game }, { path: '/game', component: Game },
{ path: '/floorplan', component: Floorplan },
] ]
const router = createRouter({ const router = createRouter({

View File

@ -0,0 +1,33 @@
import { defineStore } from 'pinia'
import { SERVER_URL } from '../constants'
export const useFloorplanStore = defineStore('floorplan', {
state: () => {
return {
// for initially empty lists
}
},
actions: {
async getData() {
try {
const res = await fetch(`${SERVER_URL}/api/floorplan`)
const data = await res.json()
if (data.length) {
// this.list = data
}
} catch (error) {
// this.list = []
}
},
}
})
export interface ProductInfo {
id: number
title: string
description: string
model3d?: string
image1?: string
image2?: string
image3?: string
}

View File

@ -3,13 +3,8 @@ name = "interactive-table"
version = "0.1.0" version = "0.1.0"
description = "" description = ""
authors = ["Your Name <you@example.com>"] authors = ["Your Name <you@example.com>"]
<<<<<<< HEAD
readme = "README.md" readme = "README.md"
package-mode=false package-mode=false
=======
readme = "readme.md"
package-mode = false
>>>>>>> bx-434-game
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.10" python = "^3.10"
@ -19,13 +14,9 @@ taskipy = "^1.12.2"
django-cors-headers = "^4.3.1" django-cors-headers = "^4.3.1"
pillow = "^10.3.0" pillow = "^10.3.0"
python-dotenv = "^1.0.1" python-dotenv = "^1.0.1"
<<<<<<< HEAD
psycopg2 = "^2.9.9" psycopg2 = "^2.9.9"
opencv-python = "^4.9.0.80" opencv-python = "^4.9.0.80"
potracer = "^0.0.4" potracer = "^0.0.4"
=======
psycopg2-binary = "^2.9.9"
>>>>>>> bx-434-game
[build-system] [build-system]