Loading page in Django based on its ID - python

I've been working with Django in order to make my portfolio and I've managed to make a simple page manager. The problem is, it does not work how I want it to work:
I create the page.
It loads the content I gave it.
With jQuery, I load only that content (as formatted HTML).
It shows itself without reloading or moving to another page.
The problem is with the last two steps, I can't get the view and template to only load one.
Views.py:
def paginas(request, title):
get_page = Page.objects.all() # I can't think of a way to make a proper filter
return render_to_response('template.html', {'get_page': get_page}, context_instance=RequestContext(request), mimetype="text/html")
Template.html:
{% if get_page %}
{% for page in get_page %}
{{ page.content|safe }}
<p>Full path is {{ request.get_full_path }} and page id is {{ page.id }}</p>
{% endfor %}
{% else %}
<p>Nothing.</p>
{% endif %}
I know I should filter it, but I don't know how.
I appreciate your help.

tbh, the django tutorial explains urls, parameters and forms very clear, but here's the idea:
url(r'^/someapp/(?P<page_id>\d+)/$', paginas),
def paginas(request, **kwargs):
id = kwargs.pop('page_id')
page = get_object_or_404(Page, id=id)
# etcetera
class Page(models.Model):
# regular stuff
def get_absolute_url(self):
return "/someapp/%d/" % self.id

In paginas you are obviously getting all Pages.
To get one page you can use the get function
def paginas(request, title):
try:
your_page = Page.objects.get(title=title)
except Page.DoesNotExist:
# error no page for that title
# could use built in get_object_or_404 as ArgsKwargs suggested
It's also important to consider using a slug to make sure encoding is correct. The page id would be even better to use

Related

TemplateDoesNotExist at /app/detail/3/

I got an error,
TemplateDoesNotExist at /app/detail/3/ app/post_detail.html.
I wrote the following:
def top(request):
content = POST.objects.order_by('-created_at')[:5]
page = _get_page(blog_content, request.GET.get('page'))
return render(request, 'top.html',{'content':content,"page":page})
class DetailView(generic.DetailView):
model = POST
def detail(request, pk):
content = POST.objects.get(id=pk)
return render(request, 'detail.html',{'content': content})
in top.html
<div>
{% for content in page %}
<h2>{{ content.title }}</h2>
<p>SHOW DETAIL</p>
{% endfor %}
</div>
in detail.html
<h2>{{ content.title }}</h2>
<p>{{ content.text }}</p>
When I access top.html, ordinary web site is shown, so it is ok. But when I put SHOW DETAIL links the error happens.
I did not write post_detail.html anywhere in my code, so I really cannot understand why post_detail.html causes the mistake.
As a test,I made post_detail.html in same directory with top.html and detail.html, but the same error happens. I want to make a system when I put SHOW DETAIL links, the content's detail is shown.
How should I fix this? What is wrong in my code?
After reading answer,I rewrote DetailView of views.py
class DetailView(generic.DetailView):
model = POST
template_name = 'detail.html'
but when I put SHOW DETAIL links, nothing is shown there.I wrote in detail.html
<h2>{{ post.title }}</h2>
<p>{{ post.text }}</p>
Am I wrong to write the way of detail.html or views.py?How can I show detail's content?
You are using a generic detail view for the POST detail. Generic views do not expect or use a detail() method, and either look for a template as specified in the template_name class attribute or the default which is modelname_detail.html.
You should either make your view a standard function view - like the "top" one - by moving the detail method out of that class; or, remove the method altogether (because it just does what the generic view does already) and either rename your template to post_detail.html or set template_name = 'detail.html'.

simple forloop with instance tag

I want to pass data from models to template using CMS_plugins.py
I've made an app and standalone works. When i open link manualy
localhost:port/en/post_list.html all values are shown and works.
If i go on admin page and add plugin, values in mysql are stored but not presended in my template.html . I want to pass values in template.html
EDIT:
I manage to pass values to template. I edited cms_plugins.py
How can i hook data with "for" ?.
In code blow, nothing isnt shown in my template.html
<p>{{instance.firstline}}</p> ->>>this works
{ %block content %}
{{ instance.post.offer_option}}
<p>{{post.firstline}}</p>
<p>{{post.secline}}</p>
{% endfor %}
{% endblock}
if i change to :
{% for post in posts %}
<p>{{post.firstline}}</p>
<p>{{post.secline}}</p>
{% endfor %}
{% endblock}
In upper case if i run manualy url: localhost:port/en/pricing , I can see the result i want to be rendered in template.In template nothing isnt shown neither.
cms_plugins.py
class pricing(CMSPluginBase):
model = Post
name = _("pricing")
render_template = "post_list.html"
cache = False
def render(self, context, instance, placeholder):
context.update({'instance': instance})
return context
plugin_pool.register_plugin(pricing)

simple loop in rendered template django cms plugin

I want to loop data taken from database in rendered template. Using cms plugin.
I dont have problem looping data in html template. But if i use CMSPlugin to insert new app in placeholder, nothing shows.
If i run url localhost:port/test.html.I got input what i want. But rendered template doesnt loop data.
{% for post in posts %}
{{ post.firstoption }}
{% endfor %}
if I use code below, nothing shows in my rendered template. Values are passed in rendered template. Because, if i try {{instance.firstoption}} i get value shown in template. Problem is i cant loop data with tag instance.
{% for post in instance.posts %}
{{ post.firstoption }}
{% endfor %}
I also tried {% for post in instance.posts_set.all %}
and {% for post in instance.posts.all %}
cms_plugins.py
class pricing(CMSPluginBase):
model = mymodel
name = _("myplugin")
render_template = "template.html"
cache = False
def render(self, context, instance, placeholder):
context.update({'instance': instance})
return context
models.py
class mymodel(CMSPlugin):
firstoption = models.CharField(max_length=200)
def __str__(self):
return self.firstoption
It is probably because you need to call all on your posts
{% for post in instance.posts.all %}
{{ post.firstoption }}
{% endfor }

django-cms: how to get the Page from an app associated with it

Given this apphook:
class NewsHook(CMSApp):
name = _("News")
urls = ["apps.news.urls"]
apphook_pool.register(NewsHook)
and this model inside apps.news.models:
class Article(models.Model):
title = models.CharField(max_length=255)
...
Is it possible to reference the page associated by apphook in, say, a method on Article?
From the model side I've gotten as far as article._meta.app_label or article._meta.app_config.verbose_name, but that only yields 'news' and 'News', respectively.
And I know from https://github.com/divio/django-cms/blob/7888ab8421bb836c8f7a1127d9a2bf4d4bbdf23e/cms/models/pagemodel.py#L82 that a page's apphook is accessible with page.application_urls, which gives me 'u'NewsHook'.
But I'm missing a link.
I suppose I could filter Pages by the application_urls field and look for a match with my article._meta.app_config.verbose_name, but that would be neither neither failsafe nor pretty.
Any ideas for a better way?
I know this question is a year old and probably OP have figured it out, but I had a similar problem, which I solved by referencing the apphook directly on the method.
from applications.cms_apps import ApplicationAppHook
from cms.models.pagemodel import Page
class Application(models.Model):
def related_cms_page(self):
return Page.objects.filter(application_namespace=ApplicationAppHook.app_name).public().first()
I've gone somewhat further and created a templatetag that uses the application_namespace value to retrieve the page
from cms.models.pagemodel import Page
#register.assignment_tag()
def get_page_by_namespace(application_namespace_str):
try:
return Page.objects.filter(application_namespace=application_namespace_str).public().first()
except AttributeError:
# EAFP ;)
return None
And on the template:
{% get_page_by_namespace 'applications_apphook' as page %}
{% if page %}
{{ page.get_menu_title }}
{# Official Django CMS templatetags also works in this instance, i.e. {% page_attribute "page_title" page %} but it seems a bit redundant to me #}
{% endif %}

Trouble Rendering Template Variables in Django

I am hitting a brick wall when it comes to solving this problem. I have a template that is being included in an other template, but I am unable to render any template variables in the included template. I have a separate template tag file for the included template. I am at a total loss right now how to resolve this problem.
I would like to be able to render the field values from my model in the template (which consist of an image, a short description, etc.) I am fairly certain that I am going about this in the wrong way.
Below is my code:
The model:
class AddOnItem(models.Model):
base_product = models.ForeignKey(Product)
base_price = models.DecimalField(max_digits=8, decimal_places=2, default=0.0)
addon_image = models.ImageField(upload_to='uploads/shop/product/images/',
default='uploads/shop/product/images/', help_text='Max width: 450px')
short_description = models.CharField(max_length=255, blank=True)
def __unicode__(self):
return self.base_product.name
The template:
{% load addon_tags %}
{% if items_to_add %}
{% for items in items_to_add %}
<div id="addon-container">
<div id="left-addon" class="addon-container">
<img src="#" class="addon-image">
<p class="addon-description">{{items.short_description}}</p>
</div>
</div>
{% endfor %}
{% endif %}
addon_tags.py:
from django import template
from sho.models import AddOnItem
register = template.Library()
#register.inclusion_tag("foo/templates/v/sho/addon.html", takes_context=True)
def add_on_render():
context['items_to_add'] = AddOnItem()
return context
I imagine I am doing either a lot wrong (my assumption at the moment) or I am missing some minor bit. I have been working on this for several days and have gone over the docs repeatedly. I am simply completely missing something and this has become a major blocker for me. Any help would be appreciated.
Django version 1.4
Edit:
I ended up rewriting the view and did away with the templatetag. Thanks to both Daniel Roseman and Odif Yltsaeb for their replies.
1) From your post you are adding empty, new item into the context in add_on_render templateag.
2) I cant see in your post, WHERE you are using {% add_on_render %} templatetag. You have created templattag, but do not seem to be using it anywhere.
It is bit hard to understand what exactly are you trying to do or why you even need templatetag there.
If you want to display models field value, you do not need templateag for this and all the stuff that you show in your "template" part of this post, could be very well in your main template, which i assume, is not shown in your post.
If you want to use templatetag, then this templatetag should probably recieve AddOnItem istance as parameter like this:
#register.inclusion_tag("foo/templates/v/sho/addon.html", takes_context=True)
def add_on_render(item):
context['items_to_add'] = item
return context
And You could use it in some template like this:
{% load addon_tags %}
{% if items_to_add %}
{% for items in items_to_add %}
<div id="addon-container">
<div id="left-addon" class="addon-container">
<img src="#" class="addon-image">
<p class="addon-description">{% add_on_render items %}</p>
</div>
</div>
{% endfor %}
{% endif %}
and your foo/templates/v/sho/addon.html
would like like this:
{{ items_to_add.short_description }}
But doing it this way seems very unnecessary as you could achieve all that without templatag by using the template code that you already have outside your "main" template.
You haven't posted the template that you are attempting to include the tag in. I suspect you're not calling it at all, because there are a couple of errors that would cause exceptions if you did try and use the tag. You need to do {% add_on_render %} somewhere in your main template.
As I say though there are a couple of errors. Firstly, you don't define context (as an empty dict) before adding the items_to_add key. You can shortcut this by just doing it in one go.
Secondly you've made items_to_add a single, blank, AddOnItem. So in your included template, iterating through items_to_add does nothing at all. Not sure what you are trying to do there. Perhaps you want to pass all AddOnItem instances?
context = {'items_to_add': AddOnItem.objects.all()}
Or maybe you want to filter them by some criteria, in which case you probably want to pass those criteria to the inclusion tag itself:
def add_on_render(product):
context = {'items_to_add': AddOnItem.objects.filter(base_product=product)}
and you would call it from the main template like this:
{% add_on_render my_product %}
if you set "takes_context=True" you should take context as the first argument in decorated function:
#register.inclusion_tag("foo/templates/v/sho/addon.html", takes_context=True)
def add_on_render(context):
context['items_to_add'] = AddOnItem()
....

Categories