All, something similar seems to have been posted before, however, slim and twig are still very new to me so apologies.
A little back ground, I have an application which posts data to
http://dev.website.com/post.php
Data1="My Date"
Data2="More data"
Eventually it will go in the database, but baby steps, first i just want to know then when i run the post from something like Advanced REST client, it actually shows its been posted.
In old school PHP I can just do this:
<?php
print ("Data1: " . $_POST["Data1"]);
print ("Data2: " . $_POST["Data2"]);
?>
Im trying to do this in slim and twig but I either don't understand it correctly or its not working, could someone tell me what im doing wrong please?
Im using userfrosting for a start which seems to work, i've done the tutorials on the site but they dont really help with this.
in the site index, my routes in index.php look like this:
$app->get('/post.php', function () use ($app) {
$app->render('post.twig');
});
$app->post('/post.php', function () use ($app) {
$backup_post_data1= $app->request->post('data1');
$app->render('post.twig', [
'backup_post_data1' => $backup_post_data1,
]);
});
My twig template post.php (That's what it was called in the old PHP site and is hard coded in the application which makes the post)
{% extends "layouts/layout-simple.twig" %}
{% block page %}
{% set page = page | merge({
"title" : "post page",
"description" : "Accept new data from post."
}) %}
{{ parent() }}
{% endblock %}
{% block content %}
<h1>My data</h1>
<table border="1">
<tbody>
<tr>
<td><strong> Variable</strong></td>
<td><strong> POST DATA </strong></td>
</tr>
<tr>
<td>
Data1
</td>
<td>
{{ backup_post_data1 }}
</td>
</tr>
</tbody>
</table>
{% endblock %}
Thanks in advance
Related
I'm going to try my best to explain this, sorry if it seems confusing.
I have a customized theme. I'm trying to take articles from the blog and put them into 7 separate tagged pages. Essentially to create separate blog templates standard one blog template. The pages bring in a section that paginates by 6.
I'm able to bring the blog articles into the section and paginate, but I'm unable to filter out the unnecessary tags. When I use if/unless statements inside the pagination loop, it just didn't render the unnecessary ones but still paginated based on it, so I had 3 articles on the first page, 2 on the second, and so on. Which make sense why it would do that.
I've tried the 'where' filter on my assign tag and the paginate tag, didn't work. When I asked on the Shopify Slack someone mentioned using the Section Render API with the endpoint '/blogs/{blog_id}/tagged/{tag_id}' but the returns all of the HTML from that page and I don't know how I'd parse and paginate over that. The Section Render API documentation is wanting, to say the least. And my experience with APIs is limited
The closest I've come to answer an is this answer: https://stackoverflow.com/a/60000460/12948634
The problem with the liquid solution is that I can apply a "view" to the tagged posts page but I still have to paginate over it. I still have to use the {% paginate blog.articles %} that apparently doesn't filter. Pagination isn't included in this theme and I'm not quite sure how to add that that to my 'blog-content.liquid' file without disturbing the main tagged page.
Any ideas? Code below:
<div id="article-index-card-section" class="g-flex">
{% assign blog = blogs.{blog_id} %}
{% paginate blog.articles by 6 %}
{% for article in blog.articles %}
<div class="article-index-card g-vertical">
<div style="display: flex; flex-direction: column;">
<img class="article-index-card-image" src="{{ article.image.src | img_url: 'master' }}">
<div class="article-index-card-text">
<h4>{{ article.title }}</h4>
<p class="t-body">{{ article.excerpt }}</p>
</div>
</div>
<div class="article-index-card-btn btn">
Learn More
</div>
</div>
{% endfor %}
<div>
{{ paginate | default_pagination: next: '>', previous: '<' }}
</div>
{% endpaginate %}
</div>
I will probably go the JS route in this case.
Here is what will I probably do, I don't know if it will fit your needs.
Create a separate blog.ajax.liquid template
We will create a new blog template and we will keep only the HTML need for the page to make the request faster and strip unused HTML elements.
{% layout none %}
<div id="article-index-card-section" class="g-flex">
{% paginate blog.articles by 6 %}
{% for article in blog.articles %}
<div class="article-index-card g-vertical">
<div style="display: flex; flex-direction: column;">
<img class="article-index-card-image" src="{{ article.image.src | img_url: 'master' }}">
<div class="article-index-card-text">
<h4>{{ article.title }}</h4>
<p class="t-body">{{ article.excerpt }}</p>
</div>
</div>
<div class="article-index-card-btn btn">
Learn More
</div>
</div>
{% endfor %}
<div>
{{ paginate | default_pagination: next: '>', previous: '<' }}
</div>
{% endpaginate %}
</div>
That's why we add the line {% layout none %} at the top to remove all of the HTML output from the default layout and only output the HTML on the template we create.
Make fetch request to that new template
We make a fetch request to the blog but we must specify that it must used the newly created template and not the default one.
fetch('/blogs/{blog_handle}/tagged/{tag}?view=ajax').then(res => res.text()).then(res => {
document.querySelector('.blog-holder').innerHTML = res;
})
For that we add the ?view=ajax to the end of the request, where the ajax part is the name of the template we created after blog.ajax.liquid.
This request needs to be done for each separate blog, so if you have 10 blogs you will do this request 10 times for each one.
Pagination request
The pagination request will be similar to the request of the blog but you will need to add the page=2 argument to the request where the 2 is the page number.
So something like so:
fetch('/blogs/{blog_id}/tagged/{tag_id}?view=ajax&page=2').then(res => res.text()).then(res => {
document.querySelector('.blog-template').innerHTML = res;
})
Blog main page
I will probably create a static section, where you will be able to select which blog goes on this page.
{%- for block in section.blocks -%}
{%- assign _block = block.settings -%}
{%- assign block_blog = _block.blog -%}
<div class="blog-template" data-handle="{{block_blog}}">
</div><!-- /.blog-template -->
{%- endfor -%}
<script>
document.querySelectorAll('.blog-template').forEach(item => {
const handle = item.getAttribute('data-handle');
// make fetch request and the logic for your tags
})
</script>
{% schema %}
{
"name": "Blogs",
"blocks": [
{
"type": "blog",
"name": "Blog",
"settings": [
{
"type": "blog",
"id": "blog",
"label": "Choose a blog"
}
]
}
]
}
{% endschema %}
This will be my personal choice of direction I go, I don't know if it will fit your needs.
I don't want to use javascript as its probably just a one-off usecase. Here's my code and the problem statement follows.
# Form class
class ManageContainers(FlaskForm):
stop_container = SubmitField('stop')
# HTML Render
{% for i in containers %}
<tbody>
<tr>
<th scope="row">{{ i.short_id }}</th>
<td>{{ i.name }}</td>
<td>{{ i.image.tags }}</td>
<td>{{ i.ports }}</td>
<td>
<form action="#" method="post">
{{ form.stop_container() }}
</form>
</td>
</tr>
</tbody>
{% endfor %}
# Actual app route
#app.route('/list-containers', methods=['POST','GET'])
def index():
containers_list = client.containers.list(all=False)
form = ManageContainers()
if form.is_submitted():
print("stop the container")
delete_container(HOW_TO_GET_THIS?)
return redirect(url_for('index'))
return render_template('index.html', containers=containers_list, form=form)
def delete_container(container_id):
container = client.containers.get(container_id)
container.stop()
container.remove()
I am using docker sdk for python and basically trying to stop / start containers. I am stuck where I want to use that button that says "stop" which will delete the container.
Important - It is actually calling a function like this because I can see "stop the container" in my console. But I don't know how to pass the ID (i.id) of the container while the function is getting called.
Here's a screenshot of what the page actually looks like to save you sometime.
SCREENSHOT
Since you are not taking any user input for any fields, I don't think, it's related to WTForms.
You can try the below steps:
Create a route for stopping the container:
#app.route('/stop-container/<id>', methods=['POST'])
def stop_container(id):
delete_container(id)
return redirect(url_for('index'))
Change your form to:
<form action={{ url_for('stop_container', id=i.short_id) }} method='post'>
{{ form.stop_container() }}
</form>
i have a lot of sub entities, so i want to add/update them reusing one controller, view.
So i need before every form print out list of sub entities already created.
Sub entity name is variable
{% form_theme form 'bootstrap_4_horizontal_layout.html.twig' %}
<table class="table">
{% for entity in parentEntity.{{ subEntityName }} %}
<tr>
<td>{{ entity }}</td>
</tr>
{% endfor %}
</table>
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
But this is not working, also
~ subEntityName ~
Not works
Cant find any suggestion. Is possible to use variables in twig loop definition
Found solution
{% set entities = attribute(parentEntity, entityName) %}
{% for entity in entities %}
<tr>
<td>{{ entity }}</td>
</tr>
{% endfor %}
And this works for me like a charm!
Instead of creating a new variable entities, you can also simply do:
{% for entity in attribute(parentEntity, entityName) %}
And instead of using the attribute function, you can use the bracket notation, at least if parentEntity is an array:
{% for entity in parentEntity[entityName] %}
I was trying to iterate zip list in jinja2 and display values in HTML table but failed at every single try with a blank page, however, I can display values in the Unordered list like as follows.
<ul>
{% for bus, info in jnjbus_info %}
<li>{{bus}}</li>
<li>{{info}}</li>
{% endfor %}
</ul>
This is my flask/function where I passing values to template:
#app.route('/busses')
def busses():
bus_type = ['AC', 'NON-AC', 'Sleeper', 'NON-Sleeper']
bus_info = ['1010', '2020', '3030', '4040']
return render_template('busses.html', jnjbus_info=zip(bus_type, bus_info))
I'm rendering template called busses.html
Here's the script:
<table style="width:100%">
<tr>
<th>Bus Type</th>
<th>Bus Information</th>
</tr>
{% for bus, info in jnjbus_info %}
<tr>
<td>{{bus}}</td>
<td>{{info}}</td>
</tr>
{% endfor %}
</table>
you don't have the
<tbody> </tbody>
tag in your page i added it and it works:
<table style="width:100%">
<tr>
<th>Bus Type</th>
<th>Bus Information</th>
</tr>
<tbody>
{% for bus, info in jnjbus_info %}
<tr>
<td>{{bus}}</td>
<td>{{info}}</td>
</tr>
{% endfor %}
</tbody>
</table>
here is how it looks like :
The code provided in this question is bug-free, however, the problem caused by port=5000 and may be browser cache as well. While tackling with the bug I have written a similar script py and html and screen shot .and ran on port=8888 which works like charm. Note : consider running the same application on different ports and clearing browser cache.
I have this simple form where I need a custom template for a field to render something right next to the <input> tag. Since I won't be needing this anywhere else, I thought I'd put it right in the same template as the form like suggested here:
{% form_theme form _self %}
{% block text_widget %}
{{ block('form_widget_simple') }}
something
{% endblock %}
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
That's pretty much the whole template (to be used with ajax, hence no surrounding markup).
The issue now is, "something" gets rendered right at the beginning of the output where the block text_widget is declared, as would any other block. Its rendered fine in the form next to the <input>:
something
<form name="form" method="post" action="">
<table id="form"><tr>
<td> <label for="form_Search" class="required">Search</label></td>
<td> <input type="text" id="form_Search" name="form[Search]" required="required" autofocus="autofocus" />
something
</td>
</tr><tr style="display: none">
<td colspan="2"><input type="hidden" id="form__token" name="form[_token]" value="dUwdoiz9vo1TJTRjvyUcz9Rwd-D7pTvqUH-R0zCtg28" /></td>
</tr></table>
</form>
This obviously makes inline theming completely unusable, so I think I might be doing something wrong...
How do I get rid of that extra "something" at the beginning?
Having the question already written up and also solved the problem, I might as well answer:
The solution is to derive the template from a dummy base template to swallow any output that's outside of blocks defined in the base template:
{# empty.html.twig #}
{% block content %}
{% endblock %}
And for the actually needed template:
{% extends 'empty.html.twig' %}
{% form_theme form _self %}
{% block text_widget %}
{{ block('form_widget_simple') }}
something
{% endblock %}
{% block content %}
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
{% endblock %}
One probably wouldn't think twice about it when customizing a field in a regular template that already uses inheritance, but this way it feels like a hack...