capture image and save it to database with django - python

I am trying to make a web app with django in which it clicks an image from the camera and saves the image to a database. How can that be implemented? if there is a source code available, kindly share a link to it. thank you

I came here hoping to find an answer; there not being one, I hereby offer mine ...
The trick is to encode the image and save it as a TextField.
The solution I provide is bit clunky in the way the images are read every time select_image.html is loaded, but I did that because my requirement is a bit more complex and this does the job. I assume you know how to get the image from the camera (which is equivalent to my reading it from file).
There are two templates, select_image.html and display_image.html. When select_image.html is called for the first time it reads .png images from file and saves the images to the database. When an image is selected it is retrieved from the database and displayed in display_image.html.
select_image.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Select Image</title>
</head>
<body>
<h1>Select Image</h1>
{% block content %}
<ul>
{% for image in images %}
<li>{{ image }}</li>
{% endfor %}
</ul>
{% endblock %}
</body>
</html>
display_image.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Display Image</title>
</head>
<body>
<h1>Display Image</h1>
{% block content %}
<img id="image" src="{{ image }}" alt="image">
{% endblock %}
<p></p>
Images
</body>
</html>
models.py
class Image(models.Model):
name = models.CharField(max_length=25, null= False, blank=False, default='image_name', unique=True)
image = models.TextField()
urls.py
urlpatterns = [
path('images', views.Images.as_view(), name='images'),
path('display-image/<str:image_name>/', views.DisplayImage.as_view(), name='display-image'),
]
views.py
from PIL import Image as PilImage
import io
import base64
import os
from .models import Image
class Images(View):
url = "images/select_image.html"
def get(self, request):
dir = <image file directory>
image_names = ['red', 'green', 'blue']
for image_name in image_names:
base_path = os.sep.join([dir, image_name])
path = '.'.join([base_path, 'png'])
pil_image = PilImage.open(path)
encoded_image = self._encode_image(pil_image)
Image.objects.get_or_create(name=image_name, image=encoded_image)
context = {'images': image_names}
return render(request, self.url, context)
#staticmethod
def _encode_image(image):
"""Return image encoded to base64 from a PIL.Image.Image."""
io_buffer = io.BytesIO()
image.save(io_buffer, format='PNG')
saved_image = io_buffer.getvalue()
encoded_image = ''.join(['data:image/jpg;base64,', base64.b64encode(saved_image).decode()])
return encoded_image
class DisplayImage(View):
url = "images/display_image.html"
def get(self, request, image_name):
image = get_object_or_404(Image, name=image_name)
context = {'image': image.image}
return render(request, self.url, context)

Related

Loading images from an AWS bucket media folder to a HTML pdf template

I am trying to generate a PDF file out of a post created by a user, and include an image, which I want to store in an AWS bucket.
This is how it was working with my own file system
My function to generate a pdf in views.py:
def form_render_pdf_view(request, *args, **kwargs):
pk = kwargs.get('pk')
form = get_object_or_404(Post, pk=pk)
template_path = 'form/pdf2.html'
context = {
'form': form
}
# Create a Django response object, and specify content_type as pdf
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'filename="report.pdf"'
# find the template and render it.
template = get_template(template_path)
html = template.render(context)
# create a pdf
pisa_status = pisa.CreatePDF(
html, dest=response)
if pisa_status.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>')
return response
And rendering the image in the html template
<div>
<img src="{{form.image.path}}">
</div>
Now after uploading the files in a bucket it doesn't seem to work. The image is being stored there after uploading the post, but when creating the PDF the image is not displayed.(And it gives me an error: This backend doesn't support absolute paths). I tried to change the image source in the HTML template but it still didn't work.
Here is how I was able to implement it successfully. Hope it helps
url.py
path('foo/bar/<str:bar_id>/report/pdf/', getPdf,name="bar-report-pdf"),
process.py
from io import BytesIO
from django.conf import settings
from django.http import HttpResponse
from django.template.loader import get_template
from xhtml2pdf import pisa
def html_to_pdf(template_src, context_dict={}):
template = get_template(template_src)
html = template.render(context_dict)
result = BytesIO()
pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")),
result,
)
if not pdf.err:
return HttpResponse(result.getvalue(), content_type='application/pdf')
return None
do not use the link_callback attribute of the pisaDocument when using external url
view.py
from foo.process import html_to_pdf
def getPdf(request,bar_id):
image_set = Bar.objects.filter(id=bar_id).all()
context = {
'title':"Inspection Report",
"images": image_set,
}
open('templates/temp.html', "w").write(render_to_string('app/bar-report-pdf.html',context ))
pdf = html_to_pdf('temp.html')
return HttpResponse(pdf, content_type='application/pdf')
bar-report-pdf.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{% for image in images %}
<img class="d-block img-fluid" src="{{image.thumbnail_url_public}}" alt="{{forloop.counter}}">
{% endfor %}
</body>
</html>
here image.thumbnail_url_public is a text field containing public s3 image url. you can also use the presigned url if its a private s3 bucket.
hope it helps

Files in django template

i have a problem when i am trying to show files download link in django templates
message:
AttributeError: 'NoneType' object has no attribute 'split'
File "c:\users\ramin\appdata\local\programs\python\python36-32\Lib\wsgiref\simple_server.py", line 35, in close
self.status.split(' ',1)[0], self.bytes_sent
----------------------------------------
AttributeError: 'NoneType' object has no attribute 'split'
----------------------------------------
models.py:
from django.db import models
class Book(models.Model):
Title = models.CharField(max_length=100)
Writer = models.CharField(max_length=100)
Description = models.TextField()
Image = models.ImageField(default='default.jpg')
File = models.FileField(upload_to='PDF/')
def __str__(self):
return self.Title
views.py:
from django.views.generic.list import ListView
from . import models
class BookListView(ListView):
queryset = models.Book.objects.all()
template_name = 'Book/BookList.html'
template:
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Books List</title>
</head>
<body>
{% for x in object_list %}
<h2>{{ x.Title }}</h2>
<img style="width:100px" src="{{ x.Image.url }}">
<p><a href="{{ x.File.url }}" download="{{ x.Title }}">Download</p>
{% endfor %}
</body>
</html>
when i click on download link , i can download file successfully but i see this message
Maybe the problem that you use a .txt file as the default image
try the following code, assuming that object_name is an object of that model:
filename = os.path.basename(object_name.file.name)
response = HttpResponse(object_name.file, content_type='text/plain')
response['Content-Disposition'] = 'attachment; filename=%s' % filename
return response
See the following part of the Django documentation on sending files directly: https://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment

Django: Saving images uploaded through ImageField

I am trying to set up a webapp that accepts image uploads from a user, using ImageField, but I cant seem to figure out how to save the uploaded image. My media folder is empty even though there doesnt seem to be any errors.
Went through a lot of tutorials to no avail. I get the basic concept, create a form, model, set media in settings.py, handle upload in views, and I am getting a working view with a image upload form, but uploading an image does not save.
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
urls.py
urlpatterns = [
path('embed/', embed, name = 'embed'),
path('success', success, name = 'success'),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
forms.py
class imguploadform(forms.ModelForm):
class Meta:
model = imgupload
fields = ['title', 'image']
models.py
class imgupload(models.Model):
title = models.CharField(max_length = 20)
image = models.ImageField(upload_to="media/images/", default = None)
def __str__(self):
return self.title
views.py
def embed(request):
if request.method == 'POST':
form = imguploadform(request.POST, request.FILES)
if form.is_valid():
newimg = imgupload(title=request.POST['title'], image=request.FILES['image'])
newimg.save()
return redirect('success')
else:
form = imguploadform()
return render(request, 'webapp/imgupload.html', {'form' : form})
def success(request):
return HttpResponse("Successfully uploaded")
imgupload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Upload Image</title>
</head>
<body>
<form method = "post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload</button>
</form>
</body>
</html>
Another thing to note, the admin panel does not show the image model
The following code worked at my machine whoes os system is ubuntu18 with newest django and pillow
models.py
class Imgupload(models.Model):
title = models.CharField(max_length=20)
image = models.ImageField(upload_to="images/", default=None)
def __str__(self):
return self.title
views.py
def embed(request):
if request.method == "POST":
form = Imguploadform(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect("success")
else:
form = Imguploadform()
img = Imgupload.objects.last()
return render(request, "webapp/imgupload.html", {"form": form, "img": img})
def success(request):
return HttpResponse("Successfully uploaded")
imgupload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Upload Image</title>
</head>
<body>
<form method = "post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload</button>
</form>
{% if img %}
Image uploaded latest:
<img src="{{ img.image.url }}">
{% endif %}
</body>
</html>

'str' object has no attribute 'method'

I am trying to access a request.method in a python view, but I'm getting the error
'str' object has no attribute 'method'
The really odd thing is that I can see no difference between how I set up this page and how I set up another similar page; yet that one works fine and this one does not.
The code I am using is as follows:
main/views.py:
from .alphabetize import alphabetize
from .forms import WordListForm
def alphabetize(request):
if request.method == "POST":
form = WordListForm(request.POST)
if form.is_valid():
word_list = alphabetize(form.cleaned_data['word_list'])
return render(request, 'main/alphabetize.html', {'form': form, 'word_list': word_list})
else:
form = WordListForm()
return render(request, 'main/alphabetize.html', {'form': form})
/main/forms.py
class WordListForm(forms.Form):
word_list = forms.CharField(label="Word List")
main/urls.py
from django.conf.urls import url
from main import views
urlpatterns = [
url(r'alphabetize', views.alphabetize, name='alphabetize'),
]
main/alphabetize.py
def alphabetize(s):
word_list = []
for word in s.split(','):
word_list.append(word.strip())
word_list.sort()
return ', '.join(word_list)
templates/main/alphabetize.html
{% extends "base.html" %}
{% block content %}
<form action="/alphabetize" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
<p>Your list alphabetized: {{ alpha_list }}</p>
{% endblock content %}
/templates/base.html
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Awesome Django Page</title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
<div class="main">
{% block content %}{% endblock content %}
</div>
</body>
</html>
It seems that for some reason request is a string rather than an HttpRequest object, but I can't figure out why that would be.
You have two different functions called alphabetize; your view, and your utility function. As a result your view is calling itself, rather than the other function.
You should rename one of these.
Your view name overrides imported function alphabetize. Change view name to fix:
from .alphabetize import alphabetize
from .forms import WordListForm
def alphabetize_view(request):

attach img file in pdf weasyprint

I need help with attaching img file in pdfs. We use the WeasyPrint lib for generating pdf from html.
in html connect img file like this
<img src="1.png" alt="">
<img src="2.png" alt="">
<img src="3.png" alt="">
but it is not working. I don't see the image.
use static for path of the image file
{% load static %}
<img src="{% static 'images/static.jpg' %}" alt="">
and pass base_url in HTML class in views.py
pdf_file = HTML(string=rendered_html, base_url=request.build_absolute_uri())
html file
<!DOCTYPE html>
<html lang="en">
{% load static %}
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<img src="{% static 'images/static.jpg' %}" alt="">
</div>
</body>
</html>
views.py
from django.template.loader import get_template
from weasyprint import HTML, CSS
from django.conf import settings
from django.http import HttpResponse
def generate_pdf(request):
html_template = get_template('latest/html_pdf.html')
user = request.user
rendered_html = html_template.render().encode(encoding="UTF-8")
pdf_file = HTML(string=rendered_html, base_url=request.build_absolute_uri()).write_pdf(stylesheets=[CSS(settings.STATIC_ROOT + '/css/generate_html.css')])
http_response = HttpResponse(pdf_file, content_type='application/pdf')
http_response['Content-Disposition'] = 'filename="generate_html.pdf"'
return http_response
In case of sending emails with pdf attached, it's possible to pass path from view to function dedicated to emails.
views.py
[...]
path = request.build_absolute_uri() # build absolute path
order_confirmation.delay(order.id, path) # pass to func
[...]
tasks.py
#app.task
def order_confirmation(order_id, path): # receive path
order = Order.objects.get(id=order_id)
subject = f"Order nr. {order.id}"
email_from = settings.EMAIL
email_to = order.get_email
message = (...)
email = EmailMessage(subject, message, email_from, [email_to])
html = render_to_string('pdf.html', {'order' : order, 'company': company})
out = BytesIO()
stylesheets=[weasyprint.CSS(settings.STATIC_ROOT + '/css/pdf.css')]
weasyprint.HTML(string=html, base_url=path).write_pdf(out, stylesheets=stylesheets) # use here
email.attach(f'order_{order.id}.pdf',
out.getvalue(),
'application/pdf')
email.send()

Categories