django upload image and show that image - python

I have a question,this is my code
When uploade image success,It will return all data (item=Item.objects.all()) and show on the template
What if I only want the picture which is just uploaded by user to show on template(not all images in database),how can I do this?
Please guide me !
Thank you very much.
views.py
def background(request):
if request.method=="POST":
img = ItemForm(request.POST, request.FILES)
if img.is_valid():
img.save()
return HttpResponseRedirect(reverse('imageupload:background'))
img=ItemForm()
item=Item.objects.all()
return render(request,'uploader/background.html',{'form':img,'item':item,})
models.py
from sorl.thumbnail import ImageField
class Item(models.Model):
image = ImageField(upload_to='thumb/')
class ItemForm(forms.ModelForm):
class Meta:
model = Item
templates:
<form action="#" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form}} <input type="submit" value="Upload" />
</form>
{% for i in item%}
{{i.image}}
{% thumbnail i.image "1024" crop="center" format="PNG" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}">
{% endthumbnail %}
{% endfor %}

It would be better if you add a field that can be used to keep track of your latest uploaded Image.
class Item(models.Model):
image = ImageField(upload_to='thumb/')
upload_time = models.DateTimeField(auto_now=False, auto_now_add=True)
Here I have added one more feild named upload_time with parameter auto_now_add=True.
DateField.auto_now_add
Automatically set the field to now when the object is first created.
Useful for creation of timestamps. Note that the current date is always used;
it’s not just a default value that you can override.
After that you can get the latest object from Item model using latest method.
def background(request):
if request.method=="POST":
img = ItemForm(request.POST, request.FILES)
if img.is_valid():
img.save()
return HttpResponseRedirect(reverse('imageupload:background'))
img=ItemForm()
item=Item.objects.latest('upload_time')
return render(request,'uploader/background.html',{'form':img,'item':item,})
About latest:
latest(field_name=None)
Returns the latest object in the table, by date, using the field_name provided as the date field.
So you will be getting single object then it would not be required to iterate it in your template.
{{item.image}}
{% thumbnail item.image "1024" crop="center" format="PNG" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}">
{% endthumbnail %}

You can have the id there when save. Just set the id in session. So when redirecting you can have the id of that photo & user also like ...
photoId = request.session['photoId']
userId = request.session['_auth_user_id']
item=Item.objects.get(pk=photoId) #you can also use filter by userId
Code:
if img.is_valid():
img.save()
request.session['photoId'] = img.id
return HttpResponseRedirect(reverse('imageupload:background'))

You don't have to use the session and redirect or add any extra field. The ModelForm save() method returns the object just saved. Try this:
# views.py
def background(request):
form = ItemForm(request.POST or None, request.FILES or None)
item = None
if request.method=="POST" and form.is_valid():
item = form.save()
return render(request,'uploader/background.html',{'form': form,'item': item,})
# template
<form action="#" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form}} <input type="submit" value="Upload" />
</form>
{% if item %}
{{ item.image }}
{% thumbnail item.image "1024" crop="center" format="PNG" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}">
{% endthumbnail %}
{% endif %}

I did something slightly different. My view renders a graph figure (an image) dynamically each time so it is not in the database. But to embed a single instance of a graph from my models this is what I did:
First, I made a view that renders the graph from my data and created a url that goes to it (selected by using it's id):
url(r'^graphs/graphImage/(?P<graph_id>\d+?)/$', 'hydro.views.render_graph', name='graphImage'),
no need to show my view, but if i went to that url my view would be called and it would render the graph and only the graph. Similar to most sites where if you click on the picture you just get a webpage showing only the picture.
Now working with this url:
url(r'^graphs/(?P<graph_id>\d+?)/$', 'hydro.views.single_graph', name='graph_detail'),
this view brings up a template with this bad boy:
{% url 'graphImage' graph.id as the_graph %}
<img src="{{the_graph}}" alt="{{the_graph}}"/>
the url portion grabs my graphImage url and inputs the graph.id with it. And then I name it the_graph to keep it simple.
then i make an image tag as the src as the _graph. Don't worry about alt it just shows the url if it doesnt work for debugging.
So what I did was render a graph on one webpage and just use that as a source for an image tag. Theres a million ways to do this sort of thing, but this was the most obvious with my limited skills and just knowing about html and django.

Related

Display an image in a post's details corresponding to the first letter of the user's name?

In my blog app I want to display an image in the post's details. But the tricky part is that I want to display the image corresponding to the first letter of the user's first name. For example if the user's name is "Sam" I want to display the letter 'S' image. I tried to add all letters avatars in static folder.And i tried
<!--code for displaying image from database--->
{% if post.author.profile.image.url is None %}
<img src="{% static 'images/{{letter}}.png' %}" class='logo3'/>
{% else %}
<img src="{{ post.author.profile.image.url }}" class='logo3'/>
{% endif %}
views.py
def homepage(request):
l=[]
post= Post.objects.all().order_by('-date')
ctr= post.count()
print(ctr)
for i in range(0,ctr):
letter = post[i].author_id[0].lower()
l.append(letter)
return render(request,'layout.html',{'posts':post,'letter':l})
models.py
class Post(models.Model):
title=models.CharField(max_length=100)
desc=models.TextField()
date=models.DateTimeField(auto_now=True)
author=models.ForeignKey(settings.AUTH_USER_MODEL,
to_field="username",on_delete=models.CASCADE)
class Profile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
image = models.ImageField(default=None,upload_to='pics')
In my browser if i click on inspect in img tag the src displaying is /media/None
The simplest way to display images according to the user's first name is create a div instead of an image with rounded corners.
{% if post.author.profile.image %}
<img src="{{ post.author.profile.image.url }}" class='logo3'/>
{% else %}
<div class="text-center align-center" style="align-items:center !important;justify-content:center !important;background-color: black;width: 50px;height: 50px;border-radius: 50px">
<p style="padding-top: 25%" >{{ post.author.username.0 }}</p>
</div>
{% endif %}
{{ post.author.username.0 }} will give you the first letter of username
You are accessing author by post.author object, so just do post.author.username.0 in your template, you don't need that list of letters in context. name.0 in Django templates corresponds to name[0] in Python.
Edit: set to username field, the alternatives are first_name and last_name.

How to display django model data on the django cms page template

I would like to be able to use my external app data on django cms page.
I am able to use custom plugin data but not data from normal django app
I tried creating views to handle my data but how do I call this view from django cms pages?
here is exactly what I am asking for but his explanation is shallow and the link provided in the answer is no longer in use.
Here is my model:
class ExternalArticle(models.Model):
url = models.URLField()
source = models.CharField(
max_length=100,
help_text="Please supply the source of the article",
verbose_name="source of the article",
)
title = models.CharField(
max_length=250,
help_text="Please supply the title of the article",
verbose_name="title of the article",
)
class Meta:
ordering = ["-original_publication_date"]
def __str__(self):
return u"%s:%s" % (self.source[0:60], self.title[0:60])
My template has placeholders
{% load cms_tags %}
{% block title %}{% page_attribute "page_title" %}{% endblock title %}
{% block content %}
<section class="section">
<div class="container">
<div class="row">
<!-- header-->
<div class="col-lg-12">
<div class="updates">
{% placeholder "header" %}
</div>
</div>
<!-- header end-->
</div> <!-- end row -->
but I don't mind displaying this data anywhere on the template if not possible inside a place holder
I have a custom page that I am using in Django cms.
I would like to display the above data is a section in the Django cms page
If this model was inheriting from CMSPlugin then that would be easy because I could use a custom plugin in my placeholder
I expect to display the data from my model in the template.
I was able to achieve this by doing the following:
#plugin_pool.register_plugin
class ArticlesPluginPublisher(CMSPluginBase):
model = ArticlesPluginModel
name = _("Articles")
render_template = "article_plugin/articles.html"
cache = False
def render(self, context, instance, placeholder):
context = super(ArticlesPluginPublisher, self).render(
context, instance, placeholder
)
context.update(
{
"articles": Article.objects.order_by(
"-original_publication_date"
)
}
)
return context
The plugin model(ArticlesPluginModel) is just for storing the configurations for the instance of the plugin. Not the actual articles.
Then the render will just add to the context the relevant articles from the external app(Article)
You must somehow connect the ExternalArticle with a page object. For example
by defining the ExternalArticle as a page extension
or with an AppHook
or - low-tech - with a PageField on the ExternalArticle model
{% load cms_tags %}
<h1>{{ instance.poll.question }}</h1>
<form action="{% url polls.views.vote poll.id %}" method="post"> {% csrf_token %}
{% for choice in instance.poll.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>

Flask dynamic input form, FormField returns blank POST data

I'm working on a Flask webapp that asks (internal) users to select options for an arbitrary number of files that will be in a directory on our network so that some other scripts can process the files according to those options (not relevant to this issue, but if you're curious they are A/V files we need to process).
The problem I'm having is that I can't seem to both dynamically generate the form fields needed (there could be 0 - dozens of files in the server directory the app is looking in) and collect the form data for each instance of the form class I created for the input objects. How do you shoehorn n form instances into an instance of another form class??
I have a base IngestForm class and an ObjectForm class that describes fields pertaining to each individual object. My basic suspicion is that wtforms can't have a subclass that includes other forms... but I can print everything out at various steps before the form gets POSTed and see all the data that I expect as a dict, and I can see that the sub-forms are there as wtforms objects. From my index.html template I can see all the expected data from the ObjectForm instances. But once the super-form is posted, all that is returned is a blank choicesDict (see below) and the submit value. Does the IngestForm instance get reinitialized or something weird when I hit Submit?
Here's what I have now. I have set up a dict for choices where each key is the path of the file in question and the value is an instance of the ObjectForm class:
forms.py
class ObjectForm(FlaskForm):
"""
Fields for an individual object
"""
targetFilePath = wtforms.HiddenField('targetObjectPath')
option1 = wtforms.BooleanField('Option1?')
option2 = wtforms.BooleanField("Option2?")
# etc.
class IngestForm(FlaskForm):
'''
General input form
'''
choicesDict = {}
# also tried just targetObject = wtforms.FormField(ObjectForm)
submit = wtforms.SubmitField('Submit')
routes.py:
[import relevant stuff]
#app.route('/index',methods=['GET','POST'])
def index():
# GET A DICT OF PATHS AND BASENAMES TO PROCESS {'fullPath':'basename'}
objects = listObjects.list_objects()
class OneObject(forms.ObjectForm):
pass
choices = {}
for path,_object in objects.items():
choices[path] = OneObject(targetPath=path,targetBase=_object)
# also tried setattr(forms.IngestForm,'choicesDict',choices)
form = forms.IngestForm()
form.choicesDict = choices
if form.is_submitted():
return redirect(url_for('status'))
return render_template(
'index.html',title='Index',objects=objects,form=form
)
#app.route('/status',methods=['GET','POST'])
def status():
# DO THE STUFF
ingest.html template:
{% block content %}
<h1>Here are files to ingest:</h1>
<form action="{{url_for('status')}}" method='POST'>
<div>
{% for item,vals in form.choicesDict.items() %}
<p>{{vals.targetBase.data}}</p>
<p>{{vals.option1.label}}{{vals.option1()}}</p>
<p>{{vals.option2.label}} {{vals.option3()}}</p>
<p>{{vals.etc.label}}{{vals.etc()}}</p>
{%endfor%}
</div>
{{form.submit()}}
</form>
{% endblock %}
status.html template just takes the POST data. Not really relevant here except to say I can see it is getting none of the choicesDict
OK so I solved this in a really hack-y way but whatever. I used a jinja2 macro following this example and in my form template constructed field names/ids that are unique to the files I'm interested in.
So for each file ['a.mov','b.mov','c.mp4'] in my network directory, I create a dict like so: {'a.mov': SubclassObjectForm, 'b.mov': SubclassObjectForm } and I have a MainForm instance field that includes this dict. When I render the form, the jinja macro creates name and id attributes for the <label> and <input> fields as needed that include a prefix for the file in question.
For example <input name='targetObjectFilePath-movieA.mov' value='/full/path/to/file' type='hidden>.
When the form gets POSTed, it's just a matter of pulling the relevant bits of data in my view.
I hope this helps someone! It might not be elegant or 'pro' but it gets my task done. Next step... styling!
forms.py
class ObjectForm(FlaskForm):
"""
Fields for an individual object
"""
targetFilePath = wtforms.HiddenField('targetObjectPath')
targetBase = wtforms.HiddenField('targetObjectBasename')
option1 = wtforms.BooleanField('Option1?')
option2 = wtforms.BooleanField("Option2?")
# etc.
class IngestForm(FlaskForm):
'''
General input form
'''
choicesDict = wtforms.HiddenField(default='no choices')
submit = wtforms.SubmitField('Submit')
routes.py
[import relevant stuff]
#app.route('/index',methods=['GET','POST'])
def index():
# GET A DICT OF PATHS AND BASENAMES TO PROCESS {'fullPath':'basename'}
objects = listObjects.list_objects()
class OneObject(forms.ObjectForm):
pass
choices = {}
for path,_object in objects.items():
choices[path] = OneObject(targetPath=path,targetBase=_object)
form = forms.IngestForm()
form.choicesDict = choices
return render_template(
'index.html',title='Index',form=form
)
#app.route('/status',methods=['GET','POST'])
def status():
data = request.form.to_dict(flat=False)
# DO THE STUFF
index.html
{% import "macros.html" as macros %}
{% extends "base.html" %}
{% block content %}
<h1>Here are files to ingest:</h1>
<form action="{{ url_for('status') }}" method='POST'>
{{ form.hidden_tag() }}
{{ form.csrf_token }}
{# iterate over the form dict with subforms included: #}
{% for item,vals in form.choicesDict.items() %}
<div>
{# iterate over subform fields and include target file basename #}
{% for field in vals %}
{{macros.render_field(field,vals.targetBase.data)}}
{% endfor %}
</div>
{%endfor%}
{{form.submit()}}
</form>
{% endblock %}
macros.html
{% macro render_field(field, uniqueName) %}
<p>
{# I only care about 2 kinds of data: filenames/paths and boolean options. #}
{% if field.type == 'BooleanField' %}
<label for="{{ field.id }}-{{ uniqueName }}">{{ field.label.text }}</label>
<input name="{{ field.id }}-{{ uniqueName }}" id="{{ field.id }}-{{ uniqueName }}" type="checkbox" default=""></input>
{# render hidden input for full path for later processing #}
{% elif field.name == 'targetPath' %}
<input name="{{ field.id }}-{{ uniqueName }}" id="{{ field.id }}-{{ uniqueName }}" type="hidden" value="{{ field.data }}"/>
{# use basename for local id purposes and display value as label for users #}
{% elif field.name == 'targetBase' %}
<label for="{{ field.id }}-{{ uniqueName }}">{{ uniqueName }}</label>
<input name="{{ field.id }}-{{ uniqueName }}" id="{{ field.id }}-{{ uniqueName }}" type="hidden" value="{{ field.data }}"/>
{% endif %}
</p>
{% endmacro %}

Django: form as image

I have a simple form in my template, index.html:
{% if stripped_thumbnail_file_list %}
{% for thumbnail_name in stripped_thumbnail_file_list %}
<div class="">
<div class="">
This is my form
<form class="" action="{% url 'index' %}" method="post">
{% csrf_token %}
<input type="image" value="{{ thumbnail_name }}" src="{{ MEDIA_URL}}thumbnails/{{ thumbnail_name }}.jpg">
</form>
</div>
</div>
{% endfor %}
{% else %}
<p>No videos are available.</p>
{% endif %}
I want the index view to pull the {{ thumbnail_name }} value from this form and use it as a variable when the index view redirects to a different view that will use that name to play a matching video.
I have been unsuccessful in trying to pull that value from the form as I have it. I suspect this may because I'm not creating a Django form object. I tried to create that object, but I can't find any examples of a Django form object as an image like I have in my form.
What should that look like? Or, can someone make a recommendation on how to pull the value from the form as is?
EDIT: adding views.py snippet:
def index(request):
# if this is a POST request we need to process the form data
if request.POST:
# get thumbnail_name from form
# redirect to a new URL (hardcode thumbnail name for now):
return HttpResponseRedirect('2017-02-01_04-29-10/video/')
thumbnail_file_list = get_file_list(target_directory, ".jpg")
stripped_thumbnail_file_list = strip_file_extension(thumbnail_file_list)
template = loader.get_template('dash/index.html')
context = {
'stripped_thumbnail_file_list': stripped_thumbnail_file_list,
}
return HttpResponse(template.render(context, request))
def video(request, file_name):
print("this is the file name passed: " + file_name)
template = loader.get_template('dash/video.html')
context = {
'file_name': file_name,
}
return HttpResponse(template.render(context, request))
First: you need to declare the 'name' attribute on your form imput.
<input name="thumbnail_name" type="image" value="{{ thumbnail_name }}" src="{{ MEDIA_URL}}thumbnails/{{ thumbnail_name }}.jpg">
Second: Why don't you just set the 'action' of the form to your 'video' function (when you perform a redirect, you are losing all your POST data).Then, from there you could retrieve the value: something like that
def video(request):
file_name = request.POST.get('thumbnail_name')
print("this is the file name passed: " + file_name)
template = loader.get_template('dash/video.html')
context = {
'file_name': file_name,
}
return HttpResponse(template.render(context, request))
Hope it helps

Image not showing in for loop

I am trying to display the image and name in a for loop on my template.
This is what I have on my template for loop, and I thought it should work, but it doesn't
{% for op in tracked_objects %}
{% if op.is_mine %}
<div style="float:left;">
<div>
<img src="{{ op.tracked_object.image }}" alt="">
<a href='{% url track-profile op.tracked_object.id %}'>{{ op.tracked_object }}</a><br>
</div>
</div>
{% endif %}
{% endfor %}
I know that op.is_mine is true because the Name shows.
Here is my views.py:
#login_required
def profile(request):
user = request.user
tracked_objects = user.tracked_object_perms.all().order_by('is_mine',)
context = {
'tracked_objects':tracked_objects,
}
return render_to_response( 'accounts/profile.html' , RequestContext(request, context))
and finally the models.py
name = models.CharField(max_length='140')
image = models.ImageField(upload_to='img/tracked_object_images', null=True, blank=True)
Update
Now when I use the below anser of adding the .url onto the end, I get three broken image icons. Now I have checked the path and it goes to the correct image. Would this be a server issue possibly? Or something along those lines?
Try:
<img src="{{ op.tracked_object.image.url }}" alt="">
See Using django.contrib.staticfiles.

Categories