Estás Navegando ru ООН Ecommerce, Llama Llama un Producto Tu atención y Нажмите Para Verlo, нет TE Convence. Решит от Otrass Otrass Opciones, гасс щелчок en un nuevo producto y, Cuando Hages Scroll Al Fondo de la Página, La Página Te Muestra EL Primer Producto Que Viste БАЙДЕ ЛЕ ЛЕЙЕНДА “ВИСТОС Recientemente”. Tú поуэдит Хейсеру Л.М. МИММО У Джанго Й Редис.
django y redis.
Agrogar Una Sección de Productos VisitaDos Aummerce Las Ventas en ecommerce y mantiene Al Usuario Más Tiempo En La Página. ES Normal Añadir Este Historial A US USUARIO Que Ya Está en la Base de datos. Los Encargados de la Página Web Tienen ООН истории de los productos que vemos, los que compramos, cuanto tiempo pasamos viéndolos y mouseos otros datos pero … ¿y los usuarios annónimos que no tienen una cuenta?
Историал де Сирта Пагина де электронной коммерции que ya Нет Necesita Más Pubouldididad.
A lo mejor no te interesa (o tu empresa) Tener Guardados en una base de ditos elistorial de millones de productos visitados por cada usuario anónimo que visita el sitio, Перо Аун Así Te Gustaría Mastrarle CADA USUARIO, REGIGNADO O NO, LOS Productos que ha visto.
Redis es en motor de base de datos muy eficatione, trabaja con datos volátiles, Pues Almacena Su Información en Memoria, POR LO Que Su Acceso Es Casi Instantáneo, Aunque Volátil. Sin Embargo ES Positible Volcar SU Información A un Medio Parstary, COMO MySQL, Postgres U Otra Base DE DECOS, СОПОРМЕНЕНИЯ Отказ Seguramente PodeMos Usar Redis Pero … ¿Cómo Vamos Diferenciar Usuario Anónimo de Otro?
HAHE MOSSAS MANERAS DE ABRORDAR ESE SCRELYA, PUEDES ASOCIAR US USUARIO (Y SU ИСТОРИИ) CONA Cookie, IP O Hasta Unace Defiliado и т. Д. EL TIPO DE DETO QUE DESSEES VINCUL CONEDEDEE DE LAS Intenciones del Negocio. Para Este EJEMPLO USAREMOS SESSARE SESSION KEY DEL Sistema de Sesiones que ya viene incluido en django de manera predeterminada.
Instalar Redis EN GNU/Linux
Antes de Empezar A USAR Django Y Redis Hay Que Instalar Este último En Nuestro Sistema Operativo GNU/Linux. Si no tienes ni Idey de los comandos básicos en antero antero linux te sugiero Visitar Mi Entrada Que Habla de Los Comandos Más Comunes.
sudo apt install redis-server redis-server
Instalar Redis Para Pishon
Continuación Vamos A Instalar El Paquete Que Vincula Redis Con Python.
pip install redis
EN EL Archivo settings.py De Nuestra Appleación, Agrogamos Los Valores Por Defecto Que Vamos Usar. ESTOS PuEDEN SER DIFERENTES SI TU SERVISTOR DE REDIS ESTA EN OTRA UBICACION O SI ELEVISTE OTRO PUERTO EN LUGAR DEL PREDETEMINADO.
# settings.py # ... REDIS_HOST = 'localhost' REDIS_PORT = 6379 REDIS_DB = 0
Además le pediremos a django que harde La Sesión Con Cada Petición Y Nos Aseguraremos Que Esté Activeo El Mardware Para Sesiones.
# settings.py MIDDLEWARES = [ 'django.contrib.sessions.middleware.SessionMiddleware', # ... ] # ... SESSION_SAVE_EVERY_REQUEST = True
Para Este Ejemplo Uso Un Modelo Llamado Продукт, Pero Tu Peedes Sustituirlo POR EL EQUIVALENTE RU TU ALPACACIón.
# app/models.py from django.db import models class Product(models.Model): # ...
Si имеет Llegado Hasta Aquí, Pero No Tienes Idey De Como Funciona Django Tengo Unas EntraDas Donde Reseño Un Par de Libros que Pueden Servirte: El libro indepitivo de django (Gratuito) o Django по примеру
Eligiendo el valor que usaremos como llave en django y redis
Primero Hay Que Elegir El Momento En Que Redis Guardará Nuestro Acceso Al Producto. La Vista que devualve los утолщёны de un producto sería lo идеально. De esta manera, cada que unsuario del sitio web acceda a los detalles del producto agregaremos la información del Producto AdiledAdor de Usuario.
# app/views.py from .models import Product from django.shortcuts import get_object_or_404 def product_details(request, product_id): products = Product.objects.all() # O el queryset que prefieras product = get_object_or_404(products, product_id) # ... más código
Primeramente, Vamos A obtener El objeto Cuyos разветвляет Estamos Conssorado, Para Eso Usamos get_object_or_404 Al Que Le Pasamos un Queryset o un modelo y el ID Que Buscará.
Ahora Vamos a Crage Una Serie de Funciones Para Facilitar Nuestro Trabajo, Puedes Crarlas en Archivo Searado, Yo Le lllamaré usils.py.
Conectar Redis Y Python
En El Archivo de Utils.py Vamos Ettome Enty Ena Conexión Entre Python Y Redis. El Método Strictredis Recibirá Los Valores, Estos Son Los Mismos Que Escesificalamos En Nuestro Archivo de Configuración, POR LO Que Podemos Importarlos Directamente de Ahí.
# app/utils.py import redis from django.conf import settings r = redis.StrictRedis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=settings.REDIS_DB)
CREAR undeificator de usaario para usar como llave en redis
Queremos asociar cada llave de redis un usuario, por lo que, necesitamos una función que nos devuelva una manera de Идентифицирован Cada Usuario de Nuestra Página. PARA USUARIOS ANONIMOS LO IDEAL SERIA USAR SESSAR SESSION SESSION, SI QUEREMOS ELCOR USUARIOS CON CUETO PODEMOS ASOCIARLOS DIREATAMESTE CON SU USUARIO.
Nuestra Función Guarda La Sesión Si No Essee Una session_key. de esta manera nos aseguraremos de siempre contar con una. La Función nos devolverá la Session_key Si El Usuario es Anónimo O El Usuario Si Este Ya Esta Loggeado.
Para Esto Es Necesario Que reciba El Objeto запрос COMO ARDUCTO.
# app/utils.py def get_user_id_for_redis(request): if not request.session.session_key: request.session.save() return request.session.session_key if request.user.is_anonymous else request.user
Gravelar Valores en redis con lpush o rpush
La Manera en la que redis los datos es vinculándolos con una llave, esa llave tiene una lista asociada que será la que antendrá la información.
Es bastante похожая un diccionario que tiene una lista como доблесть. El Equivalente En Código Python Se Vería Más o Menos así:
{"id_de_usuario_unico_1": [34, 22, 100, 5, 6], "id_de_usuario_unico_2": [112, 444, 3]}
Los números que googenaremos serán los id o llaves primarias de los productos.
Para Penirle a redis que extienda esa lista por El Commartio Usaremos Lpush Отказ
Эль Методо Lpush заливка; El Nombre de la llave que Grougaremos, Como Primer Purging; ООН Valor Que Agregará A Al Inicio Lista de Valores Asociada, Como Segundo Puranto. En caso de que La Llave No Essea, La Creará. Además Lpush Retorna El Tamaño de la lista asociada a lay llave que que que le pasamos como pragingo. El Método Rpush Hace Lo Mismo Pero Por El Final.
Sabiendo Esto Creemos Una Función Que Tome unsuario y un und de producto y se los pase redis para que los garde, nuestra función recornará el valor que devualve Lpush Отказ
# app/utils.py def create_product_history_by_user(user_id, product_id): product_history_length = r.lpush(user_id, product_id) return product_history_length
Continuanno Con La Analogía Annoherior, Lpush Haría Algo Parecido Esto.
{"id_de_usuario_unico_1": [34, 22, 100, 5, 6]} r.lpush("id_de_usuario_unico_1", 1000) {"id_de_usuario_unico_1": [1000, 34, 22, 100, 5, 6]}
Obtener una lista de valores asociada a una llave con lrange
Ahora Que Ya Hemos Creado Una Función Para Extender Una lista Asociada A unsuario, Creamos Una Función Que nos devuelva esa lista.
USEMOS лишать
Эль Методо lrange NOS PASARLE UNA LLAVE ( user_id ) y nos devolverá la lista que tiene asignada , Desde El Valor Eniacy (0), Hasta El Final (4), Contando Desde El Commaribied. ES DECIR, LOS ELEALION CON INDICS DEL 0 AL 4. COMO Нет Queremos Repetir Valores, Recurriremos Una Установить понимание Para Transformar Los Valores en Enterop.
# app/utils.py def get_products_ids_by_user(user_id): last_viewed_products_ids = r.lrange(user_id, 0, -1) # Devuelve [b'2', b'4', ...] last_viewed_products_ids_list = {int(id) for id in last_viewed_products_ids} return last_viewed_products_ids_list
ESTA Función Nos Devolverá únicamente Esos Valores de Redis, Para Que Podamos Saber Que Productos Retornaremos de la Base de Datos.
Creando un Queryset Partir de Valores de Redis
La Función Ansiory Nos Devualve Una Lista de Valores, переписывает ID O Llaves Primarias de Productos En Nuestra Base de Datos.
USAREMOS ESA LISTA DE VALORES PARA FILTRAR Productos EN Nuestra Base DE DETOS, UN USO BASTANTE COMúN DEL ORM DE DJANGO CON EL QUE NO DEBERYAS TENERAS.
BásiCamente COOTA: COUTÉN TODOS LOS Productos Y Luego Fíltralos de Manera Que Solo Queden Aquellos Productos Cuyo I d o llave primaria se encientre en la lista llamada product_ids.
# app/utils.py from .models import Product def get_product_history_queryset_by_user(product_ids, product_id): last_viewed_products_queryset = Product.objects.all().filter( id__in=product_ids).exclude(id=product_id) return last_viewed_products_queryset
Toma en cuenta que puedes sustituir la query Product.Objects.all () пункт La Queryset Que Tú. Quizás Prefieras no masturar todos los productos ru tu base de ditos, Sino Solo Los Activeos, Los Que Tengan Inventario O Custerquier Otra Combinación.
Evitemos Harritar Валкомреорки Repetidos
COMO No Queremos que en la la lista de productos vistos se repitan productos, vamos a asgurarnaros de que el id o llave primaria del producto no se Encuentre en la lista que estamos obteniendo angregarlo.
Para Hacerlo Solo Revisamos que EL ID del Producto SE Entuentre Fuera de la lista que nos rovesea la función get_products_ids_by_user que escribimos insormente.
# app/views.py from .models import Product from django.shortcuts import get_object_or_404 def product_details(request, product_id): # ... user_id = get_user_id_for_redis(request) product_ids = get_products_ids_by_user(user_id) if int(product_id) not in product_ids: create_product_history_by_user(user_id, product_id) product_history_queryset = get_product_history_queryset_by_user(product_ids) # ... más código
Sin Embargo Ahora Nos Topamos Con Otro Проблема, Que Pasa Si Nuestra Tienda Tiene Decenas de Male de Productos y nuestro trafico diario son decenas de miles de usuarios, ¿de verdad queremos mantener en memoria una lista tan grande de productos visitados? La Mayoría de Los Usuarios Нет Revisarán Sus últimos Mil Productos Para Ver Si Se Les Antoja Comprar Allgo.
ES Innecesario Mantener Una Lista Tan Larga Si Solo Vamos Acceder A anced a unos cuantos productos.
¿Cómo Lo Solucionamos? Necesitamos Crage Una Función Que Nos Ayude Mantener La Lista de productos Asociados A una llave en redis en límite.
RPOP Y LPOP de Redis Remueven Un Elemento de Una lista
El Método RPOP SE Encarga de Remover El último Elemento de Una losa asociada a una llave y lo devualve. EL MÉTODO LPOP HACE LO MIMSO, PERO CON EL PRIMER ELEVELEO
PodeMos USAR RPOP PARA PARA REMOVER EL ELEVENTO Más Antiguo E IR DEPURANDO LOS ELEVELES Más Viejos. Si Con La última Incerción La Lista Crece Más Allá de Nuestro Limite (En Este Caso 5) Quitaremos El Elemento Más Antiguo.
# app/utils.py from .models import Product def limit_product_history_length(user_id, product_history_length): if product_history_length > 5: r.pop(user_id)
ltrim es una альтернатива y rpop y lpop y
La Función ЛТРИМ de redis se encarga de cortar los valores siveres de losa asociada a una llave Le indimos El índice Seiacty Y SU INDICE Final Como Argingos.
La Diferencia Que Tiene Con Ltrim Es Que Su Tiempo de Ejecución Es O (n), Puesto Ceence Coneed Coneedover, MientArs Que Para RPOP ES DE O (1). Si no tienes Idea de que te estoy hablando tissa Mi entrada donde hablo un poco sobre la notación большой o o quédate con la Idea de que si solo vamos a Eliminar un remention rpop es mejor. Sin Embargo Puede Que quieras un comportamiento diferente y sirva más usar ловкий .
Redis Tiene información del Tiempo de Ejecución de Cada Función en do Documentación Y Pude Ser Muy útil Si El Rendimiento de Tu Alplicación de django Es.
# app/utils.py from .models import Product def limit_product_history_length(user_id, product_history_length): if product_history_length > 5: r.ltrim(user_id, 0, 5)
Ahora Agrogamos La Función Para Que Se ejecute SOLO Si Ha Habido Una Inserción de un premento en redis, es decir, si el producto Фактический без SE Encuentra En Nuestra Lista.
# app/views.py from .models import Product from django.shortcuts import get_object_or_404 def product_details(request, product_id): # ... user_id = get_user_id_for_redis(request) product_ids = get_products_ids_by_user(user_id) if product_id not in product_ids: product_history_length = create_product_history_by_user(user_id, product_id) limit_product_history_length(user_id, product_history_length) product_history_queryset = get_product_history_queryset_by_user(request.user, product_ids) # ... más código
AHORA QUE TENEMOS EL QUERYSET CON LOS DETOS DE REDIS, PODEMOS RECORNARLO Y RENDERIZARLO EN UNA PLOTILLA DE DE DJANGO, PRECESARLO PARA DEVOLVER UNA RESSUESTA JSON o lo que tu queplación requeivera.
# app/views.py from django.shortcuts import get_object_or_404 from django.template.response import TemplateResponse def product_details(request, product_id): # ... context = {"visited_products": visited_products} return TemplateResponse( request, 'product/details.html', context)
Asignar Una Fecha de Expiración a los datos en redis
Перо, que tal si No Nos Interesa Que Tantos Productos Vea un Cliente Anónimo, Sino El Tiempo Que Los Guardamos.
Quizás Hoy El Clients quiera Comprar Comprar Producto En Esperial, Pero A Lo Mejor Solidamos Inútil MaStarle ESE Mismo Producto Tres Meses Después. ¿ Побуждение Нет ponerle una fecha de expiración a la lista que estamos guardando? Si El Usuario Нет Vuelve Visager Nuevo Producto Tras Transcurrir Cierta Cantidad de Tiempo Se Borrará La Información.
R.Expire оставлять La llave que queremos que Caduque y El Tiempo Para Su Eliminación, En Enes Orden, Como Sus Argugeos. Para Este Ejemplo Le He He asignado Tres Meses. Y así se Иран Борряндо Лос Историал Де Лас-Сезиойс Инактивас Квер Хан Эстадо Инактивас Пор Ларго Tiempo.
# app/utils.py from .models import Product def create_product_history_by_user(user_id, product_id): product_history_length = r.lpush(user_id, product_id) r.expire(user_id, 60*60*24*90) return product_history_length
Redis Tiene Mucho Para ofrecer, Y Vincularlo Con Django Te Permiterá Hacer Luceo. Тэхо Ла Documentación de Redis POR SI Q QUIERES PROFUNDIZAR ELLE ELLA Y SUS Привязки en python.
Оригинал: “https://dev.to/silicosis/como-crear-un-historial-de-productos-visitados-con-django-y-redis-291l”