Python Pyramid: Load view based on database variable - python

I just started pyramid and have a problem with loading views. I want to load a view based on a variable fetched from the database like my PHP solution here: rewrite url with htaccess
I've build a script that can do this, but I'm quite sure this is not the right way to do it. I think when I use this in a real site it will get very complicated and messy. Could someone explain how to this properly or point me to an other solution?
My current script:
config.add_route('home', '/')
config.add_route('admin_home', '/admin')
config.add_route('admin_pages', '/admin/pages')
config.add_static_view(name='static', path='website:static')
config.add_route('view_loader', '/*url')
views.py
class ViewLoader(object):
def __init__(self, request):
self.request = request
#view_config(route_name="view_loader", renderer="templates/view_loader.pt")
def view_loader(self):
request = self.request
url = "/%s" % request.matchdict["url"]
page = DBSession.query(Pages).filter_by(url=url).one()
return dict(title=page.title, include=page.template)
view_loader.pt
<!DOCTYPE html>
<html>
<body>
<metal:main use-macro="load: ${include}"></metal:main>
</body>
</html>
Idea of the system:
Admins can create pages in a cms with random url's and have to select a template. The system has to generate these pages.
url = /random/random -> look for template in db -> render template_1
url = /random2/random2 -> look for template in db -> render template_2
So I want to render the template after the class/method is being called to determine what template has to be rendered

I found a more logical approach for my problem with the help of this question Map different URLs to same view. Actually the solution is quite simple I just didn't know it is possible to declare a renderer in add_view()
main.py
pages = DBSession.query(Pages)
for page in pages:
config.add_route(str(page.name), page.url)
if page.template.decode('utf-8') == "home_view":
config.add_view(home_view, route_name=str(page.name), renderer='templates/home.pt')
elif page.template.decode('utf-8') == "detail_view":
config.add_view(home_view, route_name=str(page.name), renderer='templates/detail.pt')
views.py
def home_view(self, request):
return dict(.....)

Related

Rendering a template inside a django view?

So I'm designing a website with Django that does some heavy scraping based on user input.
This can take up to 5-6 secs and while I am working on cutting that down I would like for some kind of a loader to show up while the backend is scraping.
I have put a loader as you normally would using CSS and JavaScript inside the template but that only pops up when the template is actually loading and not when the view is scraping to gather data for the template.
Tried this in Django:
def scrape(request):
render(request,'loader.html')
*do scraping*
return render(request,'results.html',scraped_data)
The method I would use to solve this is to fire an async function within the scrape view.
#shared_task
def do_the_needful():
return "hello I am doing the needful"
def scrape_result(request, scrape_id):
result = AsyncResult(scrape_id).get()
# convert result to json or some other web format
return result_as_json
def scrape(request):
scrape_request_id = do_the_needful.submit()
return render(request, "scrape.html", context={"scrape_request_id": scrape_request_id}
Then within the HTML you'll need to create some Javascript which will perform Ajax requests to the scrape_result view using the scrape_request_id in the context.

How to show images in Django Template with out static?

I have an API which gives me a list of movies, and there images are in HTTP links like:
https://d2gx0xinochgze.cloudfront.net/5/public/public/system/posters/12/thumb/Tevar-Movie-Opening-Day-Box-Office-Collection-Report-1140x752_1482917123.jpg
So in django we use static file {% static 'image.jpg' %} to display images in templates, But how to display api images links in template?
{% static 'image.jpg' %} doesn't magically make the image show up in the website, django renders the template with what its been given. Static means take a look at the statics folder, search for the given parameter as a file, and get the url for that given static asset.
In your particular case, you say you get the url of the images. You can easily add those urls to context, which is then gonna be a part of the rendering process.
For a function view it would roughly look like this.
def view(request, *a, **kw):
template = loader.get_template('my_template.html')
context = {'my_image': get_image_from_api()}
return HttpResponse(template.render(context, request))
For a class based view it would roughly look like this.
class MyView(TemplateView):
template_name = 'my_template.html'
def get_extra_context(self):
_super_context = super().get_extra_context()
context = {'my_image': get_image_from_api()}
return {**_super_context, **context}
For both of these views, which are roughly the same; you now can use {{my_image}} inside the template to refer to the url. Hope it helps!
Fetch the images via python in views per say. Pass them through your context when rendering the page. Use django's template tags to put the URLs within tags.

Django returning static HTML in views.py?

So I have a standard Django project with a basic view that returns a simple HTML confirmation statement. Would it be plausible for me to define all of my HTML in the view itself as a really long string and return that using HttpResponse() I know it's a bit unorthodox, but this is an example of what I'm thinking about:
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import render_to_response
def index(request):
html = """
<html>
<body>
This is my bare-bones html page.
</body>
</html>
"""
return HttpResponse(html)
My corresponding JS and stylesheets would be stored in the same directory as views. py in my app in this example. Just making sure: I'm not asking if this works, because I already know the answer is yes, I just want to know if there are any disadvantages/drawbacks to this method, and why don't more people do this?
You can use built-in template renderer to get works filters/templatetags/etc
Most people dont use this because it mixes Python with HTML and gets very messy and out of hand very quickly
To answer your question, this solution works alright, but it is not adopted by many programmers because it makes the whole code disorganized and not easy to understand.
Also, this system would not be good for large projects because the code would contain lots of html in the same file as the python. It is always nice and time saving to separate code into files based on performance.
A better solution
Save your html in a folder called templates in the current directory, in this case, the templates folder can contain an index.html file which would have
<html>
<body>
This is my bare-bones html page.
</body>
</html>
in the views create an index view for this template using the code below
def index(request):
return render(request, 'index.html')
if you would need to pass in some data to the html you can use context in the request as shown below:
def index(request):
context = {
"name":"some name"
}
return render(request, 'index.html', context=context)
access the data in html using the structure below:
<html>
<body>
The data passed to the page is {{name}}.
</body>
</html>
I hope this helps

render_to_response or redirect changes the template elements in Django 1.8

I'm trying to check if email id entered by user is existing in the database table, if existing - I would like to route to 'prof.html' template otherwise just show a message in the login.html template.
Both the conditions are working fine.
However, the problem is when I use redirect() or render_to_response() -
the destination template elements like div, input etc., are being changed automatically (prof.html in this case) ?
Can we also send the context information to destination template ?
(response data or any object from the database and redirect to prof.html template via view in this case)
Below is my code :
Views.py
def verifyme(request):
if request.method == "POST":
emailid4loginV = request.POST['emailid4login_Aj']
else:
emailid4loginV = ''
response_data = ''
return HttpResponse(response_data, content_type="text/plain")
response_data = ''
if Employee.objects.filter(email = emailid4loginV).exists():
response_data='Thanks for waiting - login successful'
#return render_to_response('app/prof.html', { 'response_data':response_data},
# context_instance = RequestContext( request ) )
return redirect('/myprofile')
else:
response_data='Ouch! you are not a registered user!'
return HttpResponse(response_data, content_type="text/plain")
urls.py
url(r'^myprofile$', 'app.views.profile', name='profile'),
Just for your info, 'profile' view does return some objects from the table and renders in the template app/prof.html.
I observed that the destination template is being rendered in same login.html template (How ? : In the browser url, I dont see myprofile - but the one for login) But when I request the myprofile manually by entering in the website url (localhost:xxxxx/myprofile), it works perfectly :(
URL before submitting request in login.html :
URL after submitting request in login.html - myprofile is rendered in the same page :
When I manually type in the url, template just works perfectly..
Could you please let me know what could be the problem ?
EDIT:
Solved this issue with a little trick, posted in the below
https://stackoverflow.com/questions/31091938/why-is-httpresponseredirectreverse-doesnt-redirect-to-new-page
1) Actually there are many ways to pass data to next view ... generally in such cases like you have better way - using sessions (cookie|localstorage|sessionstorage), it is like clipboard ... save session data in one view and get it later in another one. For example:
First view:
self.request.session['response_data'] = 'some text'
self.request.session.set_expiry(0) # user’s session cookie will expire when the user’s Web browser is closed.
Other views:
response_data = self.request.session.get('response_data', '')
But if you planning just use this data in template Django has some kind more high-level interface for it and in your case semantically right to use it - The messages framework https://docs.djangoproject.com/en/1.8/ref/contrib/messages/
2) If you want redirect to another view better use url namespaces and reverse https://docs.djangoproject.com/en/1.8/ref/urlresolvers/#reverse
return HttpResponseRedirect(reverse(app.views.profile)) # here I've passed callable object because you have not show your app url namespace, but generally use namespaces
https://docs.djangoproject.com/en/1.8/topics/http/urls/#url-namespaces

Can I serve the contents of a static file directly as the Http response from a view?

I'm looking to return the contents of a static file as the (sometimes) HttpResponse from one of my views.
Is there a simple way to do this in Django?
If the view sometimes does something with templating or any other calculations, then the best way will be to decide on the "sometimes" when you need to return a static object, and then issue a temporary redirect to that static url - this then leaves the server serving your static content the job of delivering the content.
update
Since I haven't used Django in a while, just generally web development etc... I have been informed that Django from 1.3+ includes a (what looks like) very easy redirect mechanism. (Simpler than what I recall anyway!)
https://docs.djangoproject.com/en/dev/topics/class-based-views/
courtesy of Tadeck
I really liked Jon Clement's idea. Though if you ever need to, this is how you serve a file:
def view(request):
with open(path) as file:
response = HttpResponse(file.read(), content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename=filename.pdf'
return response
There is a way, in addition to what others have shown, this is sometimes used for returning responses for requests for robots.txt:
in views.py:
from django.views.generic import TemplateView
class RobotsTxtView(TemplateView):
"""A class-based view for responding to requests for robots.txt file
"""
template_name = 'robots.txt'
def render_to_response(self, context, **kwargs):
"""Overwritten render_to_response for applying text/html mimetype
"""
return super(RobotsTxtView, self).render_to_response(context,
content_type='text/plain', **kwargs)
when you need a view (eg. inside urls.py or when trying to generate actual view), use this:
from myapp.views import RobotsTxtView
robots_view = RobotsTxtView.as_view()
in robots.txt file in templates you can actually have static content (or anything you like).
But in general others are right: if you are serving static content, serve it as static content, do not use Django to process this file if you do not need that.
return HttpResponse("any content")
will do the trick rit? OR have I misundertood your question

Categories

Resources