Problem with django urls which have a hyphen in them - python

I have a simple set of urls in a Django url conf file which points to some object detail generic views.
urlpatterns = patterns('',
url(r'^projects/(?P<slug>[\w-]+)/$', ProjectDetailView.as_view(), name='view_project'),
url(r'^roles/(?P<slug>[\w-]+)/$', RoleDetailView.as_view(), name='view_role'),
)
The problem is whenever there's a hyphen in the urls (eg:-/projects/new-project/) slug, Djangos development server get stuck. I've checked with pdb and there isn't a problem with parsing the url and getting the object from the database based on the slug. But it gets stuck somewhere when the template gets rendered. I can't figure out the source of the problem. any idea what the problem is?
The view code is,
class ProjectDetailView(DetailView):
model=Project
context_object_name='project_obj'
slug_field='slug'
#method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(ProjectDetailView, self).dispatch(*args, **kwargs)
The template code is,
{% extends "base.html" %}
{% load static %}
{% block static %}
<link rel="stylesheet" type="text/css" href="{% get_static_prefix %}css/demo_table.css">
<script type="application/javascript" src="{% get_static_prefix %}js/users-index.js"></script>
{% endblock %}
{% block content %}
<div id="itemlist">
{% if project_obj %}
<div>
<p>{{ project_obj.title }}</p>
<p>{{ project_obj.description }}</p>
</div>
{% else %}
<p>No Details available.</p>
{% endif %}
<div>
{% endblock %}
After removing some of the tags from the template it started working,
<div id="itemlist">
{% if project_obj %}
<div>
<p>{{ project_obj.title }}</p>
<p>{{ project_obj.description }}</p>
</div>
{% else %}
<p>No Details available.</p>
{% endif %}
<div>

Change [\w-]+ to [-\w]+. For me [\w-]+ never works with python regexp's.

My guess is that you wrote a custom template tag, but it's broken. You're using it in base.html :P

Related

Passing a variable to include in extends in Django templates

I have the following structure of templates:
main.html
<html>
<body>
<p>
This works: {% block title %}{% endblock %}
</p>
{% include 'heading.html' with title=title %} {# but this does not work since it is not a variable #}
</body>
</html>
heading.html
<p>
{{ title }}
</p>
page.html
{% extends 'main.html' %}
{% block title %}test title{% endblock %}
How can I pass the title from page.html to heading.html? Ideally, it should be defined as a block like now, but alternatives are also welcome. I'd like to contain the solution within the templates if possible.
Clarification:
This is a minimal example, but I have multiple pages like main.html that share a larger header that has title and some other variables that I'd like defined in the child template (not necessarily as variable as long as the text is passed).
I could put the title into the view code, but this solution would just decrease the separation of displayed data from the logic.
Use a block around the include with variables, and then wrap {{ block.super }} in the with template tag.
main.html:
<html>
<body>
<p>
This works: {% block title %}{% endblock %}
</p>
{% block with_variables %}
{% include 'heading.html' %}
{% endblock %}
</body>
</html>
page.html:
{% extends 'main.html' %}
{% block title %}test title{% endblock %}
{% block with_variables %}
{% with title="variable title" %}
{{ block.super }}
{% endwith %}
{% endblock %}
You may name it {% block heading %}, or nest the whole main.html in {% block content %}.
instead of {% include %}, you might want to use custom template tags with returning html or extension like slippers
You don't need heading.html. You can use the context variable title directly; as long as you pass it to your render function in your view, e.g.:
views.py
def my_view(request):
context = {'title': 'Hello World!'}
return render(request, 'page.html', context=context)
main.html
<html>
<body>
<p>
This is my title:
{% block title %}{% endblock %}
</p>
</body>
</html>
page.html
{% extends 'main.html' %}
{% block title %}
<strong>{{title}}</strong>
{% endblock %}
If you have administrative rights to your Django installation, an easy and elegant solution would be to switch your Django's template renderer to Jinja2 instead using django-jinja as a backend.
The main advantage of Jinja2 for the needs of this question is that it supports assignment of a block to a variable through block assignments. Since Jinja2 is inspired by the Django template language, your existing templates will need few modifications, if any.
With Jinja2 as a template renderer, you can set the title variable with a block of HTML content in the child template:
page.html
{% extends 'main.html' %}
{% set title %}test title{% endset %}
The title variable will then work in the shared template:
main.html
<html>
<body>
<p>
Main template works: {{ title }}
</p>
{% include 'heading.html' %}
</body>
</html>
And it will also work in the included template:
heading.html
<p>
Included template also works: {{ title }}
</p>
Demo: https://replit.com/#blhsing/AlarmedCleverDebugmonitor
One possible solution is to split heading.html into two and add a {% block %} in-between, but this is an ugly workaround that is prone to bugs with unclosed tags.
I am searching for a better alternative.
main.html
...
{% include 'heading1.html' %} {# containing <p> #}
{% block title %}{% endblock %}
{% include 'heading2.html' %} {# containing </p> #}
...
Additionally, if white spaces are important, there has to be no new line between includes and the block.
add your title to the rendering context and it will be visible in page, main and included heading.

Django include template, overwrite 'self' variable?

I've been tasked to fix a template structure in a Django app. I am not very familiar with Django as I deal mostly with front end projects built in React.
The Django app is using Wagtail as a backend CMS. I am looping through it's pages, and including a template block and trying to pass variables with the with statement on the include. I can successfully pass variables to the template block, but I need to overwrite the 'self' variable as the template block is looking for self.something.
Here is what my template looks like.
{% load static wagtailimages_tags wagtailcore_tags %}
<div class="c-card {% if self.variant %}c-card--{{ self.variant }}{% endif %}">
{% if self.image %}
{% image self.image original class="c-card__image" loading="lazy" %}
{% endif %}
{% if self.title %}
<h3 class="c-card__title">{{ self.title }}</h3>
{% endif %}
{% if self.text %}
<p class="c-card__content">{{ self.text }}</p>
{% endif %}
{% if self.button.title and self.button.url %}
{% include './button_block.html' with button=self.button %}
{% endif %}
</div>
and then there is the loop and include snippet...
{% for chapter_menu in page.chapters %}
<div class="medium-6 large-4 columns">
{{ chapter_menu.value.title }}
{% include './blocks/card_block.html' with self=chapter_menu.value %}
</div>
{% endfor %}
Doing this self=chapter_menu.value results in a TypeError, which is expected as I am defining self twice. push() got multiple values for argument 'self'
How can I go about doing this? Any docs I can read besides the basic django templating docs? https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#with
add the only attribute to include.... Did not find this in any documentation...
{% include './blocks/card_block.html' with self=chapter_menu.value only %}

Django- url not displaying page despite changing

This is the index.html
{% extends 'base.html' %}
{% block content %}
<h1>list of {{title}}</h1>
{% if questions %}
<ul>
{% for question in questions %}
<li>
{{question.title}}
</li>
{% endfor %}
</ul>
{% else %}
<p>there is a no question available</p>
{% endif %}
{% endblock %}
details.html
{% extends 'base.html' %}
{% block content %}
<H2>Details Page</H2>
<h3>{{question.title}}</h3>
{% for choice in question.choices %}
<p>{{choice.text}}({{choice.votes}})</p>
{% empty %}
<p>There is no choice available for this Question</p>
{% endfor %}
<p>Poll is created by {{question.created_by.first_name}}</p>
{% endblock %}
This is base.html
{%load static%}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebPage</title>
<link rel="stylesheet" href="(%static 'css/custom.css'%)">
</head>
<body>
<h1>Welcome to My Page</h1>
{% block content %}
{% endblock %}
</body>
</html>
And poll.urls
from django.conf.urls import url
from poll.views import *
urlpatterns = [
url('', index, name='polls_list'),
url('<int:id>/details/', details, name='polls_details')
]
So this is what happens I have 3 questions that display on the index.html, on clicking any of them it changes to the proper url but does not open the requested page. How do I solve this. Do keep in mind that i just started django two days ago so pardon my naivety.Thanks
In urls.py you are using the url() function but path syntax. Change it to path:
path('', index, name='polls_list'),
path('<int:id>/details/', details, name='polls_details')
Edit If you're using pre-2.0, path syntax is not supported, so you need to use regexes:
url('^$', index, name='polls_list'),
url('^(?P<id>\d+)/details/$', details, name='polls_details')
Can you please edit your url as per the code below. Django can handle the url creation.
{{question.title}}

what is the method to use a different template to extend the statement {% block%}?

I have this situation, my base.html
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
...
</head>
<body>
...
<div class="container-fluid">
<div class="row">
<div class="col-xs-6">
{% block album %}
{% endblock %}
</div>
<div class="col-xs-6">
{% block artist %}
{% endblock %}
</div>
</div>
</div>
then my album.html
{% extends 'polls/base.html' %}
{% block album %}
{% for album in albums %}
<div>
<h3>{{album.name}}</h3>
<ul>
<li>Artist: {{album.artist}}</li>
<li>Genre: {{album.genre}}</li>
<li>Songs: , </li>
<li>Vote: {{album.vote}}</li>
</ul>
</div>
<hr />
{% endfor %}
{% endblock %}
my url.py
...
url(r'^$', views.album, name='album'),
url(r'^album/(?P<pk>[0-9]+)/$', views.album_detail, name='album_detail'),
...
my views.py
def album(request):
albums = Album.objects.all()
artists = Artist.objects.all()
return render(request,'polls/album.html',{'albums':albums,'artists':artists})
def album_detail(request, pk):
album = get_object_or_404(Album, pk=pk)
return render(request, 'polls/album_detail.html', {'album': album})
ok and album is render. But I would do the same thing with another file.html and extend the {% block artist %} but do not know how. please help me.
Not sure I understood your question correctly, but it seems that you need to have the template HTML for "artist" and the HTML for "album" in separate .html files.
There is no way to do that the way you are going, because then you'd have two templates extending the base.html template, and you'd end up with two complete HTML documents.
So your two partial templates artist-partial.html and album-partial.html should not extend base.html.
{% for album in albums %}
<div>
...
</div>
{% endfor %}
and
{% for artist in artists %}
<div>
...
</div>
{% endfor %}
Then, create another template file, maybe album-container.html that will be the container for the partial templates, extending from the base template.
{% extends 'polls/base.html' %}
{% block artist %}
{% include 'polls/artist-partial.html' %}
{% endblock %}
{% block album %}
{% include 'polls/album-partial.html' %}
{% endblock %}
And that template is loaded in your view
return render(request,'polls/album-container.html',
{'albums': albums,'artists': artists})

Django extends/include - bug?

I'm trying to use both extends and include tags in one template, just like:
{% extends "layout.html" %}
{% block content %}
<div id="content">
<nav class="mainMenu">
{% include "list.html" %}
</nav>
</div>
{% endblock %}
Unfortunately what is displayed is only list.html without contents from layout.html and file that is including the list.html. Why is that?
You are most probably only rendering list.html in your view, check for that.

Categories

Resources