i've finished developing a website, it's working fine however i am trying to optimize my website by adding dynamic templates, and want to make sure that if it can be done on pyramid python.
for example, in my jinja template i have the following:
{% block article_detail %}
<form action="{{request.route_url('Sports_News_Action',action=action)}}" method="post" class="form">
{% if action =='edit' %}
{{ form.id() }}
example in my controller:
#view_config(route_name='Sports_News_Action', match_param='action=create',
renderer='StarAdmin:templates/edit_sports.jinja2')
def general_create(request):
entry = SportNews()
the request route will have to match the one in my controller in order to run the function. what i want to do is how do i replace the one in jinja with a dynamic variable, to use the one jinja template lets say for different views/controllers with different route_names.
I think in your situation the simplest solution is to leave action undefined and the browser will submit the request to the current url. You only need to specify action if you want to submit the form to a different url than the current. That being said, you can use lots of different options in pyramid to generate a url as well. For example, request.url is the current url, or request.matched_route.name is the name of the current matched route.
Related
I have page_obj in a template which was returned from a ListView view. Now, I wanted to create links to several pages before and after the current page. Therefore, I wanted to slice page_obj.paginator.page_range this way: page_obj.paginator.page_range[page_obj.number-3:page_obj.number+4]. This works in django shell but for some reason when I did it a template, there is a Template Syntax Error, Could not parse the remainder: '[page_obj.number-3:page_obj.number+4]' from 'page_obj.paginator.page_range[page_obj.number-3:page_obj.number+4]'. Is there a workaround for this case?
P.S. I know I can do it using the whole page_obj.paginator.page_range and then using if statements to check if a page is in the required range, but I thought it's a bit inefficient.
As stated in my comment Django Template Language does not include normal python syntax. The reason for this is Django aims to separate the logic and design of the website. If there is need to perform somewhat complicated logic you either need to use template tags or filters.
For your need either an inclusion tag would work or a simple filter that would take the page_range and return a sliced version of it. A template filter here would not be very useful considering we can only pass one argument to it, meaning it would not be very customizable. Let's assume that your pagination would look very similar or perhaps you would pass the template you use to the tag.
Firstly you need to create a templatetags sub-package in your app and then in that you would add files (e.g. pagination_tags.py) which would contain your tags. The layout would be something like:
your_app/
__init__.py
models.py
templatetags/
__init__.py
pagination_tags.py
views.py
Now in your file pagination_tags.py you want to write your tags. As a reference you may read the howto on Custom template tags and filters in the documentation.
Firstly we declare register which is an instance of template.Library. After which we would write our template tags / filters. We will use an inclusion_tag:
from django import template
register = template.Library()
#register.inclusion_tag('pagination_tag.html')
def show_pagination(page_obj, **kwargs):
left = kwargs.get('left', 3)
right = kwargs.get('right', 4)
pages_iter = page_obj.paginator.page_range[page_obj.number - left:page_obj.number + right]
template = kwargs.get('template', 'default_pagination_template.html')
return {**kwargs, 'page_obj': page_obj, 'pages_iter': pages_iter, 'template': template}
Now we will have a simple template named pagination_tag.html that will simply extend the template name either passed as a keyword argument or default_pagination_template.html:
{% extends template %}
Now in default_pagination_template.html or any other template we can use all the variables in the dictionary that our function show_pagination returns:
{% for page_num in pages_iter %}
Display page links here, etc.
{% endfor %}
You can modify this implementation as per your needs. I will also leave the design and implementation of default_pagination_template.html upto you.
Now in your template where you want to use this, first we will load these tags. Then we will use them:
{% load pagination_tags %}
...
{% show_pagination page_obj left=5 right=6 template="some_custom_template.html" %}
I'm working in a Flask app, and I'm trying to set it up to create dynamic webpages based on the data in the SQL database. For example, if we scrape data about a certain criminal, I want Flask to route my requests such that I can type:
myflaskapp.com/criminal/[criminal's name]/
and be taken to a page specifically for that criminal. This is the relevant portion of the views.py that I've already written:
#app.route('/criminal/<first_name>')
def criminal(first_name):
criminal = Individual_Criminal.query.filter_by(first_name=first_name).first()
return render_template('user.html',
criminal=criminal)
Now, when I call the Individual_Criminal.query.filter_by(first_name=first_name).first() in a Python shell, it returns as expected:
However, when I set up my Flask server, and do (what I believe to be) the exact same command query, it just gives me a blank page (with my navbar and stuff extended from the base html.)
The HTML for the page I'm trying to call is simple:
<!-- extend base layout -->
{% extends "base.html" %}
{% block content %}
<h1>{{ criminal.full_name }}</h1>
<hr>
{% endblock %}
As you can see, it should be returning the particular criminal's full name (in this case, Bryan Sanford). Instead, it returns this:
Instead of the requested criminal's full name, the way that the HTML specifies.
Where am I going wrong here? My thinking is that if I can do that exact query that's in my views.py file and have it return the correct value, it should work the same in my Flask app. However, clearly there are some wires crossed somewhere. Can any of you wonderful people help me untangle this?
edit: as discussed in one of the answers comments, when I change views.py to include print(criminal.first_name), it fails, throwing AttributeError: 'NoneType' object has no attribute 'first_name'. Even though the exact same line works exactly as expected in the actual database!
Your routing seems to be wrong?
This is not the same
myflaskapp.com/[criminal's name]/
as
#app.route('/criminal/<first_name>')
Try
myflaskapp.com/criminal/[criminal's name]/
Using frozen flask to make my website static, I have the following problem.
While all of my pages are being built (file//c:/correctpath/build/2014/page-title/index.html) the links to the pages are file:///c:/2014/page-title/.
Is there something I have missed?
EDIT:
In my template I have something like
{% for page in pages %}
{{ page.title }}
{% endfor %}
where .url() is a method on the page object:
return url_for('article', name=self.name, **kwargs)
url_for produces absolute paths (e. g. /2014/page-title) - when you open up your files in the browser it follows the rules regarding relative URL resolution and strips the extra file contents. If you just want to view your files as they will be seen on the server, Flask-Frozen has a run method that will let you preview your site after generating it.
Alternately, you can set FREEZER_RELATIVE_URLS to True to have Flask-Frozen generate links with index.html in them explicitly.
Rather than setting FREEZER_RELATIVE_URLS = True, with resulting URLs ending on index.html, you can also set FREEZER_BASE_URL to <http://your.website/subdir>.
For example in Django if I have a url named 'home' then I can put {% url home %} in the template and it will navigate to that url. I couldn't find anything specific in the Pyramid docs so I am looking to tou Stack Overflow.
Thanks
The brackets depend on the templating engine you are using, but request.route_url('home') is the Python code you need inside.
For example, in your desired template file:
jinja2--> {{ request.route_url('home') }}
mako/chameleon--> ${ request.route_url('home') }
If your route definition includes pattern matching, such as config.add_route('sometestpage', '/test/{pagename}'), then you would do request.route_url('sometestpage', pagename='myfavoritepage')
I am trying to implement django-facebookconnect, for I need to check if a user logged in via Facebook or a regular user.
At the template, I can check if user logged in via facebook by checking request.facebook.uid
such as:
{% if is_facebook %}
{% show_facebook_photo user %}
{% endif %}
For this, I need to pass is_facebook': request.facebook.uid to the template and I will be using this in everywhere thus I want tried to apply it to an existing template context processor and call the snipplet above at the base.html, and it works fine for Foo objects:
def global_variables(request):
from django.conf import settings
from myproject.myapp.models import Foo
return {'is_facebook': request.facebook.uid,'foo_list': Foo.objects.all()}
I can list Foo objects at any view without any issue however it fails for this new is_facebook, it simply returns nothing.
If I pass 'is_facebook': request.facebook.uid in every single view , it works but I need this globally for any view rendering.
If you have access via the request object, why do you need to add a special is_facebook boolean at all? Just enable the built-in django.core.context_processors.request and this will ensure that request is present in all templates, then you can do this:
{% if request.facebook.uid %}
It could be a timing issue. Make sure that the Common middleware comes before the facebook middleware in your settings file. You can probably debug and see when the facebook middleware is modifying the request and when your context processor is invoked. That may give you some clue as to why this is happening. But, as Daniel said, you can always just use the request object in your templates.