← Назад к вопросам
Как вывести три случайных сущности на одну из страниц?
1.3 Junior🔥 121 комментариев
#Django#Базы данных (SQL)
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Вывод трёх случайных сущностей на страницу
Вот несколько способов получить случайные элементы из базы данных и вывести их на страницу:
1. SQLAlchemy + func.random() (общий способ)
from sqlalchemy import select, func
from sqlalchemy.orm import Session
from models import Product # или любая другая модель
def get_random_products(session: Session, limit: int = 3):
"""Получить 3 случайных товара из базы"""
stmt = select(Product).order_by(func.random()).limit(limit)
products = session.execute(stmt).scalars().all()
return products
2. PostgreSQL - более эффективный способ
Для PostgreSQL лучше использовать встроенную функцию RANDOM():
from sqlalchemy import text
from sqlalchemy.orm import Session
def get_random_products_postgres(session: Session, limit: int = 3):
"""Получить случайные товары из PostgreSQL (оптимизировано)"""
query = text(
"SELECT * FROM products ORDER BY RANDOM() LIMIT :limit"
)
result = session.execute(query, {"limit": limit})
return result.fetchall()
3. FastAPI endpoint для вывода случайных сущностей
from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
from typing import Annotated
app = FastAPI()
def get_db() -> Generator[Session, None, None]:
session = SessionLocal()
try:
yield session
finally:
session.close()
@app.get("/api/v1/products/random")
def get_random_products(
limit: int = 3,
db: Annotated[Session, Depends(get_db)] = None
):
"""API endpoint для получения случайных товаров"""
from sqlalchemy import select, func
from models import Product
stmt = select(Product).order_by(func.random()).limit(limit)
products = db.execute(stmt).scalars().all()
return [
{
"id": p.id,
"name": p.name,
"price": p.price,
"description": p.description
}
for p in products
]
4. Django ORM
Если используешь Django:
from django.db.models import Q
from .models import Product
def get_random_products(limit=3):
"""Получить случайные товары в Django"""
return Product.objects.order_by('?')[:limit]
# В view
from django.shortcuts import render
def product_page(request):
random_products = get_random_products()
return render(request, 'products.html', {
'random_products': random_products
})
5. Frontend - React/Next.js
import { useEffect, useState } from 'react';
function RandomProducts() {
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchRandomProducts() {
try {
const response = await fetch('/api/v1/products/random?limit=3');
const data = await response.json();
setProducts(data);
} catch (error) {
console.error('Ошибка при загрузке товаров:', error);
} finally {
setLoading(false);
}
}
fetchRandomProducts();
}, []);
if (loading) return <div>Загрузка...</div>;
return (
<div className="random-products">
{products.map((product) => (
<div key={product.id} className="product-card">
<h3>{product.name}</h3>
<p>{product.description}</p>
<p className="price">{product.price} руб.</p>
</div>
))}
</div>
);
}
export default RandomProducts;
6. Более производительный способ (кеширование)
Для часто посещаемых страниц лучше кешировать результаты:
from functools import lru_cache
import asyncio
from datetime import datetime, timedelta
class RandomProductsCache:
def __init__(self, cache_ttl_seconds: int = 300):
self.cache = None
self.cache_time = None
self.ttl = cache_ttl_seconds
def is_expired(self) -> bool:
if not self.cache_time:
return True
return datetime.now() - self.cache_time > timedelta(seconds=self.ttl)
def get_random_products(self, session: Session, limit: int = 3):
if not self.is_expired():
return self.cache
from sqlalchemy import select, func
from models import Product
stmt = select(Product).order_by(func.random()).limit(limit)
products = session.execute(stmt).scalars().all()
self.cache = products
self.cache_time = datetime.now()
return products
# Использование
product_cache = RandomProductsCache(cache_ttl_seconds=300)
@app.get("/api/v1/products/random")
def get_random_products(
db: Annotated[Session, Depends(get_db)] = None
):
products = product_cache.get_random_products(db)
return [p.to_dict() for p in products]
7. Альтернатива - выбрать случайные ID вручную
Для очень больших таблиц RANDOM() может быть медленным:
import random
from sqlalchemy import select, func
from models import Product
def get_random_products_optimized(session: Session, limit: int = 3):
"""Оптимизированный способ для очень больших таблиц"""
# Получить общее количество
total_count = session.execute(
select(func.count()).select_from(Product)
).scalar()
# Выбрать случайные смещения
random_offsets = sorted([random.randint(0, total_count - 1) for _ in range(limit)])
# Получить товары по смещениям
products = []
for offset in random_offsets:
stmt = select(Product).offset(offset).limit(1)
product = session.execute(stmt).scalar()
if product:
products.append(product)
return products
Сравнение методов
| Метод | Скорость | Когда использовать |
|---|---|---|
| ORDER BY RANDOM() | Медленнее на больших таблицах | До 100k записей |
| Кеширование | Очень быстро | Часто посещаемые страницы |
| Случайные ID | Быстро | Миллионы записей |
| Предвычисленные наборы | Очень быстро | Стабильные случайные наборы |
Вывод
Для стандартного случая:
stmt = select(Product).order_by(func.random()).limit(3)
Для высоконагруженного приложения:
- Кешируй результаты на 5-10 минут
- Или используй предвычисленные случайные наборы
- Для очень больших таблиц - выбирай по случайным ID
Выбирай метод в зависимости от размера таблицы и частоты обновлений данных.