Display a picture via Django saved on mysql database - python

I want to display a picture with Django, which is already saved on a mysql database. In all Methods I found people used models.Imagefield(upload_to='path'), but I think this will save the file into this directory and people from other computers won´t have access later.
So the question is, how do I access the database directly and display the picture without saving it in between?
I already managed to do this in python, but I am not quite sure how to implement the code into the models.py.
Something like this was my approach :
class mysqlpicture(models.Model):
#mysqlpic=something?
def openpic():
connection = pymysql.connect(user='root', passwd='***',
host='localhost',
database='db')
cursor = connection.cursor()
sql1='select * from Pictures'
cursor.execute(sql1)
data=cursor.fetchall()
mysqlpic=io.BytesIO(data[1][0])#one means second element of column zero
#img=Image.open(mysqlpic)
#img.show()
cursor.close()
return mysqlpic
and then I tried in the views.py to give mysqlpicdirectly to the httpresponse like this:
def MysqlView(request):
query_results = mysqlpicture.objects.all()
template = loader.get_template('polls/pic.html')
context = {
'query_results': query_results,
}
return HttpResponse(template.render(context, request))
using a template pic.htmlto insert a picture like:
{% for n in query_results %}
<mysqlpic src="{{ n.mysqlpic.url }}" />
{% endfor %}
Has someone an idea how to to this in the right way?

Yes, using ImageField does allow people from other computers to access it later. It inherits all attributes and methods from FileField which uploads the file into the server in the path specified in upload_to and also saves this path into your database to keep its reference. All of that happens when you call the save() method in your model instance.
Then, you can create the url to build a link by calling your_instance.image_field.url in your template. Also remember to have a look at MEDIA_ROOT and MEDIA_URL which respectively tells Django the server root path for saving your files and the url that handles the media served from MEDIA_ROOT.

You can use BinaryField for this purposes.
But as stated in the django documentation:
Although you might think about storing files in the database, consider that it is bad design in 99% of the cases.
from django.db import models
class MysqlPicture(models.Model):
mysqlpic = models.BinaryField()
# ...
And then to display in the template you can convert binary data to base64:
from base64 import b64encode
def mysql_view(request):
query_results = MysqlPicture.objects.all()
template = loader.get_template('polls/pic.html')
context = {
'images': [b64encode(obj.mysqlpic) for obj in query_results],
}
return HttpResponse(template.render(context, request))
Template:
{% for image in images %}
<img src="data:;base64,{{ image }}">
{% endfor %}

Related

Change CSS stles from view in Django

Sorry if this is an obvious question, I am new to django and still learning.
I am creating a website that contains 6 images in total. The images in the website should remain invisible until its image id is passed from views.py.
I have a template index.html page and view that loads when this url is accessed localhost/imageid
What I need now is to make the image visible whenever its url is access. So for instance if a user goes to localhost/1. QR code 1 should be made visible. I am also storing the state of all access images. So if the user accesses the website again and goes to localhost/2 it should make image 1 and 2 visible. I am using sessions to store the state. I just need a way of making the images visible.
Thankyouuuu
Depends so a basic view would be:
from django.views.generic import TemplateView
class MyView(TemplateView):
template_name = 'my_html.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['img_id'] = self.kwargs.get('pk') # this is whatever the variable is named in the URL.
return context
html would be something like this.:
<body>
{%if img_id == 1 %}
<img src="image1path">
{%elif img_id == 2 %}
<img src="image2path">
{% endif %}
</body>
A better way would be to store the images in a database and get the image paths from a model, then you would get that in the context and reference it in the template instead of having if statements.

Django pass render_to_response template in other template

this is probably a question for absolute beginners since i'm fairly new to progrmaming. I've searched for couple of hours for an adequate solution, i don't know what else to do.
Following problem. I want to have a view that displays. e.g. the 5 latest entries & 5 newest to my database (just an example)
#views.py
import core.models as coremodels
class LandingView(TemplateView):
template_name = "base/index.html"
def index_filtered(request):
last_ones = coremodels.Startup.objects.all().order_by('-id')[:5]
first_ones = coremodels.Startup.objects.all().order_by('id')[:5]
return render_to_response("base/index.html",
{'last_ones': last_ones, 'first_ones' : first_ones})
Index.html shows the HTML content but not the content of the loop
#index.html
<div class="col-md-6">
<p> Chosen Items negative:</p>
{% for startup in last_ones %}
<li><p>{{ startup.title }}</p></li>
{% endfor %}
</div>
<div class="col-md-6">
<p> Chosen Items positive:</p>
{% for startup in first_ones %}
<li><p>{{ startup.title }}</p></li>
{% endfor %}
Here my problem:
How can I get the for loop to render the specific content?
I think Django show render_to_response in template comes very close to my problem, but i don't see a valid solution there.
Thank you for your help.
Chris
--
I edited my code and problem description based on the solutions provided in this thread
the call render_to_response("base/showlatest.html"... renders base/showlatest.html, not index.html.
The view responsible for rendering index.html should pass all data (last_ones and first_ones) to it.
Once you have included the template into index.html
{% include /base/showlatest.html %}
Change the view above (or create a new one or modify the existing, changing urls.py accordingly) to pass the data to it
return render_to_response("index.html",
{'last_ones': last_ones, 'first_ones' : first_ones})
The concept is that the view renders a certain template (index.html), which becomes the html page returned to the client browser.
That one is the template that should receive a certain context (data), so that it can include other reusable pieces (e.g. showlatest.html) and render them correctly.
The include command just copies the content of the specified template (showlatest.html) within the present one (index.html), as if it were typed in and part of it.
So you need to call render_to_response and pass it your data (last_ones and first_ones) in every view that is responsible for rendering a template that includes showlatest.html
Sorry for the twisted wording, some things are easier done than explained.
:)
UPDATE
Your last edit clarified you are using CBV's (Class Based Views).
Then your view should be something along the line:
class LandingView(TemplateView):
template_name = "base/index.html"
def get_context_data(self, **kwargs):
context = super(LandingView, self).get_context_data(**kwargs)
context['last_ones'] = coremodels.Startup.objects.all().order_by('-id')[:5]
context['first_ones'] = coremodels.Startup.objects.all().order_by('id')[:5]
return context
Note: personally I would avoid relying on the id set by the DB to order the records.
Instead, if you can alter the model, add a field to mark when it was created. For example
class Startup(models.Model):
...
created_on = models.DateTimeField(auto_now_add=True, editable=False)
then in your view the query can become
def get_context_data(self, **kwargs):
context = super(LandingView, self).get_context_data(**kwargs)
qs = coremodels.Startup.objects.all().order_by('created_on')
context['first_ones'] = qs[:5]
context['last_ones'] = qs[-5:]
return context

Uploading files in django admin, download through public site

I am running a Django website and I want to be able to upload a file through my admin panel and then have visitors to the main site be able to download it. I am running my site using Django-nonrel, Django FileTransfers and Google App Engine. I believe the upload functionality is working correctly as I am able to see the file in my App Engine Blob Storage. What I can't seem to figure out is how to present a download link to the specified file on the public website. I have pasted the relevant classes below:
I have an app called Calendar, that has the following model:
class CalendarEvent (models.Model):
start = models.DateTimeField(auto_now=False, auto_now_add=False)
end = models.DateTimeField(auto_now=False, auto_now_add=False)
title = models.CharField(max_length=500)
description = models.TextField()
file = models.FileField(upload_to='uploads/%Y/%m/%d/%H/%M/%S/')
Here is the view:
def calendar(request):
events = CalendarEvent.objects.exclude(start__lt=datetime.datetime.now()).order_by('start')
return render_to_response('home/calendar.html',{'events': events},context_instance=RequestContext(request))
def download_handler(request, pk):
upload = get_object_or_404(CalendarEvent, pk=pk)
return serve_file(request, upload.file, save_as=True)
Here is my admin:
class calendarAdmin(admin.ModelAdmin):
list_display = ('title','start','end')
admin.site.register(CalendarEvent, calendarAdmin)
Finally, here is the relevant part of my template:
{% for e in events %}
{% url Calendar.views.download_handler pk=e.pk as fallback_url %}
Download
{% endfor %}
{% firstof e.file|public_download_url fallback_url %} is just returning blank, i'm not sure where I am going wrong.
The GAE blob store does not support public download according to the documentation here, so if you use the default backend for public download urls, it returns None. So my guess is that e.file|public_download_url always return None. You could verify that.
Then I think your template is wrong. You're trying to access e.views.download_handler where it should be Calendar.views.download_handler if your app is named Calendar.
I think the sample on the django-filetransfers page is error prone because the variable used in the template loop has the same name as the sample app: "upload".
If this doesn't fix it, could you post your urls.py from Calendar app. It could be that the template's url method is not able to resolve the url for Calendar.views.download_handler if there is no mapping in urlpatterns.
You should have something like
urlpatterns = patterns('Calendar.views',
...
(r'^download/(?P<pk>.+)$', 'download_handler'),
...
)
in this file.
I don't see anything special, eg
Download File
should work, or just use e.file.url directly?
I haven't deployed on Google App Engine myself, but this appears to be what django-filetransfers was designed for:
http://www.allbuttonspressed.com/projects/django-filetransfers#handling-downloads
edit: I believe I've answered this in the other question you posted, then: Trouble downlaoding file using Django FileTransfers
I think easiest way is to write a view since this file blob cannot be retrieved directly to write a function which is such:
def file_transfer(req, calendar_event_id):
try:
ce = CalendarEvent.objects.get(calendar_event_id)
except CalendarEvent.DoesNotExist:
raise Http404()
file = ce.file (Write Google appengine specfic routine to pull file)
return HttpResponse(file, media_type='file content type')
Hook it up on urls.py

How to show widgets on pages in Flask?

How can I create a widget on the site, such as login forms, dynamic menu (items taken from the database), site statistics?
I know that you can render a template that will extend out of a base template. And in the base template you can create these widgets.
But I do not know how to move the logic from the base template to my code. For example, the selection data for the block. Such actions certainly can be done in the template, but it would be a poor method in my opinion.
Sorry for my bad English. If you can not understand, I'll try to rephrase.
You would use a python library called WTForms. It helps you write code for creating forms and other widgets backed by database which you can render using jinja2 templates.
class YourForm(Form):
your_field1 = TextField()
....
your_fieldn = SubmitField()
#app.route('/')
def view():
form=YourForm()
return render_template('your.html', form=form)
In your.html
<form >
{{ form.your_field1 }}
....
{{ form.your_fieldn }}
</form>
Check out this flask pattern for form validation and rendering to know more about it.
Edit: To create global variables available to all templates,there are two ways:
You can use global dict of jinja environment.
This is the code:
app.jinja_env.globals.update({'variable':1})
You can use ContextProcessor. Code:
#app.context_processor
def inject_variable():
return dict(variable=1)
Now you can access variable in any template of your app.

google app engine form validation with css in python

I have been looking at form validation in python using Django as this seems to be the default way to do it, other than checking each field, performing some validation and kicking out a specific message for each field that is badly formed. Ideally I want the benefits of form validation, but I do not know how to couple this Django way with the .css way I am displaying by form.
My form is templated HTML with a css behind to handle the display. The code uses data to send back the form if there is an issue and displays the form which was created previously. So in a nutshell, how do we couple validation to a pre formatted HTML form with css without individually validating.
Here is the code I am using:
Looking at those references etc http://www.djangobook.com/en/2.0/chapter07/, I have been unable to come up with a good way to couple everything together. The problem relates to send back the form and contents if the form is not valid. So what I am doing is pulling out each generated form item by item and displaying in the .html file.
So my question is. How do I get this working. Now I can display the form with css style sheet, but I cannot seem to get validation working on the field and I'm always generating an error.
class Quote(db.Model):
email = db.StringProperty(required=True)
class QuoteForm(djangoforms.ModelForm):
class Meta:
model = Quote
exclude = ['entry_time']
class MainPage(webapp.RequestHandler):
def get(self):
form = QuoteForm();
template_values = {}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, {'form': form}))
def post(self):
data = QuoteForm(data=self.request.POST)
if data.is_valid():
# save here
self.redirect('/Confirm.html')
else:
template_values = {}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, {'form': data}))
and the part of the .html file is here
<div>
{{ form.email.errors }}
<label for="id_email">Your e-mail address:</label>
{{ form.email }}
</div>
It would nothing that I put into the email field validates correctly. I'm not sure why!? I'm losing the information I have already put into the form. How do I retain this information and actually do proper validation. The model suggests that only a non blank string is required, but nothing ever satisfies the validation.
Thanks
"Customizing Form Design" section of http://www.djangobook.com/en/2.0/chapter07/ explains how to style forms to go with your HTML and CSS.
Looking at those references etc http://www.djangobook.com/en/2.0/chapter07/, I have been unable to come up with a good way to couple everything together. The problem relates to send back the form and contents if the form is not valid. So what I am doing is pulling out each generated form item by item and displaying in the .html file.
So my question is. How do I get this working. Now I can display the form with css style sheet, but I cannot seem to get validation working on the field and I'm always generating an error.
class Quote(db.Model):
email = db.StringProperty(required=True)
class QuoteForm(djangoforms.ModelForm):
class Meta:
model = Quote
exclude = ['entry_time']
class MainPage(webapp.RequestHandler):
def get(self):
form = QuoteForm();
template_values = {}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, {'form': form}))
def post(self):
data = QuoteForm(data=self.request.POST)
if data.is_valid():
# save here
self.redirect('/Confirm.html')
else:
template_values = {}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, {'form': data}))
and the part of the .html file is here
<div>
{{ form.email.errors }}
<label for="id_email">Your e-mail address:</label>
{{ form.email }}
</div>
It would nothing that I put into the email field validates correctly. I'm not sure why!? I'm losing the information I have already put into the form. How do I retain this information and actually do proper validation. The model suggests that only a non blank string is required, but nothing ever satisfies the validation.

Categories