← Назад к вопросам

Как вывести три случайных сущности на одну из страниц?

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

Выбирай метод в зависимости от размера таблицы и частоты обновлений данных.

Как вывести три случайных сущности на одну из страниц? | PrepBro