Accessing image from Cloud Storage - python

I'm pretty new to python and Google Cloud. I'm developing a website that needs to retrieve image from Cloud Storage and serve it to HTML. I deploy my Flask on App Engine and the image is can't be served it.
My Flask code looks like this:
#app.route('/translate')
def translate():
return render_template("translate.html")
#app.route('/get-image', methods=['GET', 'POST'])
def get_image():
if request.method == 'POST':
name = request.form.get("huruf")
filepath = name + ".png"
buc = storage_client.get_bucket(CLOUD_STORAGE_BUCKET)
blob = buc.blob(filepath)
filename = blob.download_to_filename(filepath)
return render_template("get-translate.html", nama=name, pict=filename)
else:
return redirect(url_for(translate))
Here is my HTML that input request:
{% extends "base.html" %}
{% block title %} Get Image - Isyaratku {% endblock %}
{% block content %}
<br>
<form action="/get-image" method="post">
<label for="huruf">Huruf :</label>
<input type="text" name="huruf">
<br>
<input type="submit" value="SUBMIT">
</form>
{% endblock %}
And here is my HTML for a received image from Cloud Storage:
{% extends "base.html" %}
{% block title %} Get Translate - Isyaratku {% endblock %}
{% block content %}
<h1>{{ nama }}</h1>
<img src="{{ pict }}" alt="gmb">
{% endblock %}

Related

URL with multiple parameters throws a NoReverseMatch error

I aim to redirect the view after the form has been saved. However django keeps throwing a NoReverseMatch error. Is there a step that I've missed or a misconfiguration?
views.py
def add_carpet(request):
context_dict = {}
carpet_form = forms.CarpetForm()
if request.method == "POST":
carpet_form = forms.CarpetForm(request.POST)
if carpet_form.is_valid():
carpet = carpet_form.save()
return redirect(reverse(
"dashboard_add_images",
kwargs={
"model_type": "carpet",
"id": carpet.id
}
))
context_dict["carpet_form"] = carpet_form
return render(
request,
'dashboard/add_carpet.html',
context_dict
)
def add_images(request, model_type, id):
...
add_images.hml
{% extends 'layouts/dashboard_base.html' %}
{% load django_bootstrap5 %}
{% load static %}
{% block title %}Add Images{% endblock title %}
{% block content %}
<div class="row">
<div class="col justify-content-end">
<h1 class="heading half_space text-muted">
Add Images for the {model}
<span class="divider-left"></span>
</h1>
</div>
</div>
{# Load CSS and JavaScript #}
{% bootstrap_css %}
{% bootstrap_javascript %}
{# Display django.contrib.messages as Bootstrap alerts #}
{% bootstrap_messages %}
{# Display a form #}
<form enctype="multipart/form-data" action="{% url 'dashboard_add_images' %}" method="post" class="form">
{% csrf_token %}
{% bootstrap_form form %}
{% bootstrap_button button_type="submit" content="OK" %}
</form>
{% endblock content %}
From above you can see I added the enctype on the form but still no change.
urls.py
urlpatterns = [
path('add_carpet', views.add_carpet, name="dashboard_add_carpet"),
path('add_images/<str:model_type>/<uuid:id>', views.add_images, name="dashboard_add_images"),]
An example redirect url after a form has been submitted is this:
http://127.0.0.1:8000/dashboard/add_images/carpet/97afd259-6ec4-48fc-869f-2a00bbe29c70
Error:
Reverse for 'dashboard_add_images' with no arguments not found. 1 pattern(s) tried: ['dashboard/add_images/(?P<model_type>[^/]+)/(?P<id>[^/]+)$']

How to change browse button to look like modern drag&drop?

I have created a django site, django site is working in this way. You go to the site, upload document with data and you get some results. You upload excel file, and you download excel file. In background I used pandas for calculations. In the end you can see code.
I have left one thing to finish. I want to create drag&drop for upload document. Chech picture 1, as I understand this is already drag&drop, just doesn't look as I would like to. I want to look like in picture 2.
Picture 1: Current
Picture 2: I would like to look like this.
Can I change the look that you seen on first image without using js?
This is html that I have and output is shown in picture 1...
{% extends "base.html" %}
{% load static %}
{% block content %}
<form action="{% url "cal" %}" method="post" enctype="multipart/form-data" class="dropzone">
{% csrf_token %}
{{ message }}
<p>{{ form.non_field_errors }}</p>
<p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
<p>
{{ form.docfile.errors }}
{{ form.docfile }}
</p>
<p><input type="submit" value="Upload and Download!"/></p>
</form>
{% endblock content %}
This is function in views
def OnlyCAL(request):
if request.method == "POST":
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
output = io.BytesIO()
newdoc = request.FILES['docfile']
#pandas calculations
response = HttpResponse(
output, content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = 'attachment; filename=%s' % filename
return response
else:
form = DocumentForm()
return render(request, 'cal.html', { 'form': form, 'page_title':page_title })
I think the best option for you is to use dropzone.js. You can find documentation here.
You should include .js and .css. Also you can customize dropzone view on your own as described here (example of customizing dropzone in combination with Django, maybe will be useful for you)
You can try this (.js and .css files included directly in your template just for example, you can include easily include it in other way):
{% extends "base.html" %}
{% load static %}
<script src="https://unpkg.com/dropzone#5/dist/min/dropzone.min.js"</script>
<link rel="stylesheet" href="https://unpkg.com/dropzone#5/dist/min/dropzone.min.css" type="text/css" />
{% block content %}
<form id="dropZoneForm" action="{% url "cal" %}" method="post" enctype="multipart/form-data" class="dropzone needsclick dz-clickable">
{% csrf_token %}
<input type="hidden" name="abc" value="i am hidden value">
<div class="fallback">
<input name="file" type="file"/>
</div>
<input type="submit" id="submit-all" value="Upload and Download" class="custom-button" style="float: right">
</form>
{% endblock content %}

Python/Flask - Display image from file input

Plain and simple, I'm aiming to have a user input their name, and select an image from the file input. With some help with my previous question, I was able to get the name to carry over to the next page, but I'm unable to get a selected image to display.
Right now, when filled out, the name and image file name are provided. Hoping to get the image file to actually display the image.
Home page...
Display page...
Here is my current code:
Home.html
{% extends 'base.html' %}
{% block head %}
<title>Home Page</title>
{% endblock %}
{% block body %}
<div class="content-container">
<form action="{{ url_for('result') }}" method="post">
<h2>Input your name:</h2>
<input type="text" class="user-input user mb-3" name="user">
<h2>Select your image:</h2>
<input type="file" accept="image/*" class="form-control-file"
id="formControlFile1" name="image">
<input class="btn btn-outline-primary" type="submit" value="Submit">
</form>
</div>
{% endblock %}
Result.html
{% extends 'base.html' %}
{% block head %}
<title>Result Page</title>
{% endblock %}
{% block body %}
<div class="content-container">
<h2>{{ name }}</h2>
<h2>{{ image }}</h2>
</div>
{% endblock %}
Main.py
from flask import Flask, render_template, request, url_for, redirect
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST':
user = request.form["user"]
image = request.form["image"]
return redirect(url_for('result', name=user, image=image))
return render_template('home.html')
#app.route("/result", methods=['GET', 'POST'])
def result():
name = request.form.get('user')
image = request.form.get('image')
return render_template("result.html", name=name, image=image)
if __name__ == "__main__":
app.run()
So, yeah, hopefully I explained that easy enough. User inputs name, selects image, and the goal is for the name to show and image to display on the result page. Thanks to anyone that can provide this lowly soul with guidance.
You can try something like that
Your form's enctype should be multipart/form-data
{% extends 'base.html' %}
{% block head %}
<title>Home Page</title>
{% endblock %}
{% block body %}
<div class="content-container">
<form action="{{ url_for('result') }}" method="post" enctype="multipart/form-data">
<h2>Input your name:</h2>
<input type="text" class="user-input user mb-3" name="user">
<h2>Select your image:</h2>
<input type="file" accept="image/*" class="form-control-file"
id="formControlFile1" name="image">
<input class="btn btn-outline-primary" type="submit" value="Submit">
</form>
</div>
{% endblock %}
You need to use request.files and decode in base64
import base64
from flask import Flask, render_template, request, url_for, redirect
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST':
user = request.form["user"]
image = request.files['image'] # get file
image_b64 = base64.b64encode(image.read()).decode('utf-8')
return redirect(url_for('result', name=user, image_b64=image_b64))
return render_template('home.html')
#app.route("/result", methods=['GET', 'POST'])
def result():
name = request.form.get('user')
image_b64 = request.form.get('image_b64')
return render_template("result.html", name=name, image_b64=image_b64)
if __name__ == "__main__":
app.run()
You should change your HTML to convert image from base64
{% extends 'base.html' %}
{% block head %}
<title>Result Page</title>
{% endblock %}
{% block body %}
<div class="content-container">
<h2>{{ name }}</h2>
<img src="data:image/png;base64, {{ image_b64 }}">
</div>
{% endblock %}

What is the method to recognize new files in a directory using Flask?

So I have a form that uploads a file to a /assets/models and I have another form on a separate page that has a selection field where I want to select one of the files from /assets/models. However, unless I restart the Flask server it doesn't show a new file in the dropdown list.
forms.py
class PredictForm(FlaskForm):
datasheet = FileField('CSV Dataset', validators=[DataRequired()])
myModels = os.listdir('C:/Users/Matt/Documents/graymatter-flask/assets/models/')
myChoices = []
for model in myModels:
myChoices.append((model,model))
model_name = SelectField('Select the Model', choices = myChoices, validators=[DataRequired()])
submit = SubmitField('Predict')
routes.py
#app.route('/predictdata', methods=['GET', 'POST'])
def predictdata():
form = PredictForm()
if form.validate_on_submit():
assets_dir = os.path.join(os.path.dirname(app.instance_path), 'assets')
input_data = form.datasheet.data
input_filename = secure_filename(input_data.filename)
model_name = form.model_name.data
input_data.save(os.path.join(assets_dir, 'tempdata', input_filename))
results_array = easy_ai_prediction.prediction(input_filename, model_name)
session['results'] = results_array.tolist()
os.remove('C:/Users/Matt/Documents/graymatter-flask/assets/tempdata/'+input_filename)
return redirect(url_for('results'))
return render_template('predictdata.html', title='Predict Data', form=form)
predictdata.html
{% extends "base.html" %}
{% block content %}
<h1>Predict</h1>
<form action="" enctype="multipart/form-data" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.datasheet.label }}<br>
{{ form.datasheet(size=32) }}<br>
{% for error in form.datasheet.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.model_name.label }}<br>
{{ form.model_name(size=1) }}<br>
{% for error in form.model_name.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>{{ form.submit }}</p>
</form>
{% endblock %}
I apologize if this is a really basic question, I've just started learning web development just for this project so I'm struggling a bit.

django - csrf protection - markdown2

In some of my blog posts using django and markdown2, I am trying to include a form as follows:
views.py:
def post_detail(request, slug=None):
instance = get_object_or_404(Post, slug=slug)
if not instance.published:
raise Http404
return render(request, "posts/post_detail.html", {'instance': instance})
My template post_detail.html contains a {{ instance.get_markdown }} variable:
{% extends "base.html" %}
{% block body_content %}
<div>
{{ instance.get_markdown }}
</div>
{% endblock body_content %}
base.html:
<html>
<body>
{% block body_content %}
{% endblock body_content %}
</body>
</html>
models.py:
import markdown2
class Post(models.Model):
...
text = models.TextField(verbose_name=_("Text"))
...
def get_markdown(self):
return mark_safe(markdown2.markdown(self.text))
Example for a saved text in Post:
### Example
<form method = "POST">
{% csrf_token %}
First name:<input type="text" name="firstname">
<input type="submit" value="Submit">
</form>
This way, the page simply shows the string "{% csrf_token %}" within the form. How can I render the post with csrf protection?
My temporary solution is:
post_detail.html:
{% extends "base.html" %}
{% block body_content %}
<div>
{{ instance.get_markdown_text }}
</div>
{% if instance.form %}
<div>
<form method = "POST">{% csrf_token %}
{{ instance.get_markdown_form }}
</form>
</div>
{% endif %}
{% endblock body_content %}
models.py:
import markdown2
class Post(models.Model):
...
text = models.TextField(verbose_name=_("Text"))
form = models.TextField(verbose_name=_("Form"), blank=True, null=True)
...
def get_markdown_text(self):
return mark_safe(markdown2.markdown(self.text))
def get_markdown_form(self):
return mark_safe(markdown2.markdown(self.form))
I'm not very happy with this solution, because of the unnecessary field "form" and method get_markdown_form in Post and post_detail.html.

Categories

Resources