How to display multiple images stored in a folder in Django - python

I am developing a django app which converts pdf to images.I am using FileField for this purpose and using ModelForms. Once uploaded the pdf files will get converted into .png and stored in a separate folder. The upload and converting pdf to png works fine but now I want to display the converted images.
I know I can use url of the uploaded image to display it but the issue is I am uploading a pdf file and hence cannot use the url to display it. I know how to display an uploaded image using url of that image. But I am uploading a pdf file, converting into image and finally storing it into separate folder. So how can I display the images stored? Below is the code I am using:
forms.py
from django import forms
from django.forms import ClearableFileInput
from app1.models import UserUploadModel
class UserUploadForm(forms.ModelForm):
class Meta:
model = UserUploadModel
fields = ['file']
widgets = {
'file' : ClearableFileInput(attrs = {'multiple': True}),
}
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserUploadModel(models.Model):
user = models.ForeignKey(User, on_delete = models.CASCADE, null = True)
file = models.FileField(upload_to = 'file_uploads')
views.py
from django.shortcuts import render, redirect
from app1.forms import UserUploadForm
from app1.models import UserUploadModel
from app1.convert import convert_file
from app1.transfer import move_dir
import os
from project1 import settings
from django.contrib.auth.decorators import login_required
#login_required
def home(request):
if request.method == 'POST':
form = UserUploadForm(request.POST, request.FILES)
if form.is_valid():
files = request.FILES.getlist('file')
f_list = []
if files:
for i in files:
file_instance = UserUploadModel(file = i, user = request.user)
file_instance.save()
f_list.append(file_instance.file.path)
[convert_file(j) for j in f_list]
src_dir = os.getcwd()
dest_dir = os.path.join(src_dir, 'media/converted_files')
move_dir(src_dir, dest_dir, '*.png')
return redirect('app1-display')
else:
form = UserUploadForm()
return render(request, 'app1/home.html', {'form' : form})
#login_required
def display(request):
images = UserUploadModel.objects.filter(user = request.user)
context = {
'images' : images
}
return render(request, 'app1/display.html', context)
home.html
{%extends "app1/base.html"%}
{%block content%}
<form method="POST" enctype="multipart/form-data">
{%csrf_token%}
{{form.as_p}}
<input type="submit">
</form>
{%endblock content%}
display.html
{%extends "app1/base.html"%}
{%load static%}
{%block content%}
{%if user.is_authenticated%}
<h2>User: {{request.user.username}}</h2>
{%endif%}
{%if images%}
{%for i in images%}
<img src={{ i.file.url }}>
{%endfor%}
{%endif%}
{%endblock content%}

Wrong approach change your model and make a file field for the converted pdf also. After converting save the file to this model field. Then you can get the url of the converted file.

I'm not sure but can you use PIL to open the image and then use Django File Response to return the image.
from PIL import Image
from django.http import FileResponse
def display(request):
images = UserUploadModel.objects.filter(user = request.user)
if images:
image = Image.open(images[0].file.path)
return FileResponse(image, content_type='image/png')

Related

How and where should I store the conversion code for image files in Django?

I created a simple form in Django of which it contains only a single form input field i.e image field. My aim is to allow a user to upload an image file i.e JPEG, JPG, SVG, PNG. Once uploaded, I want to write some code that'll convert the image file to PNG and then store it in my database. How should I write this code and where do I write it? You can view my current code below. I'm a beginner in Django and could use some help.
settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
website/urls.py:
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('myapp.urls')),
]
urlpatterns = urlpatterns + static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT)
urlpatterns = urlpatterns + static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
models.py
from django.db import models
class Image(models.Model):
"""Image upload model"""
image = models.ImageField(upload_to = 'media', default = 'media/sample.png')
created_date = models.DateTimeField(auto_now = True)
def __str__(self):
return str(self.id)
forms.py
from django import forms
from myapp.models import Image
class ImageForm(forms.ModelForm):
"""Image upload form"""
class Meta:
model = Image
exclude = ('created_date',)
views.py
from django.shortcuts import render
from django.db import models
from django.views.generic import TemplateView, CreateView
from myapp.forms import ImageForm
from django.urls import reverse_lazy
from PIL import Image
class BaseView(TemplateView):
template_name = "base.html"
class ImageView(CreateView):
template_name = "insert_image.html"
form_class = ImageForm
success_url = reverse_lazy("base")
insert_image.html
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<title> Insert an image </title>
</head>
<body>
<h1> Please upload an image below </h1>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<button type="submit"> Submit </button>
</form>
</body>
</html>
base.html
<!DOCTYPE html>
<html>
<head>
<title> Thanks! </title>
</head>
<body>
<h1> Thanks for uploading! </h1>
<button> <a href = '{% url "insert_image" %}' style="text-decoration:
none;"> Return </button> </a>
</body>
</html>
The answer is "pyrsvg" - a Python binding for librsvg.
There is an Ubuntu python-rsvg package providing it. Searching Google for its name is poor because its source code seems to be contained inside the "gnome-python-desktop" Gnome project GIT repository.
I made a minimalist "hello world" that renders SVG to a cairo surface and writes it to disk:
from django.db import models
import os
from PIL import Image
class Image(models.Model):
"""Image upload model"""
image = models.ImageField(upload_to = get_directory_path, default = 'media/sample.png')
created_date = models.DateTimeField(auto_now = True)
def __str__(self):
return str(self.id)
def get_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
file_extension = os.path.splitext(filename)
if file_extension[1] in ['.jpg','.png','.jpeg','.svg']:
if file_extension[1] != '.svg':
filename=file_extension[0]+'.png'
dir = 'Images'
else:
import cairo
import rsvg
img = cairo.ImageSurface(cairo.FORMAT_ARGB32, 640,480)
ctx = cairo.Context(img)
## handle = rsvg.Handle(<svg filename>)
# or, for in memory SVG data:
handle= rsvg.Handle(None, str(<svg data>))
handle.render_cairo(ctx)
filename=img.write_to_png("svg.png")
dir = 'Images'
else:
dir="others"
path = '{0}/{1}'.format(dir, filename)
return path
Update: as of 2014 the needed package for Fedora Linux distribution is: gnome-python2-rsvg. The above snippet listing still works as-is.
In your ImageView class you can override form_valid
class ImageView(CreateView):
[...]
def form_valid(self, form):
uploaded_image = form.instance
[do your convert code here]
return super(ImageView, self).form_valid(form)
you could also use post_save signal.
This is the exact way you can do please reply back if you face any problen and do vote my answer :--
from django.db import models
import os
from PIL import Image
class Image(models.Model):
"""Image upload model"""
image = models.ImageField(upload_to = get_directory_path, default = 'media/sample.png')
created_date = models.DateTimeField(auto_now = True)
def __str__(self):
return str(self.id)
def get_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
file_extension = os.path.splitext(filename)
if file_extension[1] in ['.jpg','.png','.jpeg']:
filename=file_extension[0]+'.png'
dir = 'Images'
else:
dir="others"
path = '{0}/{1}'.format(dir, filename)
return path

How to stop django to store images path in sqlite3 database

Following code work fine to store thumbnails images in /media/ directory. i want to store all images in following directory but django also save images path in database. Please let me know, how i can stop django to save their path and address in database ?
model.py : Code
from django.db import models
class Document(models.Model):
thumbnail = models.ImageField()
views.py : Code
from .models import Document
from .forms import DocumentForm
if (request.FILES['thumbnail']):
newdoc = Document(thumbnail = request.FILES['thumbnail'])
newdoc.save()
forms.py : Code
from django import forms
class DocumentForm(forms.Form):
thumbnail = forms.ImageField(
label='Select a file',
help_text='max. 42 megabytes'
)
template.html : Code
<form action="" method="post" id="imgUpload" enctype="multipart/form-data">
<p>{{ form.non_field_errors }}</p>
<p>{{ form.thumbnail.label_tag }} {{ form.thumbnail.help_text }}</p>
<p>
{{ form.thumbnail.errors }}
{{ form.thumbnail }}
<button type="submit" id="thumbUpload" class="btn btn-success"><i class="glyphicon glyphicon-picture"></i> Upload Thumbnails</button>
</form>
you have to override your form method , before save your validform , or you can handle with your code , you don't need to have model or form you can handle with
image = request.FILES['myfile']
now you have your image you can save it directly without model
example reproduced from Django Documentation.
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES['file'])
return HttpResponseRedirect('/success/url/')
else:
form = UploadFileForm()
return render_to_response('upload.html', {'form': form})
def handle_uploaded_file(f):
destination = open('file path', 'wb+')
for chunk in f.chunks():
destination.write(chunk)
destination.close()
you can change 'file path ' with your path where you want to store your image
I'm not clear about what you are trying to achieve but the solution is barely simple. Just get the file object and save...
oh.. one more thing just remove all the thumbnail in models.py and other files...
def handle_uploaded_file(f):
destination = open('your_media_path/media/file.png', 'wb+')
for chunk in f.chunks():
destination.write(chunk)
destination.close()
in your POST view
f = request.FILES['thumbnail']
handle_uploaded_file(f)

Why is my django file submission not posting?

I am busy building a conference website application where is is necessary to be able to upload articles. These articles should also be able to assigned to reviewers to get downloaded and scored. My problem comes with the uploading of the files. I am not sure what I am doing wrong, but I think my form is submitting the incorrect data since it doesn't run through the 'if form.is_valid:' part. I am still a beginner at this. I have watched multiple tutorials.
This is what my model.py file looks like:
from django.db import models
from time import time
def get_upload_file_name(instance, filename):
return "uploaded_files/%s_%s" % (str(time()).replace('.','_'), filename)
class Article(models.Model):
title = models.CharField(max_length=50)
abstract = models.TextField()
pub_date = models.DateTimeField('Date published')
ffile = models.FileField(upload_to=get_upload_file_name)
def __str__(self):
return "%s" % (self.title)
This is my admin.py file:
from django.contrib import admin
from .models import Article
admin.site.register(Article)
This is my forms.py file:
from django import forms
from .models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ('title','abstract','pub_date','ffile')
This is my views.py file:
from django.shortcuts import render, render_to_response
from django.http import HttpResponseRedirect
from .forms import ArticleForm
def upload_article(request):
if request.method == 'POST':
form = ArticleForm(request.POST, request.FILES)
if form.is_valid():
instance = ArticleForm(file_field=request.FILES[''])
form.save()
instance.save()
return HttpResponseRedirect('/articles/')
else:
form = ArticleForm()
return render_to_response('submit/form.html', {'form' : form})
And then my HTML template:
{% extends 'base.html' %}
{% block content %}
<form method="post" action="../upload/" enctype="multipart/form-data"> {% csrf_token %}
{{form.as_p}}
<input type="submit" value="Submit" />
</form>
{% endblock %}
There is no problems with my urls.. Can someone please help me. Or at least suggest a third party app that might make this easier?
I can post normal forms that is not uploading files, but I just can't seem to get this one.
Ok, so I found the solution to the posting problem.
models.py
from django.db import models
from django.forms import ModelForm
from time import time
# Function to determine where to place uploaded documents
# Taken from youtube tutorial: https://www.youtube.com/watch?v=b43JIn-OGZU&index=15&list=PLxxA5z-8B2xk4szCgFmgonNcCboyNneMD
def get_upload_file_name(instance, filename):
# return a string: folder_name/time-of-upload + seperated by underscore + filename
# Example: media_files/15-10-2015_Submission1
return "uploaded_files/%s_%s" % (str(time()).replace('.','_'), filename)
class Document(models.Model):
file = models.FileField( blank=False, null=True)
title = models.CharField(max_length=200, default=None)
def __str__(self):
return "%s" % self.title
class DocumentForm(ModelForm):
class Meta:
model = Document
fields = ['title', 'file']
forms.py
from django import forms
from .models import Document
class UploadFileForm(forms.ModelForm):
title = forms.CharField(max_length=200)
file = forms.FileField(
label = 'Select a file',
help_text = 'maximum file size: 50mb',
allow_empty_file=False
)
views.py
##login_required
def upload_file(request):
# Handle file upload
if request.POST:
form = DocumentForm(request.POST, request.FILES)
#print(request.POST['title'], ' ', request.POST['file'])
# print(request.FILES['file'])
if form.is_valid():
#newdoc = Document(title = request.FILES['title'])
form.save()
# Redirect to the document list after POST
# return HttpResponseRedirect(reverse('submissions.views.upload_file'))
return HttpResponseRedirect('/success/')
else:
form = DocumentForm() #A empty, unbound form
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('submissions/submission.html', args, context_instance=RequestContext(request))
So one of the problems was that I had to create a FileField in the model as weel as in the form.

DJango - My forms.py elements are not showing up in the html template

I am a newbie for Django and working on a project. I am stucked with setting up a forms.py and integrate the same with my template. I did all the required things with the help of all sort of tutorial I got online but I was unable to see the fields I declared in form on the HTML Page. Below is the code I used for each of the module. It would be great if anyone can help me out with this.
models.py
from django.db import models
class EarlyBirds(models.Model):
name = models.CharField(max_length=200)
email = models.CharField(max_length=200)
contact_number = models.IntegerField()
def __str__(self):
return '%s - %s' % (self.name, self.email)
views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.template import RequestContext, loader
from django.shortcuts import render_to_response
from .forms import EarlyBirdsForm
from .models import EarlyBirds
def register(request):
context = RequestContext(request)
success=''
if request.method == 'POST':
form = EarlyBirdsForm(request.POST)
if form.is_valid():
name = request.POST.get('name','')
email = request.POST.get('email','')
number = request.POST.get('number','')
if email:
email_exist = EarlyBirds.objects.filter(email=email)
if email_exist:
success = 'Thankyou for your intrest! This email is already registered with us. We will get back to you soon.'
else:
eb_obj = EarlyBirds(name=name,email=email,contact_number=number)
eb_obj.save()
success = 'Thankyou for your intrest! We will get back to you soon.'
else:
success = 'Please fill out the required fields'
else:
success = form.errors
else:
form = EarlyBirdsForm()
return render_to_response('ComingSoon.html', {'success':success}, context)
forms.py
from django import forms
from django.forms import ModelForm
from app_name.models import EarlyBirds
class EarlyBirdsForm(forms.Form):
name = forms.CharField(required=True,max_length=100)
email = forms.CharField(required=True,max_length=100)
number = forms.IntegerField(required=True)
class Meta:
model = EarlyBirds
fields = ("name", "email", "number")
template
<html xmlns="http://www.w3.org/1999/xhtml">
<body align="center">
<form method="POST" action="{%url 'comingsoon:register'%}">
{% csrf_token %}
<div class="header-blog-comingSoon" align="center">
<!--<form method="post">
<span>{{ form.as_p }}</span>
<br/>
<span><button class="comingsoon-Reg" type="submit">Register</button></span>
<br/><br/>
<br/><label class="successLabel">{{success}}</label>
</div>
</form>
</body>
</html>
project.urls.py
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^ComingSoon/', include('app_name.urls', namespace="comingsoon")),
url(r'^admin/', include(admin.site.urls)),
]
When I try to execute this code, the all I was able to see in the "Register" button on my html page. The three text fields for Name, Email and Contact number were missing. Please let me know what I am missing over here.
You forgot to add the form to your context:
def register(request):
...
return render_to_response('ComingSoon.html', {'success':success, 'form': form}, context)
Maybe you should try writing your form like this:
class EarlyBirdsForm(forms.ModelForm):
class Meta:
model = EarlyBirds
fields = '__all__'
Much easier and simpler. Since you're using all the attributes in the model, might as well connect the form directly with the model.
And César Bustíos said it right. You didn't add the form in the context dictionary for your template.

how to upload csv file in sqlite database django

I'm trying to upload csv through django but it's not working..
Code
Views.py
from django.shortcuts import render_to_response
from forms import UploadForm
from django.http import HttpResponseRedirect
def create(request):
if request.method == 'POST':
form = UploadForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect('/success/url/')
else:
form = UploadForm()
return render_to_response('upload.html', {'form': form})
Url.py
urlpatterns = patterns('',
(r'^$', create),
#url(r'^articles/create/$', create, name='done'),
url(r'^articles/create/$', 'article.views.create'),
)
models.py
from django.db import models
from time import time
def get_upload_file_name(instance, filename):
return "uploaded_files/%s_%s" % (str(time()).replace('.','_'), filename)
class Article(models.Model):
file = models.FileField(upload_to=get_upload_file_name)
Forms.py
from django import forms
from models import Article
class UploadForm(forms.ModelForm):
class Meta:
model = Article
html file
{% csrf_token %}
{{form.as_p}}
Your template needs to be:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" />
</form>
See the binding uploaded files to a form section in the documentation.

Categories