Django generic views - sending data to project templates - python

i try to send data with generic views from my app
urlpatterns = patterns('',
(r'*', ListView.as_view(
queryset=Post.objects.all().order_by("-created")[:2],
template_name="/mysite/templates/index.html"
)),
)
however, data cannot be sent
i c/p this query and result is returned. What's missing?
in mysite/templates/index.html
{% for post in object_list %}
{{ post.title }}
{% endfor %}
prints nothing

You are not providing enough information. r'*' is not a valid regular expression - * needs something to act on - and Django would report that if you tried to use it in a URLconf. You need to show how you are including that url in your main urls.py.

Related

TypeError: topics() missing 1 required positional argument: 'topic_id'

I'm following along a Django tutorial book to make a basic blogging application where users can write journal entries about whatever topic they choose. I've written the url, pattern, view, and template for my topic page but I keep getting this same error. but I think something is wrong with the url pattern.
urls.py
# Defines url patterns for learning_logs app
from django.conf.urls import url
from . import views
urlpatterns = [
# Home Page
url(r'^$', views.index, name='index'),
# Topic Main Page
url(r'^topics/$', views.topics, name='topics'),
# Detail page for a single topic
url(r"^topics/(?P<topic_id>\d+)/$", views.topics, name='topic'),
]
views.py
from django.shortcuts import render
from .models import Topic
# Create your views here.
def index(request):
# This is the home page for our learning_logs app
return render(request, 'learning_logs/index.html')
# This is the view for 'topics' page 9.5.20
def topics(request, topic_id):
'''show a single topic and its entries '''
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topics.html', context)
And the error:
TypeError: topics() missing 1 required positional argument: 'topic_id'
Any advice? Thank you.
EDIT**
What I'm trying to do is to have a page that lists all of the topics in general. When the link for one topic in particular is clicked, it will lead to the page for that particular topic.
Here's the code for the topics.html (all topics displayed) and topic.html (when one particular topic is chosen)..
topics.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>
{{ topic }}
</li>
{% empty %}
<li>No topics have been added yet</li>
{% endfor %}
</ul>
{% endblock content %}
and topic.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topic: {{ topic }}</p>
<p>Entries:</p>
<ul>
{% for entry in entries %}
<li>
<p>{{ entry.date_added|date:'M d, YH:i' }}</p>
<p>{{ entry.text|linebreaks }}</p>
</li>
{% empty %}
<li>No topics have been added yet</li>
{% endfor %}
</ul>
{% endblock content %}
The error clearly specifies that the function is not getting "topic_id", so there can be two cases
First, if you are using a template to redirect to that function(or view) you are not providing id, in that case, I might want to have a look at your template
Second, it's because of complex URL patterns so switch to something more simple likepath('topics/<int:topic_id>/', views.topics, name='topics'),
Lastly do not follow tutorial word to word because of things changes with update.
Your view is expecting a parameter passed to it ...
def topics(request, topic_id):
But your url does not have one:
url(r'^topics/$', views.topics, name='topics'),
You need to change the url to be something like:
path('topics/<int:topic_id>/', views.topics, name='topics'),
This means you would access that specific record at the url:
yourdomain.com/topics/1/
The 1 would be passed to the view, and used in topic = Topic.objects.get(id=topic_id)
The fact that you also have the url:
url(r'^topics/$', views.topics, name='topics'),
confuses matters - what is this view going to show with no topic set? From your code I suspect you want a list view here, which should ideally link to a different view, and maybe be named topics-list for clarity and ease of access in reverse lookups later. Your topics view specifically states in the docstring it is for viewing a single record, so don'ttry and use it for multiple ones as well. Much simpler to create a distinct view for that.
Edit: I see you've updated your path in urls.py in the question now. That should work for the single access, but note that your link topics/ is still directing to the same view - i.e. it's looking for a single record, but you're not telling it which.

How to include in django template a reverse url in translation

I have the following block of code, And I want to include a url to the login page, after the user logs out, in a translatable text.
Unfortunately, translation blocks cannot include tags, and I get the following error:
SyntaxError: Translation blocks must not include other block tags: url "account:login"
{% blocktrans %}
You have been successfully logged out.
You can log-in again.
{% endblocktrans %}
urls.py:
from django.urls import path
from django.contrib.auth import views as auth_views
app_name = 'account'
urlpatterns = [
path('login/', auth_views.LoginView.as_view(), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]
What would be the right way to achieve something like this?
Edit: I figured there are workarounds, such as translating blocks of text separately, or using javascript to append the "href" element after the page loads. But I wonder if there is a more efficient, Django way.
As documented
Reverse URL lookups cannot be carried out within the blocktrans and
should be retrieved (and stored) beforehand:
{% url 'path.to.view' arg arg2 as the_url %}
{% blocktrans %}
This is a URL: {{ the_url }}
{% endblocktrans %}

Using a specific flatpage in a template

I'm using django flatpages, and I'm wondering if there is a concise way of loading one specific flatpage within a template. The docs show the following patterns:
{% load flatpages %}
{% get_flatpages '/about/' as about_pages %}
{% get_flatpages about_prefix as about_pages %}
{% get_flatpages '/about/' for someuser as about_pages %}
I just want to load one specific page in a template, essentially using it like an include statement (e.g. {% include 'homepage.html' %})
The approach I am using is this:
{% get_flatpages '/flat-homepage/' as flatpages %}
{{ flatpages.first.content|safe }}
This works fine, but I thought there might be a slightly neater way of doing this. I'm marking the content as safe as I want html styles to be applied (again, not sure if there is a better way of doing this)
By default, there are 2 solutions for that.
First, register your flatpage in urls as below:
from django.contrib.flatpages import views
urlpatterns = [
url(r'^about-us/$', views.flatpage, {'url': '/about-us/'}, name='about'),
]
That way, you can access it using {% url %} tag, like normal view.
Second way, if you know exact url of that page, you can access it's url using:
{% url 'django.contrib.flatpages.views.flatpage' url='url_to_flatpage_here' %}
There is no other way, because all flatpages are identified by url.

Django context not rendering

I've got a Django template in HTML. I would like to pass a variable to this template using a context. However, when I render the template Django fills the spaces that reference this variable with the string specified by the TEMPLATE_STRING_IF_INVALID setting (I tested this).
Here's the relevant URLconf:
from django.conf.urls import patterns, url
from users import views
urlpatterns = patterns('',
url(r'^$', views.users),
url(r'(?P<pk>\d+)/$', views.userdetail),
)
and here's the view it references:
from django.template import RequestContext, loader
...
def userdetail(request, pk):
user = get_object_or_404(User, pk=pk)
template = loader.get_template('users/userdetail.html')
context = RequestContext(request, {'user': user})
return HttpResponse(template.render(context))
I'm fairly certain it's due to a syntax error in specifying the context but after looking at it for an hour I can't find one. I'm happy to post additional code if you think it may be relevant. Can anyone spot my mistake?
Template for those interested:
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif%}
<h1> You are viewing the page for the individual user {{ user.name }} </h1>
This user has created the following posts:
{% for post in user.post_list %}
{{ post.title }}</li>
{% endfor %}
<p>
Created on {{ user.creation_date }}
</p>
The OP wrote:
My supervisor just came around and fixed it really quickly. The issue is that templates have some predefined keywords. User is one of these keywords so django was upset that I was passing it {'user':user} in the context. Changing to {'customuser':user} avoids the collision with the django keyword and fixes this issue.

Getting admin email(s) from Django template

Is there a way to access the ADMINS variable of the settings module from an any arbitrary template without adding manually adding it into the context before being rendered, similar to how request is available in any template using RequestContext if django.core.context_processors.request is in TEMPLATE_CONTEXT_PROCESSORS?
You can write your own context processor (which is a regular function that has request as parameter):
from django.conf import settings
def admin_emails(request):
return { 'ADMINS': settings.ADMINS }
and add path.to.my.context_processor.admin_emails to TEMPLATE_CONTEXT_PROCESSORS.
I'd use a template tag like discussed for this question:
Can I access constants in settings.py from templates in Django?
Specifically I use the code from this answer: https://stackoverflow.com/a/6343321/2250326
With that you can get at the AMDINS in your templates like this:
{% value_from_settings "ADMINS" as admins %}
{% for admin in admins %}
Name: {{ admin.0 }}<br />
Email: {{ admin.1 }}
{% endfor %}

Categories

Resources