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.
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
se eu quiser salva em pastas separadas?
tipo:
produtos/brinquedos/img1….
produtos/brinquedos/img2….
produtos/eletronicos/img1….
produtos/eletronicos/img2….
Fala Jerônimo, blz?
O models.py tá assim:
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. 😉
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…
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
models.py
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/ 😉