This question already has an answer here:
How let Twig write the HTML output to a file, instead to a browser?
(1 answer)
Closed 1 year ago.
In this code below I have just generated in the browser a .xml page that shows a specific sitemap of the distributor route.
I just want to save this generated .xml in a file (in /public/sitemap folder).
what I have, and what I WANT TO USE, are only this two (like the render at the bottom of the Controller):
the urls array (see: inside the foreach)
the template of the xml file
I have already found a possible solution but is not pratical, and is not what I want. (Create new xml file and save in system using symfony2.8)
Controller:
/**
* #Route("/sitemap/sitemap.xml", name="distributor_sitemap", defaults={"_format"="xml"})
*/
public function getSitemap(Request $request) : Response
{
$urls = [];
$hostname = $request->getSchemeAndHttpHost();
// return an array of routes
$routes = $this->sitemapService->getThreeRoutesByIndexes('/distributor/');
foreach ($routes as $route){
$urls[] = array('loc' => $this->generateUrl($route));
}
// save locally the file
// -----------------------------
// ----- add the code HERE -----
// -----------------------------
// return response in XML format
$response = new Response(
$this->renderView('sitemap/sitemap.html.twig', array(
'urls' => $urls,
'hostname' => $hostname
))
);
$response->headers->set('Content-type', 'text/xml');
return $response;
}
Template:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
{% for url in urls %}
<url>{# check if hostname is not alreay in url#}
<loc>{%if url.loc|replace({hostname:''}) == url.loc%}{{hostname}}{{url.loc}}{%else%}{{url.loc}}{%endif%}</loc>
{% if url.lastmod is defined %}
<lastmod>{{url.lastmod}}</lastmod>
{% endif %}
{% if url.changefreq is defined %}
<changefreq>{{url.changefreq}}</changefreq>
{% endif %}
{% if url.priority is defined %}
<priority>{{url.priority}}</priority>
{% endif %}
{% if url.image is defined and url.image is not empty %}
<image:image>
<image:loc>{%if url.image.loc|replace({hostname:''}) == url.image.loc%}{{hostname}}{{url.image.loc}}{%else%}{{url.image.loc}}{%endif%}</image:loc>
<image:title>{{ url.image.title }}</image:title>
</image:image>
{% endif %}
</url>
{% endfor %}
The Browser result
So again the final result is to generate a .xml file in the /public/sitemap folder, and this file must contain the urls array informations disposed by the template, as it is showed in the browser. ( all the code that to this should be added in the Controller near the ---- add the code HERE ----)
Assign the content of your render template to a var, then write it in the file you want.
/**
* #Route("/sitemap/sitemap.xml", name="distributor_sitemap", defaults={"_format"="xml"})
*/
public function getSitemap(Request $request) : Response
{
$urls = [];
$hostname = $request->getSchemeAndHttpHost();
// return an array of routes
$routes = $this->sitemapService->getThreeRoutesByIndexes('/distributor/');
foreach ($routes as $route){
$urls[] = array('loc' => $this->generateUrl($route));
}
// save locally the file
$xmlContent = $this->renderView('sitemap/sitemap.html.twig', array(
'urls' => $urls,
'hostname' => $hostname
));
// Assuming the folder sitemap exists in `public`
$path = $this->getParameter('kernel.project_dir') . '/public/sitemap/sitemap.xml';
$fileSystem = new Filesystem();
$fileSystem->dumpFile($path, $xmlContent);
// -----------------------------
// ----- add the code HERE -----
// -----------------------------
// return response in XML format
$response = new Response($xmlContent);
$response->headers->set('Content-type', 'text/xml');
return $response;
}
Is there a possibility to display file in twig template when the the file is not stored inside public directory? Like call controller which would return binary response for requested file?
If you want to embed a controller response into a twig template you can use the render function.
{{ render(path('latest_articles', {max: 3})) }}
or
{{ render(controller('App\\Controller\\BlogController::recentArticles', {max: 3})) }}
Ref: https://symfony.com/doc/current/templates.html#embedding-controllers
I need to make a same-page scroll design with links on a sidebar that scrollto anchors for different sections within the same page.
I am trying to use the cmsplugin-sections and run into a 'NoneType' object is not iterable error when trying to add a section container. Someone opened an identical issue too on the same subject a few days ago. Below the trace:
Any help most welcome as I am new to django-cms. MAybe another plugin with the same functionality? Basically I need an custom text plugin for each section which has a title field and a display menu title too.
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/en/?edit
Django Version: 1.8.9
Python Version: 2.7.9
Installed Applications:
('djangocms_admin_style',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.admin',
'django.contrib.sites',
'django.contrib.sitemaps',
'django.contrib.staticfiles',
'django.contrib.messages',
'cms',
'menus',
'sekizai',
'treebeard',
'djangocms_text_ckeditor',
'djangocms_style',
'djangocms_column',
'djangocms_file',
'djangocms_googlemap',
'djangocms_inherit',
'djangocms_link',
'djangocms_picture',
'djangocms_teaser',
'djangocms_video',
'reversion',
'grounded_change',
'cmsplugin_sections')
Installed Middleware:
('cms.middleware.utils.ApphookReloadMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'cms.middleware.user.CurrentUserMiddleware',
'cms.middleware.page.CurrentPageMiddleware',
'cms.middleware.toolbar.ToolbarMiddleware',
'cms.middleware.language.LanguageCookieMiddleware')
Template error:
In template /Users/user/templates/fullwidth.html, error at line 7
'NoneType' object is not iterable
1 : {% extends "base.html" %}
2 : {% load cms_tags %}
3 :
4 : {% block title %}{% page_attribute "page_title" %}{% endblock title %}
5 :
6 : {% block content %}
7 : {% placeholder "content" %}
8 : {% endblock content %}
9 :
Traceback:
File "/Users/user/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
response = response.render() File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/response.py" in render
self.content = self.rendered_content File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/response.py" in rendered_content
content = template.render(context, self._request) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/backends/django.py" in render
return self.template.render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in render
return self._render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in _render
return self.nodelist.render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in render
bit = self.render_node(node, context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/debug.py" in render_node
return node.render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/loader_tags.py" in render
return compiled_parent._render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in _render
return self.nodelist.render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in render
bit = self.render_node(node, context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/debug.py" in render_node
return node.render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/classytags/core.py" in render
return self.render_tag(context, **kwargs) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/sekizai/templatetags/sekizai_tags.py" in render_tag
rendered_contents = nodelist.render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in render
bit = self.render_node(node, context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/debug.py" in render_node
return node.render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/classytags/core.py" in render
return self.render_tag(context, **kwargs) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/cms/templatetags/cms_tags.py" in render_tag
rendered_contents = nodelist.render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in render
bit = self.render_node(node, context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/debug.py" in render_node
return node.render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/loader_tags.py" in render
result = block.nodelist.render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/base.py" in render
bit = self.render_node(node, context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/django/template/debug.py" in render_node
return node.render(context) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/classytags/core.py" in render
return self.render_tag(context, **kwargs) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/cms/templatetags/cms_tags.py" in render_tag
content = get_placeholder_content(context, request, page, name, inherit, nodelist) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/cms/templatetags/cms_tags.py" in get_placeholder_content
content = render_placeholder(placeholder, context, name) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/cms/plugin_rendering.py" in render_placeholder
content.extend(render_plugins(plugins, context, placeholder, processors)) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/cms/plugin_rendering.py" in render_plugins
out.append(plugin.render_plugin(context, placeholder, processors=processors)) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/cms/models/pluginmodel.py" in render_plugin
context = plugin.render(context, instance, placeholder_slot) File "/Users/user/.virtualenvs/gc/lib/python2.7/site-packages/cmsplugin_sections/cms_plugins.py" in render
for child in instance.child_plugin_instances:
Exception Type: TypeError at /en/
Exception Value: 'NoneType' object is not iterable
I managed to overcome this by:
Editing the cms_plugins.py file, basically adding an if statement before the for loops to check whether there is anything inside the section container to iterate
Running python manage.py migrate to create the tables (not mentioned in the installation instructions)
When I try to create a path variable:
{% block jquery %}
<script>var url = "{{ path('bundles/foo/ajax/widb-get-data.php') }}";</script>
{% endblock %}
I get the following error:
An exception has been thrown during the rendering of a template ("Unable to generate a URL for the named route "FooBundle:Default:myfile.php" as such route does not exist.")
I recommend you to use FOSJsRoutingBundle
you can then do :
<script>
var url = Routing.generate('route_id', /* your params */);
</script>
Note that you are calling a route not a file
In order to call a route declared in your controller by routing.generate, be sure to expose it before :
/**
* #Route("/foo/{id}/bar", name="my_route_to_expose", options={"expose"=true})
*/
public function exposedAction($foo)
If I run the controller "normally" the (Booking) Controller throws an exception I get my custom 500 error page.
If I render the controller inside another template, like so:
{% render "BookingBundle:Booking:list" %}
then I don't get anything just blank output.
Is there a way to get the error page to display here with out doing a try catch inside the controller?
When you use the render tag, you can specify some options as the third argument:
ignore_errors default FALSE in debug mode and TRUE otherwise
alt an alternative controller to execute in case of an error
The debug mode is activated by passing true as the value of the second kernel's constructor argument. You can see it in the front controller classes:
$kernel = new AppKernel('dev', true);
If you don't want to ignore errors, even in non-debug mode, you can do:
{% render 'BookingBundle:Booking:list' with {}, {'ignore_errors':false} %}