1
resposta

upload e dowload de arquivos

oi bom dia. em vez de imagens estou tentando subir documentos em pdf e jpeg. quero que os usuarios facam o upload e dowload. fiz assim:

#setings

STATIC_URL = 'static/'

STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'setup/static') ]

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

#uploads

MEDIA_URL = 'uploads/' MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')

#url do setings from django.contrib import admin

from django.urls import path, include from django.conf import settings from django.conf.urls.static import static

urlpatterns = [ path('admin/', admin.site.urls), path('', include('inicial.urls')), path('', include('pop1.urls')),

] + static (settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

models

class Documento(models.Model): titulo = models.CharField(max_length=255, null=False, blank=False) arquivo = models.FileField(upload_to='uploads/')

#forms

class DocumentoForm(forms.ModelForm): class Meta: model = Documento fields = ['titulo', 'arquivo'] labels = { 'titulo': 'Nome do arquivo', 'arquivo': 'Arquivo', } widgets = { 'titulo': forms.TextInput(attrs={'class': 'form-control'}), 'arquivo': forms.FileInput(attrs={'class': 'form-control'}), }

#views NESSE VIEWS A PRIMEIRA PARTE DE PARA FAZER UPLOAD E A SEGUNDA E PARA VISUALIZAR E BAIXAR def pop1(request): documento = Documento.objects.order_by('id') form =DocumentoForm() if request.method == 'POST': form = DocumentoForm(request.POST, request.FILES) if form.is_valid(): titulo = form.cleaned_data['titulo'] arquivo = form.cleaned_data['arquivo'] cadastro = Documento.objects.create( titulo=titulo, arquivo=arquivo, ) cadastro.save() messages.error(request, 'Arquivo adicionado com sucesso') return redirect('pop1') return render(request, 'pop1/pop1.html', {'form': form, 'Documentos': documento})

#template

<section >
<p class="text-center" >Faca seu ulpload aqui</p>
<br>
    <form action="{% url 'pop1' %}" method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        <div>
            {% for field in form.visible_fields %}
            <div class="mb-3">
                <label for="{{ field.id_for_label }}" class="form-label" style="font-weight: bold;">{{ field.label }}</label>
                {{ field }}
            </div>
            {% endfor %}
        </div>
        <div>
            <button type="submit" class="btn btn-success">Enviar</button>
        </div>
    </form>

Histórico de uploads

IDDocumentoDocumentoBotões
{% if Documentos %} {% for Documento in Documentos%}
{{ Documento.id }}{{ Documento.tilulo }}{{ Documento.arquivo }} {% csrf_token %}
{% endfor %} {% else %} {% endif %}

O problema e que ele salva certinho mas se eu quiser excluir ele não exclui o arquivo (apaga do banco de dados mas nao da pasta uploads) e eu não consigo fazer dowload. o nome do arquivo tambem fica upload/nomedoarquivo. me ajude por favor segue um print Insira aqui a descrição dessa imagem para ajudar na acessibilidade

att

1 resposta

Olá Patricia, bom dia!

Vamos resolver essas questões uma de cada vez. Primeiro, para excluir o arquivo do sistema de arquivos quando ele é removido do banco de dados, você pode sobrescrever o método delete do modelo Documento. Aqui está um exemplo de como você poderia fazer isso:

from django.db import models
from django.conf import settings
import os

class Documento(models.Model):
    # ... seus outros campos ...

    def delete(self, *args, **kwargs):
        if self.arquivo:
            if os.path.isfile(self.arquivo.path):
                os.remove(self.arquivo.path)
        super(Documento, self).delete(*args, **kwargs)

Isso garantirá que, quando um objeto Documento for deletado, o arquivo associado também será removido do sistema de arquivos.

Agora, para permitir o download dos arquivos, você precisa de uma forma de servir esses arquivos através de uma view. Você pode criar uma view para servir os arquivos e um link no template para o download. Aqui está um exemplo de como você poderia fazer isso:

from django.http import FileResponse
from django.shortcuts import get_object_or_404

def download_documento(request, pk):
    documento = get_object_or_404(Documento, pk=pk)
    response = FileResponse(documento.arquivo)
    return response

E no seu template, você pode adicionar um link para essa view:

<a href="{% url 'download_documento' Documento.id %}">Baixar</a>

Não se esqueça de adicionar a URL correspondente no seu arquivo urls.py:

from django.urls import path
from .views import download_documento

urlpatterns = [
    # ... suas outras urls ...
    path('download/<int:pk>/', download_documento, name='download_documento'),
]

Por fim, sobre o nome do arquivo que está aparecendo como "upload/nomedoarquivo", isso é o caminho relativo do arquivo no sistema de arquivos. Para exibir apenas o nome do arquivo no template, você pode usar o atributo name do campo de arquivo no seu modelo, que contém apenas o nome do arquivo. Por exemplo:

<td>{{ Documento.arquivo.name }}</td>

Isso deve exibir apenas o nome do arquivo, sem o caminho "uploads/".

Espero que esse exemplo possa lhe ajudar e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.