Aula 15 – Loja Online – Django – URLs dos Produtos

More videos
Views
   

Loja Virtual – Ecommerce – Django – URLs dos Produtos

Estamos prestes a terminar com a base da app produtos, isto é, do componente produto.

Não fizemos as outras partes do crud, atualizar e excluir, essas partes do crud a gente pode fazer como administrador no Django, não precisamos nos preocupar com isso.

Os usuários não vão poder editar um produto, muito menos excluir um produto do banco.

A gente focou muito na view dos produtos, porque isso é o mais importante, nós queremos ter certeza de que os usuários possam ver os produtos.

Vamos desafogar um pouco nosso src/e_commerce/urls.py criando um outro urls.py, o urls.py para o product, ou seja, src/product/urls.py.

Depois criaremos no nosso model dentro da class Product, o método get_absolute_url(), que irá retornar a url de um produto.

Então vamos lá!

Primeiro vamos organizar melhor as nossas urls, vamos dividir em dois arquivos:

  • src/e_commerce/urls.py
  • src/product/urls.py

Crie o src/product/urls.py com o seguinte conteúdo:

from django.urls import path

from .views import (
                        ProductListView, 
                        ProductDetailSlugView,
                    )

urlpatterns = [
    path('', ProductListView.as_view()),
    path('<slug:slug>/', ProductDetailSlugView.as_view())
]

Atualize o src/e_commerce/urls.py:


from django.conf import settings
from django.conf.urls.static import static

from django.contrib import admin
from django.urls import path, include

from .views import (home_page, 
                    about_page, 
                    contact_page, 
                    login_page, 
                    register_page
)

urlpatterns = [
    path('', home_page),
    path('about/', about_page),
    path('contact/', contact_page),
    path('login/', login_page),
    path('register/', register_page),
    path('products/', include("products.urls")),
    path('admin/', admin.site.urls),
]

if settings.DEBUG:
    urlpatterns = urlpatterns + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns = urlpatterns + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Dessa forma nossas URLs ficaram bem melhores, veja que fizemos o import do include, e com ele importamos o urls.py do products, ou seja, src/product/urls.py para dentro do src/e_commerce/urls.py.

Nossas URLs melhoraram bastante.

Note que não temos mais as urls detail view, não vamos mais precisar delas.

Elas nos mostravam os detalhes dos produtos baseado no id de um produto na URL, o que não é interessante pois expõe o id daquele produto no banco de dados, além de não ser amigável para o usuário, prejudicando o SEO.

Quem vai mostrar os detalhes de cada produto agora é a nossa CBV (Class Based View) ProductDetailSlugView, construída na aula passada.

Ela mostra os detalhes do produto baseado no slug do produto, mostrando na url o slug do produto e não seu id.

Vamos criar o método get_absolute_url no nosso modelo produto, então em src/products/models.py, acrescente o método que tá em laranja, o get_absolute_url:


import random
import os
from django.db import models
from django.db.models.signals import pre_save, post_save

from .utils import unique_slug_generator

def get_filename_ext(filepath):
    base_name = os.path.basename(filepath)
    name, ext = os.path.splitext(base_name)
    return name, ext


def upload_image_path(instance, filename):
    new_filename = random.randint(1, 3910209312)
    name, ext = get_filename_ext(filename)
    final_filename = '{new_filename}{ext}'.format(new_filename = new_filename, ext = ext) #old format
    #final_filename = f"{new_filename}{ext}" #syntax to python 3.6 and up

    return "products/{new_filename}/{final_filename}".format(
            new_filename = new_filename, 
            final_filename = final_filename
            )
    #return f"products/{new_filename}/{new_filename}" #syntax to python 3.6 and up

class ProductQuerySet(models.query.QuerySet):
    def active(self):
        return self.filter(active = True)

    def featured(self):
        return self.filter(featured = True, active = True)

class ProductManager(models.Manager):
    def get_queryset(self):
        return ProductQuerySet(self.model, using = self._db)

    def all(self):
        return self.get_queryset().active()

    def featured(self):
        return self.get_queryset().featured()

    def get_by_id(self, id):
        qs = self.get_queryset().filter(id = id)
        if qs.count() == 1:
            return qs.first()
        return None


# Create your models here.
class Product(models.Model): #product_category
    title       = models.CharField(max_length=120)
    slug        = models.SlugField(blank = True, unique = True)
    description = models.TextField()
    price       = models.DecimalField(decimal_places=2, max_digits=20, default=39.99)
    image       = models.ImageField(upload_to = upload_image_path, null = True, blank = True)
    featured     = models.BooleanField(default = False)
    active     = models.BooleanField(default = True)

    objects     = ProductManager()

    def get_absolute_url(self):
        return "/products/{slug}/".format(slug = self.slug)

    def __str__(self):
        return self.title
    
    def __unicode__(self):
        return self.title

def product_pre_save_receiver(sender, instance, *args, **kwargs):
    if not instance.slug:
        instance.slug = unique_slug_generator(instance)

pre_save.connect(product_pre_save_receiver, sender = Product)

O get_absolute_url vai devolver a string com o slug do produto consultado, para montar a url.

Agora vamos alterar o template inserindo a tag <a> com o hrefs apontando para a url do produto.

Então modifique o src/products/templates/products/list.html:


{% for obj in object_list %}
	<a href='{{ obj.get_absolute_url }}'>{{ obj.title }}</a><br/>
{% endfor%}

Agora os usuários poderão navegar pelos produtos clicando nos links.

O get_absolute_url é uma convenção do Django, é necessário para usar a função reverse() que iremos falar depois, mas, só pra dá uma leve pincelada, a principal vantagem do reverse() é que você não precisa codificar rotas no código.

O reverse () é usado para aderir ao princípio DRY (don’t repeat yourself), ou seja, se você alterar uma url no futuro, poderá fazer referência a essa url usando reverse (nome_da_url).

Usar o get_absolute_url é mais conveniente e vai facilitar a nossa vida, se precisar mudar qualquer URL basta ir a um lugar para fazer isso.

As convenções do django não são obrigatórias, mas, são importantes, pois são baseadas no que desenvolvedores experientes consideram ser o melhor caminho para fazer determinadas coisas.

É isso programadoras e programadores, vou ficando por aqui.

Na próxima aula, vamos melhorar nossos HTMLs.

Dêem um joinha 👍 na página do Código Fluente no Facebook
https://www.facebook.com/Codigofluente-338485370069035/

Vou deixar meu link de referidos na digitalocean pra vocês.

Quem se cadastrar por esse link, ganha $100.00 dólares de crédito na digitalocean:

Digital Ocean

Esse outro link é da one.com:

One.com

Para baixar o código como está até agora, acesse o link abaixo:
https://github.com/toticavalcanti/django_ecommerce/tree/product_urls

Obrigado, até a próxima e 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>