Aula 89 – Lidando com o Sinal do Objeto Visualizado

Aula 89 – Lidando com o Sinal do Objeto Visualizado

Loja Online - Django

Loja Online – Django

Voltar para página principal do blog

Todas as aulas desse curso

Aula 88                                   Aula 90

Redes Sociais:

facebook

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Melhore seu NETWORKING

https://digitalinnovation.one/

Participe de comunidades de desenvolvedores:

Fiquem a vontade para me adicionar ao linkedin.

E também para me seguir no https://github.com/toticavalcanti.

Código final da aula:

https://github.com/toticavalcanti

Quer aprender python3 de graça e com certificado? Acesse então:

https://workover.com.br/python-codigo-fluente

Canais do Youtube

Toti

Lofi Music Zone Beats

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

PIX para doações

PIX Nubank

PIX Nubank


 

Aula 89 – Lidando com o Sinal do Objeto Visualizado

Agora vamos lidar com o sinal emitido pelo objeto visualizado.

Temos o mixin, temos o signal, que fizemos na aula passada, e portanto, uma forma de trabalhar com esses dados dos produtos visualizados.

Então bora lá!

Abra o models.py do analytics e faça as alterações indicadas abaixo em azul.

django_ecommerce/e_commerce/analytics/models.py


from django.conf import settings
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

from .signals import object_viewed_signal

User = settings.AUTH_USER_MODEL

class ObjectViewed(models.Model):
    user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE) # specific user, instance.id
    ip_address = models.CharField(max_length=220, blank=True, null=True)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) # Product, Order, Cart, Address...
    object_id = models.PositiveIntegerField() # User id, Product id, Order id
    content_object = GenericForeignKey('content_type', 'object_id')
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.content_object} viewed on {self.timestamp}"

    class Meta:
        ordering = ['-timestamp'] # most recent saved show up first
        verbose_name = 'Object viewed'
        verbose_name_plural = 'Objects viewed'

def object_viewed_receiver(sender, instance, request, *args, **kwargs):
    print(sender)
    print(instance)
    print(request)
    print(request.user)

object_viewed_signal.connect(object_viewed_receiver)

Agora entre na página de produtos, clique na view de algum produto e no console do servidor, vejo os prints da object_viewed_receiver().

Explicação das alterações feitas acima

  1. from .signals import object_viewed_signal: Importa um sinal personalizado chamado object_viewed_signal de um arquivo signals.py no mesmo diretório. Esse sinal é usado para notificar partes do aplicativo quando um objeto é visualizado.
  2. def object_viewed_receiver(sender, instance, request, *args, **kwargs): Define uma função que atua como receptor para o sinal object_viewed_signal. Essa função será chamada automaticamente quando o sinal for emitido. Ela recebe informações sobre o evento que disparou o sinal, incluindo o modelo que enviou o sinal (sender), a instância do modelo (instance), e o objeto de requisição HTTP (request).
  3. object_viewed_signal.connect(object_viewed_receiver): Conecta o receptor object_viewed_receiver ao sinal object_viewed_signal. Isso significa que, sempre que o sinal object_viewed_signal for emitido em qualquer parte do aplicativo, a função object_viewed_receiver será executada.

Esse código permite que você monitore quando um objeto específico é visualizado no seu aplicativo Django, executando a função object_viewed_receiver em resposta a esse evento.

Arquivo signals.py criado na aula passada

No arquivo signals.py, foi definido um sinal personalizado Django utilizando a classe Signal do módulo.

django_ecommerce/e_commerce/analytics/signals.py 

from django.dispatch import Signal
object_viewed_signal = Signal(providing_args=['instance', 'request'])

IMPORTANTE. A partir da versão 4.0 do Django, o signal não recebe mais o providing_args, portanto a forma correta do signals.py é essa abaixo.

Vejamos o que cada parte faz:

  1. Importação da Classe Signal:
    • from django.dispatch import Signal: Aqui, você está importando a classe Signal do módulo django.dispatch. No Django, Signal é uma forma de permitir que determinados remetentes notifiquem um conjunto de receptores quando ocorrem ações no sistema.
  2. Criação de um Sinal Personalizado (object_viewed_signal):
    • object_viewed_signal = Signal(providing_args=['instance', 'request']): Nesta linha, você está criando um sinal personalizado chamado object_viewed_signal.
    • providing_args=['instance', 'request']: Esta parte é uma maneira de documentar quais argumentos são esperados pelos receptores deste sinal. Aqui, os argumentos são instance (a instância do objeto que foi visualizado) e request (o objeto de requisição HTTP).

IMPORTANTE. A partir da versão 4.0 do Django, o signal não recebe mais o providing_args, portanto a forma correta do signals.py é essa abaixo.

django_ecommerce/e_commerce/analytics/signals.py 

from django.dispatch import Signal
object_viewed_signal = Signal()

Melhorando o utils.py

A razão para usar request.META.get("REMOTE_ADDR", None) é garantir que, se o endereço IP não estiver disponível no request.META, como em situações onde o usuário está atrás de um proxy, a função retornará None em vez de causar um erro.

Isso torna o código mais seguro e previne falhas caso a chave "REMOTE_ADDR" não exista no dicionário.

django_ecommerce/e_commerce/analytics/utils.py


def get_client_ip(request):
    # Obtém o valor do cabeçalho 'HTTP_X_FORWARDED_FOR' do objeto 'request.META'.
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    
    # Verifica se o cabeçalho 'HTTP_X_FORWARDED_FOR' está presente.
    if x_forwarded_for:
        # Se estiver presente, o cabeçalho pode conter uma lista de endereços IP separados por vírgulas.
        # Portanto, dividimos a string em uma lista usando ',' como delimitador e pegamos o primeiro elemento da lista,
        # que é o endereço IP do user.
        ip = x_forwarded_for.split(",")[0]
    else:
        # Se o cabeçalho 'HTTP_X_FORWARDED_FOR' não estiver presente, usamos o endereço IP do user
        # que está disponível em 'request.META["REMOTE_ADDR"]'.
        ip = request.META.get("REMOTE_ADDR", None)
    
    # Retornamos o endereço IP final.
    return ip 

Continuando as alterações do models.py do analytics

django_ecommerce/e_commerce/analytics/models.py


from django.conf import settings
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

from .signals import object_viewed_signal
from .utils import get_client_ip

User = settings.AUTH_USER_MODEL

class ObjectViewed(models.Model):
    user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE) # specific user, instance.id
    ip_address = models.CharField(max_length=220, blank=True, null=True)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) # Product, Order, Cart, Address...
    object_id = models.PositiveIntegerField() # User id, Product id, Order id
    content_object = GenericForeignKey('content_type', 'object_id')
    timestamp = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.content_object} viewed on {self.timestamp}"

    class Meta:
        ordering = ['-timestamp'] # most recent saved show up first
        verbose_name = 'Object viewed'
        verbose_name_plural = 'Objects viewed'

def object_viewed_receiver(sender, instance, request, *args, **kwargs):
    def object_viewed_receiver(sender, instance, request, *args, **kwargs):
    c_type = ContentType.objects.get_for_model(sender) # instance.__class__
    new_view_obj = ObjectViewed.objects.create(
        user = request.user,
        content_type=c_type,
        object_id=instance.id,
        ip_address = get_client_ip(request)
    )

object_viewed_signal.connect(object_viewed_receiver)

Agora entre na página de produtos e visualize alguns deles, depois entre na página de admin, acesse a parte de analytics/objectviewed.

E veja que agora temos uma forma de salvar e armazenar items visualizados.

Explicação das alterações

  1. Importação de get_client_ip:
    • from .utils import get_client_ip: Esta linha importa a função get_client_ip do móduloutils que está no mesmo diretório que o arquivo atual, indicado pelo .. A função get_client_ip é usada para obter o endereço IP do cliente que está fazendo a requisição.
  2. Função object_viewed_receiver:
    • Esta função é um receptor (receiver) de sinal que é chamado quando um objeto é visualizado. Em Django, os sinais permitem que determinadas ações sejam executadas em resposta a eventos específicos.
  3. Parâmetros da Função:
    • sender: O modelo que enviou o sinal.
    • instance: A instância do modelo que foi visualizada.
    • request: O objeto de requisição HTTP.
    • *args, **kwargs: Argumentos e palavras-chave adicionais.
  4. Corpo da Função:
    • c_type = ContentType.objects.get_for_model(sender): Obtém o ContentType para o modelo que enviou o sinal. ContentType é um modelo do Django que armazena informações sobre os modelos usados em um aplicativo.
    • new_view_obj = ObjectViewed.objects.create(...): Cria um novo registro no modelo ObjectViewed, salvando quem viu o objeto, qual foi o objeto, o ID do objeto e o endereço IP do usuário que o viu.
  5. Criação do Registro ObjectViewed:
    • user = request.user: O usuário que fez a requisição.
    • content_type = c_type: O tipo de conteúdo do objeto visualizado.
    • object_id = instance.id: O ID da instância visualizada.
    • ip_address = get_client_ip(request): O endereço IP do usuário, obtido pela função get_client_ip.
  6. Conexão com o Sinal:
    • object_viewed_signal.connect(object_viewed_receiver): Conecta o receptor object_viewed_receiver ao sinal object_viewed_signal. Isso significa que, sempre que o sinal object_viewed_signal for disparado, a função object_viewed_receiver será chamada.

Por essa aula é só, na próxima a gente vai fazer o handle do sinal emitido pelos objetos visualizados.

Voltar para página principal do blog

Todas as aulas desse curso

Aula 88                                   Aula 90

Código final da aula:

https://github.com/toticavalcanti

Canais do Youtube

Toti

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

Dêem um joinha 👍 na página do Código Fluente no
Facebook.

Sigam o Código Fluente no Instagram e no TikTok.

Código Fluente no Pinterest.

Meus links de afiliados:

Hostinger

Digital Ocean

One.com

Nos vemos na próxima então, \o/  😉 Bons Estudos!

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>