FlaskWTF same form on every view / page - forms

in my Flask Project i have configured a basepage.html Jinja template every other page inherits from.
In this basepage.html i want to have a Search bar at the top, so that it also appears at every page inheriting from it.
The input from this search form (is a form even the best way to do it?) should be processed
by the routing function search() I defined as follows:
views.py
#app.route('/')
#app.route('/dashboard')
def dashboard():
return render_template('Dashboard.html') #Dashboard.html inherits from basepage.html
#app.route('/search', methods=['GET' ,'POST'])
def search():
search_query = #input from search-bar
result = #get data matching search_query from database
return render_template('Search.html', results = results) #Search.html extends basepage.html
forms.py excerpt:
class Search(FlaskForm):
search_query = StringField('Search for ...')
submit = SubmitField('Search')
Is there a way i can have my Search form on every page, so when i enter my query in the bar at the top of the Dashboard form and press enter the search_query gets processed by the search() view?

Just create your searchbar template code in a partial file located at /templates/includes/my_searchbar.html or whatever you want to name it and then in your base template just place an includes directive wherever you want the search to render in, something like:
{% include 'includes/my_searchbar.html' %}
If the searchbar is included in base and all your other templates inherit from base, then search will be included on all pages.
All of your routes will also need to have the Search() form class included so they have access to the form, so you will need to modify your routes something like:
from app.forms import Search #if you defined Search in /app/forms.py
#app.route('/dashboard')
def dashboard():
search_form = Search() #initialize an instance of the form
return render_template('Dashboard.html', search_form=search_form)
Then you can use search_form in your includes/my_searchbar.html partial to render the form. Maybe something like:
<form class="form" method="post" role="form">
{{ search_form.hidden_tag() }}
{{ search_form.search_query }}
{{ search_form.submit }}
</form>

Related

Wagtail: Rendering tags from Fieldblock

I am really stuck on this: (sorry, newbie problems)
Following the method exposed in this post I need to render the tags in a page, but I am not able to get the tag values through the #property
The code is as follow, the models:
class TagsBlock(blocks.FieldBlock):
"""
Basic Stream Block that will use the Wagtail tags system.
Stores the tags as simple strings only.
"""
def __init__(self, required=False, help_text=None, **kwargs):
# note - required=False is important if you are adding this tag to an existing streamfield
self.field = forms.CharField(widget=AdminTagWidget, required=False)
super().__init__(**kwargs)
class ServicesPage(Page):
services = StreamField([
('services',blocks.StructBlock([
('entries',PortfolioBlock()),
('tags',TagsBlock(required=False)),
]))], null=True, blank=True)
#property
def get_tags(self):
"""
Helpful property to pull out the tags saved inside the struct value
Important: makes some hard assumptions about the names & structure
Does not get the id of the tag, only the strings as a list
"""
tags_all = [block.value.entries.get('tags', '').split(',') for block in self]
tags = list(chain.from_iterable(tags_all))
return tags
content_panels = Page.content_panels + [
StreamFieldPanel('services'),
]
Then in the template im just doing:
<div class="row-4">
{% for tag in page.services.get_tags %}
{{tag}}
{% endfor %}
</div>
However, I can't get any result. I have really tried everything, but I can't figure how to call the property to give me the list of values.
Thank you very much in advance for your time,
Francisco
In your template, the line
{% for tag in page.services.get_tags %}
would be trying to access a property named get_tags on the 'services' field of the page. However, get_tags isn't defined there - it's defined as a property of the page object - so this line should be
{% for tag in page.get_tags %}
Secondly, in the line
tags_all = [block.value.entries.get('tags', '').split(',') for block in self]
you're intending to loop over all the items in the StreamField, but the self in for block in self refers to the page object. This should be for block in self.services.
Finally, in the same line, block.value will give you the value of each block, which in this case will be a dictionary of two items, entries and tags. If you wanted to access entries (the PortfolioBlock), you would write block.value['entries'] or block.value.get('entries') rather than block.value.entries - but really you don't want that, you want to access the tags item instead - so block.value.entries.get('tags', '').split(',') should be block.value.get('tags', '').split(',').

How to access a method and pass an argument within the template?

In my template I want check whether an entity has a relation to another one. Meaning one object is in an attached Object Storage of another one.
In the controller I can simply call:
if ($product->getCategory()->offsetExists($category) {
print 'In category ' . $category->getName();
}
But I can't figure out the correct syntax in the template. I tried those without luck (both evaluate to true everytime):
<f:if condition="{product.category.offsetExists(category)}">true</f:if>
<f:if condition="{product.category.offsetExists({category})}">true</f:if>
Is this even possible within the template?
You can only access properties via Getter from Fluid with no parameters, but you can implement an own ViewHelper to check that. As parameters you can use your Product and the Category. Then you can call your ViewHelper from Fluid this way:
<vh:checkOffset product="{product}" category="{category}" />
or inline
{vh:checkOffset(product: product, category: category)}
Within your ViewHelper you can check this in the way you've done it in your Controller:
public function render($product, $category){
return ($product->getCategory()->offsetExists($category));
}
Additionally to sretuer's answer, I'll only mention that you can create VH which will display block conditionally like:
File typo3conf/ext/your_ext/ViewHelpers/CheckOffsetViewHelper.php
<?php
namespace VENDORNAME\YourExt\ViewHelpers;
class CheckOffsetViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper {
public function render() {
return ($product->getCategory()->offsetExists($category))
? $this->renderChildren()
: '';
}
}
?>
So you can use it in the view:
{namespace vh=VENDORNAME\YourExt\ViewHelpers}
<vh:checkOffset product="{product}" category="{category}" >
Display this only if product is in category
</vh:checkOffset>
Of course you need to fix VENDORNAME and YourExt according to your extension, can be found at the beginning of every controller, model, repository etc.
You may consider https://fluidtypo3.org/viewhelpers/vhs/master/Condition/Iterator/ContainsViewHelper.html which is designed for creating conditions in Fluid that check if an array or Iterator contains another object and works exactly like f:if regarding then and else arguments and f:then and f:else child nodes.

Play framework dynamic template include

I have a template that has to include another template based on the file name that comes from the database. For example, here is a template that takes a String that contains the name of the template file that will be included in another template.
#(sourceCodeFileName: Option[String])
#{sourceCodeFileName match {
case Some(sourceCode) => {
#sourcecode.sourceCodeFileName + "scala.html"
}
}}
Where sourcecode is the package where the actual template resides. For example., if the String parameter to the above template is given as myview, then I want to include myview.scala.html. Is there a way to do this in Play framework?
To inject HTML from a static file to a scala template, you can define a function in your template:
#import scala.io.Source
#injectHtmlFromFile(sourceCodeFilename: String) = { #{
Html(Source.fromFile("static/html/" + sourceCodeFilename + ".html").mkString)
}}
…and call it later in the template this way:
#injectHtmlFromFile(sourceCode.sourceCodeFileName)
Side note
I'm not sure I quite understand the question – I've answered the OP's comment and the same question posted by him on Google Groups.
A Play scala template is a function returning Html. You should obtain the template object in the controller and pass it to the template. But in simple cases it's just easier to pass the rendered Html:
Your template would then look like this:
#(content: Option[Html])
#content
and the controller:
object Application extends Controller {
def index = Action {
val sourceCodeFileName= ...
Ok(Some(Class.forName("views.html."+sourceCodeFileName)
.getConstructor().newInstance().asInstanceOf[() => play.api.templates.Html]()
))
}
}

Pyrocms tag as parameter in another tag

I tried to use {{ page:slug }} as a parameter in my page to get the blog articles from the category of the same name. For example:
Pagename = About me
Slug = about-me
Then create a category with the same name and slugname in Blog with associated articles. Now in pagelayouts I thought I could create the following, but it doesn't seem to work. Does anyone know why not?
{{ blog:posts order-by="created_on" dir="asc" category="{{ page:slug }}" }}
<section class="title">
<h4>
{{ title }}
</h4>
</section>
<section class="item">
<p>{{ intro }}</p>
<p>Read more..</p>
</section>
{{ /blog:posts }}
Solved
I found the answer by asking it face to face to another developer. Since this is a templating language, it doesn't support functionality. It just reads pre-made variables. So I will have to solve this problem by creating another method in pages/plugins.php.
You don't need to try and embed a tag in a string, just pass the tag straight to the attribute.
{{ blog:posts order-by="created_on" dir="asc" category="{{ page:slug }}" }}
Should be:
{{ blog:posts order-by="created_on" dir="asc" category=page:slug }}
Easier than you thought ey?
This is how I solved it using PHP. The below edit checks if the page parameter from the {{ blog:posts }} tag is set. When it is, it grabs the last segment and uses it as category filter in the database query to retreive only those posts:
In system/cms/modules/blog/plugin.php look for the 'posts' function and add a parameter:
$page = $this->attribute('page');
Then use the following statement to check if the parameter has been set and then add a 'where' statement:
if($page) //check if page is set
{
$segment = end($this->uri->segment_array()); //get the last segment from the url
$this->db->where('blog_categories.slug', $segment); //use the segment as filter
}
Now you can create a page containing blog posts from which the categories refer to its pagename like for example: www.website.com/pagename/subpagename/subsubpagename/awesome then use this as pagelayout and it will load a list of blogposts that have 'awesome' as category:
<h3>{{ page:title }}</h3>
{{ blog:posts order-by="created_on" dir="asc" page="true" }}
<h4>{{ title }}</h4>
<p>
{{ intro }}</p>
<p>
Read more..</p>
{{ /blog:posts }}
Instead of using tags i have found a simple solution to avoid tags as much as we can. Here is it.
Instead of using tags call a view in plugin and pass the third parameter as TRUE so that it return string instead of loading view than do any kind of looping and conditional checking in the view as usuall as you do with php o course. No need to meet tags there. After that in plugin where you are calling this view simply return a single variable and use your variable in tags in the page to display content of view.
Here is an example
class Plugin_Home extends Plugin
{
function test()
{
$this->load->model('test/test_m');
$data['test'] = $this->test_m->index();
return $this->load->view('test/test_view',$data , TRUE);
}
}
And in the page you can call it like this
{{ Home:test }}
And get rid of tags for conditioning and looping

Scala Lift - Dynamic page chrome

I have a page which is passed an id from which the content is determined. What I'm looking to do is dynamically replace the pages "chrome" depending on the content.
So if I have a db record "Book", I'd like to display the Book chrome in templates-hidden.
Thanks for any help, much appreciated :)
You can define a snippet that selects the template you want and pass the xhtml NodeSeq containing the template selection to it:
<lift:TemplateSnippet.dynamicTemplatePicking>
<lift:surround dynamic:template="" at="content">
<h2>some heading</h2>
<p>some text</p>
</lift:surround>
</lift:TemplateSnippet.dynamicTemplatePicking>
And the snippet code:
class TemplateSnippet {
def dynamicTemplatePicking(xhtml :NodeSeq) :NodeSeq = {
bind("dynamic", xhtml, AttrBindParam("template", Text("default"), "with"))
}
}
By changing the "default" in Text("default") inside the snippet you can choose another template depending on your needs. Maybee you want to do something like def choose (record: Record) = record match { case b: Book => "booktemplate"} and so on...
Source: Mads Hartmann's posting