render cms page within another page - python

Im trying to render a cms page, within another page using a custom cms plugin.
The this is my plugin class:
class PageInDiv(CMSPlugin):
page_div = models.ForeignKey(Page, verbose_name= "page")
def __unicode__(self):
return self.page_div.get_title()
as you can see all it does is link the plugin to a page then on my cms_plugins.py i have
class PageInDivPlugin(CMSPluginBase):
model = PageInDiv
name = _("Page in div")
render_template = "page.html"
admin_preview = False
def render(self, context, instance, placeholder):
temp = loader.get_template(instance.page_div.get_template())
html = temp.render(context)
context.update({
'html': html,
'title':instance.page_div.get_title(),
'placeholder':placeholder,
})
return context
as you can see i pass the html for the provided page to the plugin template, then the plugin template is rendered within the page thats hosting the plugin.
The problem i am having is that the placeholder content from the page thats selected via foreignkey is not being rendered ( displayed ).
So my question is, is there a way to render a pages placeholders programatically ?

Just for a moment ignoring the idea of creating a custom plugin in order to do what you describe (ie, render a page's placeholders programatically), the following might be a viable alternative, depending on what exactly you are trying to achieve...
You should be able, just in the template for your "outer" cms page (ie, the page within which you want to display the contents of another cms page), to get access to the current page like this:
{{ request.current_page }}
This is by virtue of the cms page middleware. So taking that a step further, you should be able to access the page's placeholders like this:
{% for placeholder in request.current_page.placeholders %}
{{ placeholder.render }}
{% endfor %}
That's one way you could go about rendering a page's placeholders "inside" another page.

I needed to render another page from within the template which could be accomplished with:
#register.simple_tag(takes_context=True)
def render_page(context, page, default="base.html"):
if not page:
return loader.get_template(default).render(context)
new_context = copy(context)
new_context['request'] = copy(context['request'])
new_context['request'].current_page = page
new_context['current_page'] = page
new_context['has_change_permissions'] = page.has_change_permission(context['request'])
new_context['has_view_permissions'] = page.has_view_permission(context['request'])
if not new_context['has_view_permissions']:
return loader.get_template(default).render(context)
return loader.get_template(page.get_template()).render(new_context)

Related

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.

Globally getting context in Wagtail site

I am working on a Wagtail project consisting of a few semi-static pages (homepage, about, etc.) and a blog. In the homepage, I wanted to list the latest blog entries, which I could do adding the following code to the HomePage model:
def blog_posts(self):
# Get list of live blog pages that are descendants of this page
posts = BlogPost.objects.live().order_by('-date_published')[:4]
return posts
def get_context(self, request):
context = super(HomePage, self).get_context(request)
context['posts'] = self.blog_posts()
return context
However, I would also like to add the last 3 entries in the footer, which is a common element of all the pages in the site. I'm not sure of what is the best way to do this — surely I could add similar code to all the models, but maybe there's a way to extend the Page class as a whole or somehow add "global" context? What is the best approach to do this?
This sounds like a good case for a custom template tag.
A good place for this would be in blog/templatetags/blog_tags.py:
import datetime
from django import template
from blog.models import BlogPost
register = template.Library()
#register.inclusion_tag('blog/includes/blog_posts.html', takes_context=True)
def latest_blog_posts(context):
""" Get list of live blog pages that are descendants of this page """
page = context['page']
posts = BlogPost.objects.descendant_of(page).live().public().order_by('-date_published')[:4]
return {'posts': posts}
You will need to add a partial template for this, at blog/templates/blog/includes/blog_posts.html. And then in each page template that must include this, include at the top:
{% load blog_tags %}
and in the desired location:
{% latest_blog_posts %}
I note that your code comment indicates you want descendants of the given page, but your code doesn't do that. I have included this in my example. Also, I have used an inclusion tag, so that you do not have to repeat the HTML for the blog listing on each page template that uses this custom template tag.

Django Pagination Current page in View.py

I am using Pagination in Django but using AJAX so I have to send all variables values from view to AJAX call. But For Current page there is no builtin variable available ?. As I saw official documentation. So how to Send this data already calculated in view.py ?
<span class="current">
Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
</span>
Link referenceFollowing this example
The only sensible way to do pagination/ajax/django template tags, would be to generate the entire table + current page data + table navigation etc. in the django view. I.e. move all the variables for the table from your containing page to the view for the table.
Probably a better solution is to find yourself a javascript table component and have django serve it data...
Instead of creating two different views, you can deliver the paginated content from the same view by adding a GET parameter to the url, to check for the page number and sending the ajax request to the same view. This way, it'll be easier to manage one view instead of two for the same content. And if your view does much more than generating the particular content, as you are using ajax, you can easily split the view such that one view delivers only the related content.
For example, if the url of your view is \url-to-somepage
you can send the ajax request to \url-to-somepage?page=2
Then in your template file, say template.html, include another template, say __sub_template.html for the content which will be paginated. Like,
<div>
<!--
rest of the page
-->
{% include 'templates\__sub_template.html' %}
</div>
Then in your view,
.def your_view(request):
"""
Your code here
"""
paginator = Paginator(contacts, number)
page = request.GET.get('page')
try:
result_list = paginator.page(page)
except PageNotAnInteger:
result_list = paginator.page(1)
except EmptyPage:
result_list = []
if page:
return render(request, '__sub_template.html', {'contacts': result_list})
else:
return render(request, 'template.html', {'contacts': result_list})
Use Django endless pagination http://django-endless-pagination.readthedocs.io/en/latest/twitter_pagination.html#pagination-on-scroll

How to Embed a Template Variable Inside a Hyperlink - Django Template

I am brand new to web development, Django, python, html, etc. I have a basic Django app that displays a list of publication titles that have been entered into the database. This works fine.
I now want to make it so that each publication title is a link that - when clicked on - renders another template with the details of the publication that was clicked. So far, I know how to get the publication link to render a template, but I am trying to figure out how to pass in the publication title to the hyperlink so that the data that is rendered in the details template will be specific to the title that was chosen.
Here is what I have in my publication template which displays all the publications (it is incorrect, but hopefully it clarifies what I am trying to do):
<html>
<head><title>Publications</title></head>
<body>
<h1>Publications</h1>
<ul>
{% for publication in publication_list %}
<li><strong>{{ publication.title}}</strong></li>
{% endfor %}
</ul>
</body>
</html>
For the sake of context, the url pattern that handles this is:
url(r'^(?P<detail_type>\w+)/(?P<link_item>\w+)/detail$', get_details)
And the view function is:
// note: I may have some of the logic/syntax wrong here, but this is the basic idea
def get_details(request, detail_type=None, link_item=None):
if detail_type == "publications":
publication = Publication.objects.filter(title__iexact=link_item)
return render(request, 'publication_detail.html', {'detail_type' : detail_type, 'publication' : publication})
elif ....
Like I said, I am very much a beginner so if I am approaching this in wrong way, any suggestions or resources are appreciated. Thanks.
If you use named url patterns you can easily do this with the url template tag.
urls.py
url(r'^(?P<detail_type>\w+)/(?P<link_item>\w+)/detail$', get_details, name='details')
template
{% url 'details' 'publications' publication.title %}
I hope you know about SlugField too, it is much better for urls than a normal CharField.
An alternative:
urls.py
url(r'^(?P<detail_type>\w+)/(?P<pk>\w+)/detail$', get_details, name='details')
template
{% url 'details' 'publications' publication.pk %}
views.py
def get_details(request, detail_type=None, pk=None):
if detail_type == "publications":
publication = Publication.objects.get(pk=pk)
return render(request, 'publication_detail.html', {'detail_type' : detail_type, 'publication' : publication})
elif ....
This uses the primary key of the entry instead of the title. If you want to have a url with the title in it you will want to add and use a SlugField on your model.
This looks pretty good to me, although you may want to use get as opposed to filter in your view function if all the publication titles are unique and you want to pass an instance of Publication rather than a queryset (containing one item) into the detail template. This would throw an error of there were 0 or >1 matches, but it sounds like that's probably the behavior you'd want
However, I'm not sure what it is that you're missing here. What does publication_detail.html look like? You should have essentially everything you need in the above code to render the details, assuming they're all contained in the relevant Publication instance.

Render django application within TextField

I am creating an application to display articles. In my model, I have a TextField that will contain the content of the article.
Now I would like to be able to render another application within my article. Let say I have a poll application and I would like to display a poll in the middle of the article. How can I do that ?
I tried by putting a {% render_poll 42 %} within the post but, as expected, it just display that within the generated page.
Should I create some kind of tag (like let say [poll=42]) and parse it before displaying the rendered html page ? (I use the markdown library, maybe I could extend it.) How can I do that to stay in a nice "django friendly" way ? I want that, when in the admin panel, I can easily insert poll (or other apps) within an article.
You could compile the TextField string as a template. Ie.:
from django.db import models
from django.template import Template, Context
class YourModel(models.Model):
body = models.TextField()
def render_body(self, context=None):
template = Template(self.body)
context = context or {}
context['object'] = self
return template.render(Context(context))
Then in the actual template, you could use {{ your_model.render_body }} rather than {{ your_model.body }}.

Categories

Resources