ID: streamlit-crud-v1
Категория: crud
Фреймворк: Streamlit
Сложность: Medium-High
Время адаптации: 30-40 минут
Полноценная CRUD (Create, Read, Update, Delete) страница для Streamlit приложений.
Функции:
- ✅ Create: Форма создания новых записей
- 📖 Read: Список всех записей с поиском
- ✏️ Update: Редактирование существующих записей
- 🗑️ Delete: Удаление с подтверждением
- 🔍 Поиск и фильтрация
- ✅ Валидация данных
- ⚠️ Обработка ошибок
cp templates/by-task/crud/streamlit-crud-v1/crud_page.py \
projects/myproject/pages/Users.py
Открыть Users.py и заменить переменные:
# Названия
ENTITY_NAME = "User"
ENTITY_NAME_PLURAL = "Users"
ENTITY_NAME_RU = "Пользователь"
ENTITY_NAME_RU_PLURAL = "Пользователи"
# Импорт модели
from database.models import User
# Поля для формы
FIELDS = {
'email': 'email',
'full_name': 'text',
'role': 'select',
'active': 'checkbox'
}
# Опции для select полей
SELECT_OPTIONS = {
'role': ['admin', 'manager', 'user', 'viewer']
}
# Раскомментировать функции get_all_items, create_item и т.д.
# и адаптировать под свою модель
streamlit run app.py
Поддерживаемые типы полей:
| Тип | Описание | Пример |
|---|---|---|
text |
Текстовое поле | Имя, название |
email |
Email поле | Email адрес |
number |
Числовое поле | Возраст, количество |
select |
Выпадающий список | Роль, статус |
checkbox |
Флаг (да/нет) | Активен, подтверждён |
textarea |
Многострочный текст | Описание, комментарий |
date |
Дата | Дата создания, день рождения |
ENTITY_NAME = "User"
ENTITY_NAME_PLURAL = "Users"
ENTITY_NAME_RU = "Пользователь"
ENTITY_NAME_RU_PLURAL = "Пользователи"
from database.models import User
FIELDS = {
'email': 'email',
'full_name': 'text',
'role': 'select',
'active': 'checkbox',
'created_at': 'date'
}
SELECT_OPTIONS = {
'role': ['admin', 'manager', 'user', 'viewer']
}
def get_all_items():
session = get_session()
try:
return session.query(User).all()
finally:
session.close()
def create_item(data):
session = get_session()
try:
new_user = User(**data)
session.add(new_user)
session.commit()
return new_user
except Exception as e:
session.rollback()
raise e
finally:
session.close()
# ... и т.д. для update_item, delete_item
ENTITY_NAME = "Product"
ENTITY_NAME_PLURAL = "Products"
ENTITY_NAME_RU = "Товар"
ENTITY_NAME_RU_PLURAL = "Товары"
from database.models import Product
FIELDS = {
'name': 'text',
'sku': 'text',
'price': 'number',
'category': 'select',
'description': 'textarea',
'in_stock': 'checkbox'
}
SELECT_OPTIONS = {
'category': ['Электроника', 'Одежда', 'Книги', 'Продукты']
}
ENTITY_NAME = "Customer"
ENTITY_NAME_PLURAL = "Customers"
ENTITY_NAME_RU = "Клиент"
ENTITY_NAME_RU_PLURAL = "Клиенты"
FIELDS = {
'name': 'text',
'email': 'email',
'phone': 'text',
'company': 'text',
'vip': 'checkbox',
'notes': 'textarea'
}
templates/by-task/crud/streamlit-crud-v1/
├── README.md # Этот файл
├── crud_page.py # Основной шаблон CRUD страницы
└── template.yaml # Метаданные
Streamlit автоматически валидирует:
- Email поля (формат email)
- Числовые поля (только числа)
- Даты (корректная дата)
Добавь валидацию в функции create_item и update_item:
def create_item(data):
# Валидация
if not data.get('email'):
raise ValueError("Email обязателен")
if len(data.get('full_name', '')) < 3:
raise ValueError("Имя должно быть минимум 3 символа")
# Создание
session = get_session()
try:
new_user = User(**data)
session.add(new_user)
session.commit()
return new_user
except Exception as e:
session.rollback()
raise e
finally:
session.close()
Авторизация
python
# Добавить в начало страницы
from utils.auth_utils import require_auth
require_auth()
Права доступа
python
# Проверка прав перед удалением
user = get_current_user()
if user['role'] != 'admin':
st.error("❌ Недостаточно прав")
st.stop()
SQL Injection
- SQLAlchemy автоматически защищает от SQL injection
- Используй параметризованные запросы
XSS
- Streamlit автоматически экранирует HTML
- Не используй unsafe_allow_html без необходимости
Для больших таблиц добавь пагинацию:
# После получения items
items_per_page = 50
page = st.number_input("Страница", min_value=1, value=1)
start = (page - 1) * items_per_page
end = start + items_per_page
items_page = items[start:end]
st.write(f"Показано {start+1}-{min(end, len(items))} из {len(items)}")
Используй @st.cache_data для частых запросов:
@st.cache_data(ttl=60) # Кэш на 60 секунд
def get_all_items_cached():
return get_all_items()
Генерация с нуля: ~5000 tokens
Адаптация шаблона: ~700 tokens
Экономия: 86%
Проверь что items не пустой перед доступом к элементам.
Используй st.rerun() после успешного создания/обновления.
Используй уникальные key для каждого поля. В шаблоне используется key_suffix для этого.
Проверь:
1. Функция update_item вызывается
2. session.commit() выполняется
3. Нет исключений (проверь логи)
# В разделе "Быстрые действия"
with col3:
if st.button("📥 Экспорт в Excel", use_container_width=True):
df = pd.DataFrame([vars(item) for item in items])
buffer = BytesIO()
with pd.ExcelWriter(buffer, engine='openpyxl') as writer:
df.to_excel(writer, index=False)
buffer.seek(0)
st.download_button(
label="⬇️ Скачать Excel",
data=buffer,
file_name=f"{ENTITY_NAME_PLURAL}_{datetime.now().strftime('%Y%m%d')}.xlsx",
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
)
# Массовое удаление
selected_ids = st.multiselect("Выбрать несколько", item_ids)
if st.button("🗑️ Удалить выбранные"):
for item_id in selected_ids:
delete_item(item_id)
st.success(f"Удалено {len(selected_ids)} записей")
st.rerun()
Версия: 1.0
Дата: 2025-11-10
Статус: Production ready