refactor: Generate unique names for flows and folders with the same name

This commit is contained in:
ogabrielluiz 2024-06-10 19:51:18 -03:00
commit 9b99aeda36
2 changed files with 73 additions and 28 deletions

View file

@ -31,25 +31,60 @@ def create_flow(
flow: FlowCreate,
current_user: User = Depends(get_current_active_user),
):
"""Create a new flow."""
if flow.user_id is None:
flow.user_id = current_user.id
try:
"""Create a new flow."""
if flow.user_id is None:
flow.user_id = current_user.id
db_flow = Flow.model_validate(flow, from_attributes=True)
db_flow.updated_at = datetime.now(timezone.utc)
# First check if the flow.name is unique
# there might be flows with name like: "MyFlow", "MyFlow (1)", "MyFlow (2)"
# so we need to check if the name is unique with `like` operator
# if we find a flow with the same name, we add a number to the end of the name
# based on the highest number found
if session.exec(select(Flow).where(Flow.name == flow.name).where(Flow.user_id == current_user.id)).first():
flows = session.exec(
select(Flow).where(Flow.name.like(f"{flow.name} (%")).where(Flow.user_id == current_user.id)
).all()
if flows:
numbers = [int(flow.name.split("(")[1].split(")")[0]) for flow in flows]
flow.name = f"{flow.name} ({max(numbers) + 1})"
else:
flow.name = f"{flow.name} (1)"
if db_flow.folder_id is None:
# Make sure flows always have a folder
default_folder = session.exec(
select(Folder).where(Folder.name == DEFAULT_FOLDER_NAME, Folder.user_id == current_user.id)
).first()
if default_folder:
db_flow.folder_id = default_folder.id
db_flow = Flow.model_validate(flow, from_attributes=True)
db_flow.updated_at = datetime.now(timezone.utc)
session.add(db_flow)
session.commit()
session.refresh(db_flow)
return db_flow
if db_flow.folder_id is None:
# Make sure flows always have a folder
default_folder = session.exec(
select(Folder).where(Folder.name == DEFAULT_FOLDER_NAME, Folder.user_id == current_user.id)
).first()
if default_folder:
db_flow.folder_id = default_folder.id
session.add(db_flow)
session.commit()
session.refresh(db_flow)
return db_flow
except Exception as e:
# If it is a validation error, return the error message
if hasattr(e, "errors"):
raise HTTPException(status_code=400, detail=str(e)) from e
elif "UNIQUE constraint failed" in str(e):
# Get the name of the column that failed
columns = str(e).split("UNIQUE constraint failed: ")[1].split(".")[1].split("\n")[0]
# UNIQUE constraint failed: flow.user_id, flow.name
# or UNIQUE constraint failed: flow.name
# if the column has id in it, we want the other column
column = columns.split(",")[1] if "id" in columns.split(",")[0] else columns.split(",")[0]
raise HTTPException(
status_code=400, detail=f"{column.capitalize().replace('_', ' ')} must be unique"
) from e
elif isinstance(e, HTTPException):
raise e
else:
raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/", response_model=list[FlowRead], status_code=200)

View file

@ -1,7 +1,5 @@
from typing import List
from langflow.helpers.flow import generate_unique_flow_name
from langflow.helpers.folders import generate_unique_folder_name
import orjson
from fastapi import APIRouter, Depends, File, HTTPException, Response, UploadFile, status
from sqlalchemy import or_, update
@ -9,6 +7,8 @@ from sqlmodel import Session, select
from langflow.api.v1.flows import create_flows
from langflow.api.v1.schemas import FlowListCreate, FlowListReadWithFolderName
from langflow.helpers.flow import generate_unique_flow_name
from langflow.helpers.folders import generate_unique_folder_name
from langflow.services.auth.utils import get_current_active_user
from langflow.services.database.models.flow.model import Flow, FlowCreate, FlowRead
from langflow.services.database.models.folder.constants import DEFAULT_FOLDER_NAME
@ -35,17 +35,27 @@ def create_folder(
try:
new_folder = Folder.model_validate(folder, from_attributes=True)
new_folder.user_id = current_user.id
folder_results = session.exec(
select(Folder).where(
Folder.name.like(f"{new_folder.name}%"), # type: ignore
Folder.user_id == current_user.id,
# First check if the folder.name is unique
# there might be flows with name like: "MyFlow", "MyFlow (1)", "MyFlow (2)"
# so we need to check if the name is unique with `like` operator
# if we find a flow with the same name, we add a number to the end of the name
# based on the highest number found
if session.exec(
statement=select(Folder).where(Folder.name == new_folder.name).where(Folder.user_id == current_user.id)
).first():
folder_results = session.exec(
select(Folder).where(
Folder.name.like(f"{new_folder.name}%"), # type: ignore
Folder.user_id == current_user.id,
)
)
)
existing_folder_names = [folder.name for folder in folder_results]
if existing_folder_names:
new_folder.name = f"{new_folder.name} ({len(existing_folder_names) + 1})"
if folder_results:
folder_names = [folder.name for folder in folder_results]
folder_numbers = [int(name.split("(")[-1].split(")")[0]) for name in folder_names if "(" in name]
if folder_numbers:
new_folder.name = f"{new_folder.name} ({max(folder_numbers) + 1})"
else:
new_folder.name = f"{new_folder.name} (1)"
session.add(new_folder)
session.commit()