Aula 10 – Loja Online – Ecommerce – Django – Image field – File field

Loja Virtual – Ecommerce – Django – Campo para upload de imagens ou arquivos

Na aula passada construimos a parte referente aos detalhes de cada produto.

Vamos continuar na parte dos detalhes de um produto com os image field e file field.

Agora os campos para upload de imagens ou arquivos referente a cada produto.

Campo para Imagem e para arquivo

Campo para Imagem e para arquivo

Voltar para página principal do blog

Todas as aulas desse curso

Aula 09                Aula 11

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

Curta a 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

Campo para upload de imagens ou arquivos de um produto.

Em src/products/models.py acrescente:


from django.db import models

# Create your models here.
class Product(models.Model): #product_category
    title       = models.CharField(max_length=120)
    description = models.TextField()
    price       = models.DecimalField(decimal_places=2, max_digits=20, default=100.00)
    image       = models.FileField(upload_to = 'products/')
    
    #python 3
    def __str__(self):
        return self.title
    #python 2
    def __unicode__(self):
        return self.title

Static CDN(Content Delivery Network)

Vamos criar a pasta dentro da nossa pasta static_cdn, que tá simulando um cdn, a pasta media_root, que ainda não criamos, então crie: django_ecommerce/media_root/ no mesmo nível da static_root.

As imagens e arquivos vão ser carregadas nessa pasta como configurado no final do src/e_commerce/settings.py

Rode o comando:

python manage.py makemigrations

Veja a mensagem que o Django mostra: ele reclama que você tá tentando adicionar um campo que não pode ser nulo (null) ou em branco.

Para corrigir isso acrescente ao campo image no src/products/models.py o que tá em laranja.


from django.db import models

# Create your models here.
class Product(models.Model): #product_category
    title       = models.CharField(max_length=120)
    description = models.TextField()
    price       = models.DecimalField(decimal_places=2, max_digits=20, default=100.00)
    image       = models.FileField(upload_to = 'products/', null = True, blank = True)
    
    #python 3
    def __str__(self):
        return self.title
    #python 2
    def __unicode__(self):
        return self.title

Campo obrigatório

O null = True quer dizer que você pode ter esse campo em branco no banco de dados e o blank = True quer dizer que não é um campo obrigatório no Django.

Resumindo, os dois juntos diz ao Django que esse campo não é obrigatório está preenchido.

Rode novamente o comando:

python manage.py makemigrations

python manage.py migrate

python manage.py makemigrations: Cria as migrações (gera os comandos SQL).

python manage.py migrate: executa as migrações (executa os comandos SQL).

Veja que dessa vez não houve nenhum problema, o Django não reclamou de nada.

Testando

Levante o servidor se não tiver já rodando:

python manage.py runserver

Entre na página de administrador e faça o login:

127.0.0.1:8000/admin/

Clique em products, clique em algum produto, veja que agora tem o campo image, mas, ele tá meio cinza e não tá em negrito como os outros campos, troque o blank = True, para False, dê um refresh na página e veja que ele fica como os outros campos, mais preto e em negrito.

Campo não obrigatório

Como queremos que esse campo não seja obrigatório, então deixe do jeito que tava mesmo, com o blank = True.

Faça o upload de uma imagem para esse produto e veja que ela fica na url: 127.0.0.1:8000/media/products/imagem_produto.jpg

O /media/ vem do MEDIA_URL = ‘/media/’ no src/e_commerce/settings.py e products do image = models.FileField(upload_to = ‘products/’, null = True, blank = True) no src/products/models.py , depois é o nome do arquivo (imagem_produto.jpg)

Esse campo é para carregar apenas imagens, mas, se você tentar carregar outro tipo de arquivo, ele vai aceitar, por isso vamos modificar a linha: image = models.FileField(upload_to = ‘products/’, null = True, blank = True) em src/products/models.py.

Pillow

Vamos trocar models.FileField para models.ImageField, mas veja que vai dá um erro, o Django reclama que o Pillow não está instalado, então rode o comando abaixo para instalar o Pillow:

pip install pillow

É uma biblioteca python para imagens.

Rode agora:

python manage.py makemigrations

python manage.py migrate

Levante o servidor se já não estiver no ar.

python manage.py runserver

Tente fazer o upload de algo que não seja uma imagem e veja o erro que dá: Upload a valid image….

Faça o upload de uma imagem de tênis e insira no produto tênis (tenis.png), para testar.

Temos agora que renderizar a imagem referente ao produto na página de template do detail.

Em src/products/template/products/detail.html insira:


{{ object.title }} <br/>
{{ object.description }} <br/>
{{ object.image }}

Salve e veja o resultado no browser em 127.0.0.1:8000/products/2

Veja que não mostrou a imagem, apenas a url da imagem, mesmo assim, a url errada, se você copiar a url 127.0.0.1:8000/products/imagem_123454e3.png, e colar na barra de endereço do browser, a imagem não vai ser encontrada.

Por isso, vamos a mais uma alteração no template do detail, vamos inserir url em object.image

src/products/template/products/detail.html


{{ object.title }} <br/>
{{ object.description }} <br/>
{{ object.image.url }}

Agora sim, a url da imagem está correta: 127.0.0.1:8000/media/products/tenis_lnVQeVY.jpeg

A imagem ainda não aparece na página, só o caminho dela, então vamos modificar novamente o src/products/template/products/detail.html


{{ object.title }} <br/>
{{ object.description }} <br/>
<img src='{{ object.image.url }}' class='img-fluid' />

Colocamos a tag HTML img e também definimos a class como img-fluid, que é uma classe do bootstrap.

Veja o resultado no browser

127.0.0.1:8000/products/2

Na próxima aula, iremos brincar e entender um pouco mais sobre consultas queryset e ver como que recuperar as informações do banco.

Aula 09                Aula 11

Todas as aulas desse curso

Voltar para página principal do blog

Curta a 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/file_and_images_field

Obrigado, até a próxima e bons estudos. 😉

About The Author
-

4 Comentários

  • Jerônimo
    Reply

    se eu quiser salva em pastas separadas?

    tipo:
    produtos/brinquedos/img1….
    produtos/brinquedos/img2….
    produtos/eletronicos/img1….
    produtos/eletronicos/img2….

    • toticavalcanti
      Reply

      Fala Jerônimo, blz?
      O models.py tá assim:

      
      from django.db import models
      # Create your models here.
      class Product(models.Model): #product_category
          title       = models.CharField(max_length=120)
          description = models.TextField()
          price       = models.DecimalField(decimal_places=2, max_digits=20, default=100.00)
          image       = models.FileField(upload_to = 'products/')
          
          #python 3
          def __str__(self):
              return self.title
          #python 2
          def __unicode__(self):
              return self.title
      

      Você tem a classe products, ela pode ser a classe genérica, ou seja, a super classe, e você pode ter subclasses que extendam products.
      Então, usando o exemplo que você deu, a subclasse brinquedos pode extender a classe products e ter a linha:
      image = models.FileField(upload_to = ‘products/toys/’)
      Sobrescrevendo a linha da super classe products:
      image = models.FileField(upload_to = ‘products/’)

      Entendeu?
      Qualquer coisa é só entrar em contato.
      Abraço. 😉

  • Cláudio
    Reply

    bom eu tenho meu models assim:
    class Livro(models.Model):
    nome = models.CharField(max_length=255)
    descricao = models.TextField()
    codigo = models.AutoField(primary_key=True)
    idioma = models.CharField(max_length=255)
    autor = models.CharField(max_length=255)
    numero_edicao = models.IntegerField()
    preco = models.FloatField()
    foto = models.ImageField(upload_to=”enter/imagens/%Y/%m/%D” ,null=True, blank=True)

    def __str__(self):
    return self.nome
    a view ta assim:
    def Index_livros(request):
    livro = Livro.objects.all()
    return render(request, ‘enter/index-livros.html’, {‘livro’:livro})
    e o html:
    {% block content %}

    {% for liv in livro %}

    {{liv.nome}}
    {{liv.descricao}}
    Abrir

    {% endfor %}

    {% endblock %}

    não consigo abrir a imagem…

    • toticavalcanti
      Reply

      Fala Claúdio, blz?
      Não sei se entendi direito, mas vamos lá.
      Colei seu código no sublime pra entender melhor porque aqui no comentário do post ele ficou meio confuso e sem identação.
      Quando colei no sublime vi que tinham aspas com formatação (, ou, ), ela fica meio curvadinha, como em arquivos do word, e as aspas em códigos tem que ser sem formatação, mas isso pode ser também da formatação aqui do blog mesmo, na parte dos comentários, não sei(???) enfim.
      Dá uma olhada aí no seu código pra ver se as aspas estão com formatação ou não.
      Aspas com formatação são meio curvadinhas.
      Verifiquei outras coisas no seu código.
      Em views.py falta os imports, a variável livro deve ser livros no plural, já que ela recebe uma lista de livros, da forma como você colocou, render(request, ‘enter/index-livros.html’, {‘livro’:livro}) é como se você tivesse pegando um livro, mas, na verdade o que chega em livros é uma lista com todos os livros.
      No models, models.ImageField(upload_to=”enter/imagens/%Y/%m/%D” ,null=True, blank=True) o %D deve ser minúsculo (%d), enfim, são muitos detalhes que você tem que vê aí, com as informações que você me deu não dá pra te ajudar muito, só se eu desenvolvesse o código, mas, não é esse o propósito e sim ensinar.
      Segue uma sugestão para os códigos:
      views.py

      
      from django.shortcuts import render
      from .models import Livro
      def index_livros(request):
          livros = Livro.objects.all()
          context = {
              'object': livros
          }
          return render(request, 'enter/index-livros.html', context)
      

      models.py

      
      from django.db import models
      
      class Livro(models.Model):
          nome = models.CharField(max_length=255)
          descricao = models.TextField()
          codigo = models.AutoField(primary_key=True)
          idioma = models.CharField(max_length=255)
          autor = models.CharField(max_length=255)
          numero_edicao = models.IntegerField()
          preco = models.FloatField()
          foto = models.ImageField(upload_to="enter/imagens/%Y/%m/%d" ,null=True, blank=True)
      
      def __str__(self):
          return self.nome
      

      E em index-livros.html troque o {{liv.nome}} e {{liv.nome}} por {{object.descricao}} e {{object.descricao}}, você tem que acrescentar também o {{ object.image.url }} dentro de uma tag img.

      Qualquer outra dúvida dá um toque. \o/ 😉

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>