Add Image models and clean up test code structure
Introduced `ImageCreate` and `Image` models to handle image-related data in the backend. Improved the organization and readability of the testing notebook by consolidating and formatting code into distinct sections with markdown cells.
This commit is contained in:
parent
f588bc0cda
commit
1606e80f81
@ -249,6 +249,17 @@ class Beamtime(Base):
|
||||
dewars = relationship("Dewar", back_populates="beamtime")
|
||||
|
||||
|
||||
class Image(Base):
|
||||
__tablename__ = "images"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
||||
pgroup = Column(String(255), nullable=False)
|
||||
comment = Column(String(200), nullable=True)
|
||||
filepath = Column(String(255), nullable=False)
|
||||
status = Column(String(255), nullable=True)
|
||||
sample_id = Column(Integer, ForeignKey("samples.id"), nullable=False)
|
||||
|
||||
|
||||
# class Results(Base):
|
||||
# __tablename__ = "results"
|
||||
#
|
||||
|
@ -1,4 +1,4 @@
|
||||
from fastapi import APIRouter, HTTPException, Depends, UploadFile, File
|
||||
from fastapi import APIRouter, HTTPException, Depends, UploadFile, File, Form
|
||||
from sqlalchemy.orm import Session
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
@ -9,11 +9,14 @@ from app.schemas import (
|
||||
Sample as SampleSchema,
|
||||
SampleEventCreate,
|
||||
Sample,
|
||||
Image,
|
||||
ImageCreate,
|
||||
)
|
||||
from app.models import (
|
||||
Puck as PuckModel,
|
||||
Sample as SampleModel,
|
||||
SampleEvent as SampleEventModel,
|
||||
Image as ImageModel,
|
||||
)
|
||||
from app.dependencies import get_db
|
||||
import logging
|
||||
@ -89,29 +92,22 @@ async def create_sample_event(
|
||||
return sample # Return the sample, now including `mount_count`
|
||||
|
||||
|
||||
@router.post("/{sample_id}/upload-images")
|
||||
@router.post("/{sample_id}/upload-images", response_model=Image)
|
||||
async def upload_sample_image(
|
||||
sample_id: int,
|
||||
uploaded_file: UploadFile = File(...),
|
||||
comment: str = Form(None),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
logging.info(f"Received file: {uploaded_file.filename}")
|
||||
|
||||
"""
|
||||
Uploads an image for a given sample and saves it to a directory structure.
|
||||
Args:
|
||||
sample_id (int): ID of the sample.
|
||||
uploaded_file (UploadFile): The file uploaded with the request.
|
||||
db (Session): Database session.
|
||||
"""
|
||||
|
||||
# 1. Validate Sample
|
||||
# Validate Sample
|
||||
sample = db.query(SampleModel).filter(SampleModel.id == sample_id).first()
|
||||
if not sample:
|
||||
raise HTTPException(status_code=404, detail="Sample not found")
|
||||
|
||||
# 2. Define Directory Structure
|
||||
pgroup = sample.puck.dewar.pgroups
|
||||
# Define Directory Structure
|
||||
pgroup = sample.puck.dewar.pgroups # adjust to sample or puck pgroups as needed
|
||||
today = datetime.now().strftime("%Y-%m-%d")
|
||||
dewar_name = (
|
||||
sample.puck.dewar.dewar_name
|
||||
@ -123,7 +119,7 @@ async def upload_sample_image(
|
||||
base_dir = Path(f"images/{pgroup}/{today}/{dewar_name}/{puck_name}/{position}")
|
||||
base_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# 3. Validate MIME type and Save the File
|
||||
# Validate MIME type and Save the File
|
||||
if not uploaded_file.content_type.startswith("image/"):
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
@ -146,9 +142,26 @@ async def upload_sample_image(
|
||||
f" Ensure the server has correct permissions.",
|
||||
)
|
||||
|
||||
# 4. Return Saved File Information
|
||||
logging.info(f"Uploaded 1 file for sample {sample_id}.")
|
||||
return {
|
||||
"message": "1 image uploaded successfully.",
|
||||
"file": str(file_path),
|
||||
}
|
||||
# Create the payload from the Pydantic schema
|
||||
image_payload = ImageCreate(
|
||||
pgroup=pgroup,
|
||||
comment=comment,
|
||||
filepath=str(file_path),
|
||||
status="active",
|
||||
sample_id=sample_id,
|
||||
).dict()
|
||||
|
||||
# Convert the payload to your mapped SQLAlchemy model instance.
|
||||
# Make sure that ImageModel is your mapped model for images.
|
||||
new_image = ImageModel(**image_payload)
|
||||
db.add(new_image)
|
||||
db.commit()
|
||||
db.refresh(new_image)
|
||||
|
||||
logging.info(
|
||||
f"Uploaded 1 file for sample {sample_id} and"
|
||||
f" added record {new_image.id} to the database."
|
||||
)
|
||||
# Returning the mapped SQLAlchemy object, which will be converted to the
|
||||
# Pydantic response model.
|
||||
return new_image
|
||||
|
@ -783,3 +783,24 @@ class Beamtime(BaseModel):
|
||||
proposal: Optional[Proposal]
|
||||
local_contact_id: Optional[int]
|
||||
local_contact: Optional[LocalContact]
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class ImageCreate(BaseModel):
|
||||
pgroup: str
|
||||
sample_id: int
|
||||
filepath: str
|
||||
status: str = "active"
|
||||
comment: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class Image(ImageCreate):
|
||||
id: int
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "aareDB"
|
||||
version = "0.1.0a22"
|
||||
version = "0.1.0a23"
|
||||
description = "Backend for next gen sample management system"
|
||||
authors = [{name = "Guillaume Gotthard", email = "guillaume.gotthard@psi.ch"}]
|
||||
license = {text = "MIT"}
|
||||
|
@ -1,10 +1,13 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-02-26T12:02:38.993926Z",
|
||||
"start_time": "2025-02-26T12:02:38.991283Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"outputs": [],
|
||||
"execution_count": null,
|
||||
"source": [
|
||||
"import json\n",
|
||||
"\n",
|
||||
@ -32,7 +35,18 @@
|
||||
"configuration.verify_ssl = False # Disable SSL verification\n",
|
||||
"#print(dir(SamplesApi))"
|
||||
],
|
||||
"id": "3b7c27697a4d5c83"
|
||||
"id": "3b7c27697a4d5c83",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"0.1.0a21\n",
|
||||
"https://127.0.0.1:8000\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 74
|
||||
},
|
||||
{
|
||||
"metadata": {},
|
||||
@ -160,10 +174,13 @@
|
||||
"execution_count": 43
|
||||
},
|
||||
{
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-02-26T12:04:05.046079Z",
|
||||
"start_time": "2025-02-26T12:04:04.954761Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"outputs": [],
|
||||
"execution_count": null,
|
||||
"source": [
|
||||
"# Get a list of pucks that are \"at the beamline\"\n",
|
||||
"\n",
|
||||
@ -181,13 +198,42 @@
|
||||
" except ApiException as e:\n",
|
||||
" print(\"Exception when calling PucksApi->get_pucks_by_slot_pucks_slot_slot_identifier_get: %s\\n\" % e)"
|
||||
],
|
||||
"id": "9cf3457093751b61"
|
||||
"id": "9cf3457093751b61",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"The response of PucksApi->get_pucks_by_slot_pucks_slot_slot_identifier_get:\n",
|
||||
"\n",
|
||||
"[PuckWithTellPosition(id=1, puck_name='PUCK-001', puck_type='Unipuck', puck_location_in_dewar=1, dewar_id=1, dewar_name='Dewar One', pgroup='p20001, p20002', samples=None, tell_position=None),\n",
|
||||
" PuckWithTellPosition(id=2, puck_name='PUCK002', puck_type='Unipuck', puck_location_in_dewar=2, dewar_id=1, dewar_name='Dewar One', pgroup='p20001, p20002', samples=None, tell_position=None),\n",
|
||||
" PuckWithTellPosition(id=3, puck_name='PUCK003', puck_type='Unipuck', puck_location_in_dewar=3, dewar_id=1, dewar_name='Dewar One', pgroup='p20001, p20002', samples=None, tell_position=None),\n",
|
||||
" PuckWithTellPosition(id=4, puck_name='PUCK004', puck_type='Unipuck', puck_location_in_dewar=4, dewar_id=1, dewar_name='Dewar One', pgroup='p20001, p20002', samples=None, tell_position=None),\n",
|
||||
" PuckWithTellPosition(id=5, puck_name='PUCK005', puck_type='Unipuck', puck_location_in_dewar=5, dewar_id=1, dewar_name='Dewar One', pgroup='p20001, p20002', samples=None, tell_position=None),\n",
|
||||
" PuckWithTellPosition(id=6, puck_name='PUCK006', puck_type='Unipuck', puck_location_in_dewar=6, dewar_id=1, dewar_name='Dewar One', pgroup='p20001, p20002', samples=None, tell_position=None),\n",
|
||||
" PuckWithTellPosition(id=7, puck_name='PUCK007', puck_type='Unipuck', puck_location_in_dewar=7, dewar_id=1, dewar_name='Dewar One', pgroup='p20001, p20002', samples=None, tell_position=None)]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host '127.0.0.1'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings\n",
|
||||
" warnings.warn(\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 77
|
||||
},
|
||||
{
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-02-26T12:04:33.644201Z",
|
||||
"start_time": "2025-02-26T12:04:33.625894Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"outputs": [],
|
||||
"execution_count": null,
|
||||
"source": [
|
||||
"from aareDBclient import SetTellPosition, SetTellPositionRequest\n",
|
||||
"\n",
|
||||
@ -214,10 +260,10 @@
|
||||
" # SetTellPosition(puck_name='PSIMX117', segment='A', puck_in_segment=2),\n",
|
||||
" #]\n",
|
||||
" pucks=[\n",
|
||||
" SetTellPosition(puck_name='PK006', segment='F', puck_in_segment=1),\n",
|
||||
" SetTellPosition(puck_name='PK003', segment='F', puck_in_segment=2),\n",
|
||||
" SetTellPosition(puck_name='PK002', segment='A', puck_in_segment=1),\n",
|
||||
" SetTellPosition(puck_name='PK001', segment='A', puck_in_segment=2),\n",
|
||||
" SetTellPosition(puck_name='PUCK006', segment='F', puck_in_segment=1),\n",
|
||||
" SetTellPosition(puck_name='PUCK003', segment='F', puck_in_segment=2),\n",
|
||||
" SetTellPosition(puck_name='PUCK002', segment='A', puck_in_segment=1),\n",
|
||||
" SetTellPosition(puck_name='PUCK001', segment='A', puck_in_segment=2),\n",
|
||||
" ]\n",
|
||||
" #pucks = []\n",
|
||||
" )\n",
|
||||
@ -234,13 +280,59 @@
|
||||
" except Exception as e:\n",
|
||||
" print(f\"Exception when calling PucksApi: {e}\")\n"
|
||||
],
|
||||
"id": "37e3eac6760150ee"
|
||||
"id": "37e3eac6760150ee",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"The response of PucksApi->pucks_puck_id_tell_position_put:\n",
|
||||
"\n",
|
||||
"[{'message': 'Tell position updated successfully.',\n",
|
||||
" 'new_position': 'F1',\n",
|
||||
" 'previous_position': None,\n",
|
||||
" 'puck_name': 'PUCK006',\n",
|
||||
" 'status': 'updated',\n",
|
||||
" 'tell': 'X06DA'},\n",
|
||||
" {'message': 'Tell position updated successfully.',\n",
|
||||
" 'new_position': 'F2',\n",
|
||||
" 'previous_position': None,\n",
|
||||
" 'puck_name': 'PUCK003',\n",
|
||||
" 'status': 'updated',\n",
|
||||
" 'tell': 'X06DA'},\n",
|
||||
" {'message': 'Tell position updated successfully.',\n",
|
||||
" 'new_position': 'A1',\n",
|
||||
" 'previous_position': None,\n",
|
||||
" 'puck_name': 'PUCK002',\n",
|
||||
" 'status': 'updated',\n",
|
||||
" 'tell': 'X06DA'},\n",
|
||||
" {'message': 'Tell position updated successfully.',\n",
|
||||
" 'new_position': 'A2',\n",
|
||||
" 'previous_position': None,\n",
|
||||
" 'puck_name': 'PUCK001',\n",
|
||||
" 'status': 'updated',\n",
|
||||
" 'tell': 'X06DA'}]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host '127.0.0.1'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings\n",
|
||||
" warnings.warn(\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 78
|
||||
},
|
||||
{
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-02-26T12:04:41.352140Z",
|
||||
"start_time": "2025-02-26T12:04:41.331320Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"outputs": [],
|
||||
"execution_count": null,
|
||||
"source": [
|
||||
"# Get puck_id puck_name sample_id sample_name of pucks in the tell\n",
|
||||
"\n",
|
||||
@ -275,13 +367,69 @@
|
||||
" except ApiException as e:\n",
|
||||
" print(\"Exception when calling PucksApi->get_all_pucks_in_tell: %s\\n\" % e)"
|
||||
],
|
||||
"id": "51578d944878db6a"
|
||||
"id": "51578d944878db6a",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Puck ID: 6, Puck Name: PUCK006\n",
|
||||
" Sample ID: 44, Sample Name: Sample044, Position: 2, Mount count: 1\n",
|
||||
" Sample ID: 45, Sample Name: Sample045, Position: 3, Mount count: 0\n",
|
||||
" Sample ID: 46, Sample Name: Sample046, Position: 4, Mount count: 0\n",
|
||||
" Sample ID: 47, Sample Name: Sample047, Position: 5, Mount count: 1\n",
|
||||
"Puck ID: 3, Puck Name: PUCK003\n",
|
||||
" Sample ID: 24, Sample Name: Sample024, Position: 1, Mount count: 0\n",
|
||||
" Sample ID: 25, Sample Name: Sample025, Position: 5, Mount count: 1\n",
|
||||
" Sample ID: 26, Sample Name: Sample026, Position: 8, Mount count: 1\n",
|
||||
" Sample ID: 27, Sample Name: Sample027, Position: 11, Mount count: 1\n",
|
||||
" Sample ID: 28, Sample Name: Sample028, Position: 12, Mount count: 1\n",
|
||||
"Puck ID: 2, Puck Name: PUCK002\n",
|
||||
" Sample ID: 17, Sample Name: Sample017, Position: 4, Mount count: 1\n",
|
||||
" Sample ID: 18, Sample Name: Sample018, Position: 5, Mount count: 0\n",
|
||||
" Sample ID: 19, Sample Name: Sample019, Position: 7, Mount count: 1\n",
|
||||
" Sample ID: 20, Sample Name: Sample020, Position: 10, Mount count: 0\n",
|
||||
" Sample ID: 21, Sample Name: Sample021, Position: 11, Mount count: 1\n",
|
||||
" Sample ID: 22, Sample Name: Sample022, Position: 13, Mount count: 0\n",
|
||||
" Sample ID: 23, Sample Name: Sample023, Position: 16, Mount count: 1\n",
|
||||
"Puck ID: 1, Puck Name: PUCK-001\n",
|
||||
" Sample ID: 1, Sample Name: Sample001, Position: 1, Mount count: 1\n",
|
||||
" Sample ID: 2, Sample Name: Sample002, Position: 2, Mount count: 1\n",
|
||||
" Sample ID: 3, Sample Name: Sample003, Position: 3, Mount count: 0\n",
|
||||
" Sample ID: 4, Sample Name: Sample004, Position: 4, Mount count: 0\n",
|
||||
" Sample ID: 5, Sample Name: Sample005, Position: 5, Mount count: 0\n",
|
||||
" Sample ID: 6, Sample Name: Sample006, Position: 6, Mount count: 1\n",
|
||||
" Sample ID: 7, Sample Name: Sample007, Position: 7, Mount count: 0\n",
|
||||
" Sample ID: 8, Sample Name: Sample008, Position: 8, Mount count: 1\n",
|
||||
" Sample ID: 9, Sample Name: Sample009, Position: 9, Mount count: 1\n",
|
||||
" Sample ID: 10, Sample Name: Sample010, Position: 10, Mount count: 1\n",
|
||||
" Sample ID: 11, Sample Name: Sample011, Position: 11, Mount count: 1\n",
|
||||
" Sample ID: 12, Sample Name: Sample012, Position: 12, Mount count: 1\n",
|
||||
" Sample ID: 13, Sample Name: Sample013, Position: 13, Mount count: 0\n",
|
||||
" Sample ID: 14, Sample Name: Sample014, Position: 14, Mount count: 1\n",
|
||||
" Sample ID: 15, Sample Name: Sample015, Position: 15, Mount count: 0\n",
|
||||
" Sample ID: 16, Sample Name: Sample016, Position: 16, Mount count: 0\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host '127.0.0.1'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings\n",
|
||||
" warnings.warn(\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 79
|
||||
},
|
||||
{
|
||||
"metadata": {},
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-02-26T12:05:03.257159Z",
|
||||
"start_time": "2025-02-26T12:05:03.232846Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
"outputs": [],
|
||||
"execution_count": null,
|
||||
"source": [
|
||||
"from aareDBclient import SampleEventCreate\n",
|
||||
"\n",
|
||||
@ -294,7 +442,7 @@
|
||||
" try:\n",
|
||||
" # Define the payload with only `event_type`\n",
|
||||
" sample_event_create = SampleEventCreate(\n",
|
||||
" sample_id=58,\n",
|
||||
" sample_id=16,\n",
|
||||
" event_type=\"Mounted\" # Valid event type\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
@ -304,7 +452,7 @@
|
||||
"\n",
|
||||
" # Call the API\n",
|
||||
" api_response = api_instance.create_sample_event_samples_samples_sample_id_events_post(\n",
|
||||
" sample_id=58, # Ensure this matches a valid sample ID in the database\n",
|
||||
" sample_id=16, # Ensure this matches a valid sample ID in the database\n",
|
||||
" sample_event_create=sample_event_create\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
@ -320,7 +468,40 @@
|
||||
" if e.body:\n",
|
||||
" print(f\"Error Details: {e.body}\")\n"
|
||||
],
|
||||
"id": "4a0665f92756b486"
|
||||
"id": "4a0665f92756b486",
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Payload being sent to API:\n",
|
||||
"{\"event_type\":\"Mounted\"}\n",
|
||||
"API response:\n",
|
||||
"('id', 16)\n",
|
||||
"('sample_name', 'Sample016')\n",
|
||||
"('position', 16)\n",
|
||||
"('puck_id', 1)\n",
|
||||
"('crystalname', None)\n",
|
||||
"('proteinname', None)\n",
|
||||
"('positioninpuck', None)\n",
|
||||
"('priority', None)\n",
|
||||
"('comments', None)\n",
|
||||
"('data_collection_parameters', None)\n",
|
||||
"('events', [SampleEventResponse(id=399, sample_id=16, event_type='Mounted', timestamp=datetime.datetime(2025, 2, 26, 13, 5, 3))])\n",
|
||||
"('mount_count', 1)\n",
|
||||
"('unmount_count', 0)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host '127.0.0.1'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings\n",
|
||||
" warnings.warn(\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 80
|
||||
},
|
||||
{
|
||||
"metadata": {},
|
||||
@ -347,8 +528,8 @@
|
||||
{
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2025-02-26T08:45:41.872357Z",
|
||||
"start_time": "2025-02-26T08:45:41.847822Z"
|
||||
"end_time": "2025-02-26T12:29:51.615501Z",
|
||||
"start_time": "2025-02-26T12:29:51.592886Z"
|
||||
}
|
||||
},
|
||||
"cell_type": "code",
|
||||
@ -399,7 +580,7 @@
|
||||
"text": [
|
||||
"API Response:\n",
|
||||
"200\n",
|
||||
"{'message': '1 image uploaded successfully.', 'file': 'images/p20001, p20002/2025-02-26/Dewar Two/PK001/14/IMG_1942.jpg'}\n"
|
||||
"{'pgroup': 'p20001, p20002', 'sample_id': 58, 'filepath': 'images/p20001, p20002/2025-02-26/Dewar One/PUCK007/12/IMG_1942.jpg', 'status': 'active', 'comment': None, 'id': 1}\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -411,7 +592,7 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"execution_count": 70
|
||||
"execution_count": 85
|
||||
},
|
||||
{
|
||||
"metadata": {},
|
||||
|
Loading…
x
Reference in New Issue
Block a user