How to tell jinja about files in static sub-directories? - flask

I have created a web app in which user uploads a image on my web app and that image is saved in myproject/static/uploads directory but I am unable to display that image.
my file upload code:
file = request.files['file']
filename = secure_filename(file.filename)
if filename != '':
file_ext = os.path.splitext(filename)[1]
if file_ext not in current_app.config['UPLOAD_EXTENSIONS']:
return 'Invalid Image', 400
file.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))
post = Post(title=title,body=body,author_id=current_user.id,author=current_user,filename=filename)
db.session.add(post)
db.session.commit()
return redirect(url_for('blog.index'))
return render_template('blog/create.html')
my index view:
#bp.route('/')
def index():
posts = Post.query.all()
files = os.listdir(current_app.config['UPLOAD_FOLDER'])
return render_template('blog/index.html', posts=posts, files=files)
index.html
{% block content %}
{% for post in posts %}
<article class="post">
<header>
<div>
<h1>{{ post.title }}</h1>
<div class="about">by {{ post.author.username }} on {{ post.created.strftime('%Y-%m-%d') }}</div>
</div>
</header>
<p class="body">{{ post.body }}</p>
</article>
{% for file in files %}
<img src="{{ url_for('static', filename='uploads/post.filename') }}" style="width: fit-content;">
{% endfor %}
{% if not loop.last %}
<hr>
{% endif %}
{% endfor %}
{% endblock %}

You have to use string concatenation to create the dynamic filename:
<img src="{{ url_for('static', filename='uploads/' ~ post.filename) }}" style="width: fit-content;">
The preferred operator is the tilde (~), but you can also use the plus operator if you wish.

You can simply do this in your main file:
app = Flask(__name__,
static_url_path='',
static_folder='templates/static',
template_folder='templates')
And then call your files: (path for 'example.js' is 'app/templates/static/js')
<img width="130" src="/js/example.js">

Related

can't upload image from database in django server

in my project i am trying to save image in database and next i want to get that image from database
in my dashborad everything working well, imgs where saved in db but when i am trying to get url from db and asign it to img src="" chrome says that 404 (Not Found)
this is my model
class Id(models.Model):
first_name = models.CharField(max_length=100, null=True)
image = models.ImageField(default='defaut.jpg', upload_to='document_pics')
def __str__(self):
return self.first_nam
img savinig in documents_pics folder then i am trying to in views.py get data from db and send it to home.html
def home(request):
context = {
'posts': Id.objects.all(),
'title': 'Home'
}
return render(request, 'blog/home.html', context)
home.html
{% extends 'blog/base.html' %}
{% block content %}
{% for post in posts %}
<article class="media content-section">
<img src="{{ post.image }} " width="200" height="200"
</article>
{% endfor %}
{% endblock content %}
and than i am getting 404 error
Try these path on your image jinja code in your html template
{% extends 'blog/base.html' %}
{% block content %}
{% for post in posts %}
<article class="media content-section">
<img src="{{ post.image.url }} " width="200" height="200"
</article>
{% endfor %}
{% endblock content %

Django Default Image is showing

why i can't see default image here below are my model and profile.html file:
Model:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Profile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
image = models.ImageField(upload_to='profile_pics',default='default.jpg')
def __str__(self):
return f'{self.user.username} Profile'
Profile.html:
{% extends 'blog/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<div class="media">
<img class="rounded-circle account-img" src="{{ user.profile.image.url }}">
<div class="media-body">
<h2 class="account-heading">{{ user.username }}</h2>
<p class="text-secondary">{{user.email}}</p>
</div>
</div>
<!-- FORM HERE -->
</div>
{% endblock content %}
Thank you in advance...
in templates you can check the image exists or not, if not can show a default image from static file as follows
{% if user.profile.image %}
<img src="{{ user.profile.image.url }}">
{% else %}
<img src="{% static 'img/default.png' %}">
{% endif %}

Django: the information is not processed for a given condition if

Template tag {% if %} {% endif %} does't work correctly. I need to make the search results on the page appear only after the search query. But for some reason, when the page loads, all existing content appears at once. But after get request filter works correctly.
views.py
def search(request):
place_list = Places.objects.all()
place_filter = PlaceFilter(request.GET, queryset=place_list)
return render(request, 'search/user_list.html', {'filter': place_filter})
html
{% if filter.qs %}
<div class="row">
{% for obj in filter.qs %}
<div class="col-md-3 admin__block">
<div class="cover__wrapper">
<img src="{{ obj.main_photo.url }}" alt="">
<span>#</span>{{ obj.name }}
<p>{{ obj.description }}</p>
</div>
</div>
{% endfor %}
</div>
{% endif %}
filters.py
class PlaceFilter(django_filters.FilterSet):
name = django_filters.CharFilter(lookup_expr='icontains', widget=forms.TextInput(attrs={
'placeholder': 'Search place', 'class': 'input__search'}))
class Meta:
model = Places
fields = ['name']
FilterSet's qs property returns filterset's queryset. So it's always True.
You can use request.GET in template to check if GET contains any request data and render only filtered data:
{% if request.GET %}
<div class="row">
{% for obj in filter.qs %}
<div class="col-md-3 admin__block">
<div class="cover__wrapper">
<img src="{{ obj.main_photo.url }}" alt="">
<span>#</span>{{ obj.name }}
<p>{{ obj.description }}</p>
</div>
</div>
{% endfor %}
</div>
{% endif %}

how to add an image to webapp using Python flask

I need to develop a web app using python flask and I need to add an image to the view page. But I couldn't get it.please help me out of it.
In the example below the image is stored in an SQLite database. From there you can do something like:
#app.route('/show')
def show_pic():
filename = request.args.get('filename','')
t = (filename,)
cur = g.db.execute('select label from pics where filename=?', t)
label = cur.fetchone()[0]
return render_template('upload.html', filename=filename, label=label)
And then in your template:
{% macro pic_path(pic) %}
{{ url_for('return_pic', filename='%s' % pic) }}
{% endmacro %}
{% block content %}
{% if filename is defined %}
<div id="image">
<a href="{{ pic_path(filename) }}" target="_blank">
<img class="new" src="{{ pic_path(filename) }}">
</a>
</div>
{% else %}
<ul>
{% for pic in pics %}
<li class="thumb">
<a href="{{ url_for('show_pic', filename=pic.filename) }}">
<img class="thumb" src="{{ pic_path('thumb_'+pic.filename) }}">
</a>
<strong>{{ pic.label }}</strong>
</li>
{% endfor %}
</ul>
{% endif %}
{% endblock %}

How to delete files in Django?

I followed this tutorial: Need a minimal Django file upload example
Obviously it works. But I want to be able to delete a file as well. Now even if I delete it manually from disc, it still appears on list, even after reconnecting to a server (why?)
I changed the list.html file by adding another form in the loop:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Minimal Django File Upload Example</title>
</head>
<body>
<!-- List of uploaded documents -->
{% if documents %}
<ul>
{% for document in documents %}
<li>{{ document.docfile.name }}
{% if user.is_staff %}
<form action="{% url 'delete' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="submit" value="Delete" />
</form>
{% endif %}
</li>
{% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}
<!-- Upload form. Note enctype attribute! -->
<form action="{% url 'list' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<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" /></p>
</form>
</body>
</html>
As you can see, I added Delete button in a form. By doing so, I have a button near each file. I added this to my views :
def delete(request):
if request.method != 'POST':
raise HTTP404
else:
docId = request.POST.get('docfile', None)
if docId is not None:
docToDel = Document.objects.get(pk=docId)
docToDel.delete()
form = DocumentForm(request.POST, request.FILES)
documents = Document.objects.all()
return HttpResponseRedirect(reverse('myapp.views.list'))
But that does not do anything, just reloads the page.
As I said, now I cannot even delete them manually.
What am I doing wrong?
First of all file on disk and model in DB are different things. To delete file from disk and DB you may try this
from django.shortcuts import get_object_or_404
def delete(request):
if request.method != 'POST':
raise HTTP404
docId = request.POST.get('docfile', None)
docToDel = get_object_or_404(Document, pk = docId)
docToDel.docfile.delete()
docToDel.delete()
return HttpResponseRedirect(reverse('myapp.views.list'))
Also you forgot to specify ID of Document to delete
<!-- List of uploaded documents -->
{% if documents %}
<ul>
{% for document in documents %}
<li>{{ document.docfile.name }}
{% if user.is_staff %}
<form action="{% url 'delete' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="hidden" name="docfile" value="{{ document.pk }}" />
<input type="submit" value="Delete" />
</form>
{% endif %}
</li>
{% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}