I'm learning Django and I have problems with templates.
I'm trying to add content to extended template.
Structure of my code:
base.html
category
-- category_detail.html
-- list_content.html
category_detail.html
{% extends 'base.html' %}
{% block title %}
{{ category_name }}
{% endblock %}
{% block description %}
{{ category_description }}
{% endblock %}
{% block content %}
<div class="col-md-10 text-center">
Error list
</div>
{% endblock %}
Simple subpage with button. Button should redirect to another template, hovewer it gives me NoReverseMatch.
list_content.html (which is category_error_list defined in view)
{% extends 'category/category_detail.html' %}
{% block content %}
{{ block.super }}
<h1 class="page-header"> Some string</h1>
{% endblock %}
What I'm trying to achieve is displaying "Some string" under button. (I know it should be done better with AJAX for example, but I want to learn the basics).
urls.py
urlpatterns = [
url(r'^category/$', views.categories_list, name='categories'),
url(r'^category/(?P<category_name>\w+)/$', views.category_detail, name='category_detail'),
url(r'^category/(?P<category_name>\w+)/list/$', views.category_error_list, name='category_error_list'),
]
views.py
# ${url}/category/${category}
def category_detail(request, category_name):
cat_detail = Category.objects.get(name=category_name)
return render(request, 'charts/category/category_detail.html',
{'category_name': cat_detail.name,
'category_description': cat_detail.description})
#${url}/category/${category}/list
def category_error_list(request, category_name):
category_with_errors = Category.objects.filter(name=category_name)
error_list = Error.objects.get(category=category_with_errors)
return render(request, 'charts/category/list_content.html',
{'errors_list': error_list})
Problems seems to be related with urls.py, but I can't find what is wrong.
Stacktrace:
Template error:
In template
/usr/src/app/analizer/charts/templates/charts/category/list_content.html, error at line 0
Reverse for 'category_error_list' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['category/(?P<category_name>\\w+)/list/$']
1 : {% extends 'category/category_detail.html' %}
2 :
3 : {% block content %}
4 : {{ block.super }}
5 : <h1 class="page-header"> Cos tam </h1>
6 : {% endblock %}
7 :
8 :
If I will remove block.super tag it is working, but I'm overriding content on parent template. What I'm doing wrong?
I'm using Django-1.9.4.
I have found the solution - which is nonintuitive for me - but it is working.
View category_error_list was missing category_name variable, so I have fixed it but this:
def category_error_list(request, category_name):
category_with_errors = Category.objects.get(name=category_name)
error_list = Error.objects.get(category=category_with_errors)
return render(request, 'charts/category/list_content.html',
{'category_name': category_with_errors.name,
'errors_list': error_list})
Related
I am working on CS50 Project 1 dealing with Django. In urls.py I have two paths that take strings as input, but neither work, and I receive a NoReverseError message.
urls.py code
urlpatterns = [
path("", views.index, name="index"),
path("edit_entry/<str:title>/", views.edit_entry, name = "edit_entry"),
path("search/", views.search, name = "search"),
path("wiki/<str:title>/", views.get_entry, name = "get_entry"),
path("create_entry", views.create_entry, name = "create_entry")
]
views.get_entry code
def get_entry(request, title):
exists = util.get_entry(title)
if exists is None:
return render(request, "encyclopedia/get_entry.html", {
"entry": "Entry Does Not Exist"
})
else:
entry = markdown(util.get_entry(title))
return render(request, "encyclopedia/get_entry.html", {
"entry": entry
})
views.edit_entry code (edit_entry actually has some more work that needs to be done to it)
def edit_entry(request, title):
if request.method == "POST":
form = NewEditEntryForm(request.POST)
if form.is_valid():
title = form.cleaned_data["title"]
content = form.cleaned_data["content"]
util.save_entry(title, content)
return HttpRespnseRedirect("/wiki/" + title)
else: return render(request, "encyclopedia/edit_entry.html",{
"form": NewEditEntryForm() })
The error message
NoReverseMatch at /wiki/Css/
Reverse for 'edit_entry' with keyword arguments '{'title': ''}' not found. 1 pattern(s) tried: ['edit_entry/(?P<title>[^/]+)/$']
Your help would greatly be appreciated. Thank you!
Templates
get_entry.html
{% extends "encyclopedia/layout.html" %}
{% block title %}
Encyclopedia
{% endblock %}
{% block body %}
<p>
{{ entry|safe }}
</p>
Edit This Entry
{% endblock %}
edit_entry.html
{% extends "encyclopedia/layout.html" %}
{% block title %}
Edit Entry
{% endblock %}
{% block body %}
<h1>Edit {{ title }}</h1>
<form action = "{% url 'edit_entry' title=title %}" method = "POST"></form>
{% csrf_token %}
{{ form }}
<input type = submit value = "Save">
</form>
{% endblock %}
I figured it out. I had to remove title=title from the hrefs in the templates and make it a hard coded url with a variable.
I installed the app careers mezanine and after creating a test position and turn the page to see the error TypeError at / careers / test /
jobpost_detail () got an unexpected keyword argument 'slug'. How do I fix this problem?
views
from calendar import month_name
from django.shortcuts import get_object_or_404
from collections import defaultdict
from django.contrib.contenttypes.models import ContentType
from django import VERSION
from careers.models import JobPost
from mezzanine.conf import settings
from mezzanine.generic.models import AssignedKeyword, Keyword
from mezzanine.utils.views import render, paginate
def jobpost_list(request, tag=None, year=None, month=None, template="careers/jobpost_list.html"):
"""
Display a list of job posts that are filtered by year, month.
"""
settings.use_editable()
templates = []
jobposts = JobPost.objects.published()
if tag is not None:
tag = get_object_or_404(Keyword, slug=tag)
jobposts = jobposts.filter(keywords__in=tag.assignments.all())
if year is not None:
jobposts = jobposts.filter(publish_date__year=year)
if month is not None:
jobposts = jobposts.filter(publish_date__month=month)
month = month_name[int(month)]
# We want to iterate keywords and categories for each blog post
# without triggering "num posts x 2" queries.
#
# For Django 1.3 we create dicts mapping blog post IDs to lists of
# categories and keywords, and assign these to attributes on each
# blog post. The Blog model then uses accessor methods to retrieve
# these attributes when assigned, which will fall back to the real
# related managers for Django 1.4 and higher, which will already
# have their data retrieved via prefetch_related.
jobposts = jobposts.select_related("user")
if VERSION >= (1, 4):
jobposts = jobposts.prefetch_related("keywords__keyword")
else:
if jobposts:
ids = ",".join([str(p.id) for p in jobposts])
keywords = defaultdict(list)
jobpost_type = ContentType.objects.get(app_label="careers", model="jobpost")
assigned = AssignedKeyword.objects.filter(jobpost__in=jobposts, content_type=jobpost_type).select_related("keyword")
for a in assigned:
keywords[a.object_pk].append(a.keyword)
for i, post in enumerate(jobposts):
setattr(jobposts[i], "_keywords", keywords[post.id])
jobposts = paginate(jobposts, request.GET.get("page", 1),
settings.CAREERS_PER_PAGE,
settings.MAX_PAGING_LINKS)
context = {"jobposts": jobposts, "year": year, "month": month, "tag": tag}
templates.append(template)
return render(request, templates, context)
def jobpost_detail(request, template="careers/jobpost_detail.html"):
""". Custom templates are checked for using the name
``careers/jobpost_detail_XXX.html`` where ``XXX`` is the job
posts's slug.
"""
jobposts = JobPost.objects.published()
jobpost = get_object_or_404(jobposts)
context = {"jobpost": jobpost, "editable_obj": jobpost}
templates = [u"careers/jobpost_detail_%s.html" %(slug), template]
return render(request, templates, context)
html
{% extends "careers/jobpost_list.html" %}
{% load mezzanine_tags keyword_tags i18n %}
{% block meta_title %}{{ jobpost.meta_title }}{% endblock %}
{% block meta_keywords %}{% metablock %}
{% keywords_for jobpost as tags %}
{% for tag in tags %}{% if not forloop.first %}, {% endif %}{{ tag }}{% endfor %}
{% endmetablock %}{% endblock %}
{% block meta_description %}{% metablock %}
{{ jobpost.description }}
{% endmetablock %}{% endblock %}
{% block title %}
{% editable jobpost.title %}{{ jobpost.title }}{% endeditable %}
{% endblock %}
{% block breadcrumb_menu %}
{{ block.super }}
<li class="active">{{ jobpost.title }}</li>
{% endblock %}
{% block main %}
<h6>
{% trans "Posted" %} {{ jobpost.publish_date|timesince }} {% trans "ago" %}.
</h6>
{% editable jobpost.content %}
{{ jobpost.content|richtext_filter|safe }}
{% endeditable %}
{% keywords_for jobpost as tags %}
{% if tags %}
{% spaceless %}
<ul class="unstyled tags">
<li>{% trans "Tags" %}:</li>
{% for tag in tags %}
<li>{{ tag }}</li>
{% endfor %}
</ul>
{% endspaceless %}
{% endif %}
{% set_short_url_for jobpost %}
<a class="btn small primary share-twitter" target="_blank" href="http://twitter.com/home?status={{ jobpost.short_url|urlencode }}%20{{ jobpost.title|urlencode }}">{% trans "Share on Twitter" %}</a>
<a class="btn small primary share-facebook" target="_blank" href="http://facebook.com/sharer.php?u={{ request.build_absolute_uri }}&t={{ jobpost.title|urlencode }}">{% trans "Share on Facebook" %}</a>
{% endblock %}
url
from django.conf.urls import patterns, url
# Job Post patterns.
urlpatterns = patterns("careers.views",
url("^tag/(?P<tag>.*)/$",
"jobpost_list",
name="jobpost_list_tag"),
url("^archive/(?P<year>\d{4})/(?P<month>\d{1,2})/$",
"jobpost_list",
name="jobpost_list_month"),
url("^archive/(?P<year>.*)/$",
"jobpost_list",
name="jobpost_list_year"),
url("^(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<slug>.*)/$",
"jobpost_detail",
name="jobpost_detail_date"),
url("^(?P<slug>.*)/$",
"jobpost_detail",
name="jobpost_detail"),
url("^$",
"jobpost_list",
name="jobpost_list"),
)
The error tells you exactly what is going on: your "jobpost_detail" URL the captures a slug parameter and passes it on to the view, but that view does not expect a slug, only the request and a template. Also, you are not doing anything in that view to get the actual post identified by a slug: you are always getting the first published post.
I suspect you want to do the following:
def jobpost_detail(request, slug, template="careers/jobpost_detail.html"):
jobposts = JobPost.objects.published()
jobpost = get_object_or_404(jobposts, slug=slug)
Edited my code: In the custom fieldset of a model admin:
{%load app_extras %}
{% if field.field.name == 'mobile' %}
<a target="hiddenIframe" href="http://url_to_call.php?exten={{request.user.employee_profile.extension}}&phone={{ field.field.value }}">Click-to-call</a>
{% my_mobile mobile=field.field.value as mob %}
{% endif %}
{% if field.field.name == 'sms_message' %}{{ mob }}
<a target="hiddenIframe" href="http://url_for_send_sms.php?sms_message={{ field.field.value }}&phone={{ mob }}">Click-to-send-sms</a>
{% endif %}
Here I am trying to access mobile number as well as sms_message fields of the model admin form simultaneously.
I have figured that I need to use custom tags, so I created the templatetags module, with app_extras.py containiging the function to assign the value of mobile and return it as follows:
#register.assignment_tag
def my_mobile(*args, **kwargs):
m_mobile = int(kwargs['mobile'])
return {'m_mobile': m_mobile }
In the template fiedset.html above note changes: This returns a Long value as: {'m_mobile': 1234534519L}
When seen on the browser for url for hyperlink shows:
http://url_for_send_sms.php/?sms_message=fgdfg&phone={%27m_mobile%27:%1234534519L}
How do I access the mobile number? Is my custom tag correct?
I formatted the output in my tag as:
#register.assignment_tag
def my_mobile(*args, **kwargs):
m_mobile = ("%d" %int(kwargs['mobile']))
return {'m_mobile': m_mobile }
In the template fieldset.html changed the code as:
{% if field.field.name == 'sms_message' %}
<a target="hiddenIframe" href="http://url_for_send_sms.php?sms_message={{ field.field.value }}&phone=={{ mob.m_mobile }}">Click-to-send-sms</a>
{% endif %}
Important: Both the mobile number and the sms_message are in the same line of the fieldset in the django modeladmin (in my case). So above code belongs to the loop {% for line in fieldset %} loop
Try
{% for ln in fieldset %}
{% for fld in ln %}
{% if f.field.name == 'mobile' %}
{{ f.field.value }}
{% endif %}
{% endfor %}
{% endfor %}
Maybe this is not the best solution ... but it is solution :)
I've got a model, and my instance called "show_user_image":
class user_image(models.Model):
title = models.CharField(max_length=50)
img = models.imageField(upload_to='/home/blabla')
def show_user_image(self):
return u'<img src="%s" />' % self.img.url
show_user_image.short_description = 'User image'
image_img.allow_tags = True
off course i can use it at my admin list:
list_display = ('title', 'show_user_image')
And my question is: how to use this instance in the edit form?
Something like here:
http://new-media.djangobook.com/content/en/1.0/chapter17/book_extra.png
{% extends "admin/change_form.html" %}
{% block form_top %}
<p>Insert meaningful help message here...</p>
{% endblock %}
but i want:
{% extends "admin/change_form.html" %}
{% block form_top %}
{{ MY-INSTANCE-HERE }}
{% endblock %}
I just need to image display above the form.
Thanks!
John.
The form is admin template is available via adminform.form variable. Your field is named img, so it will be like this (untested):
{% block form_top %}
<img src="{{ adminform.form.img.value }}"/>
{% endblock %}
BTW. Class names in python should use CapitalizedWordsNamingConvention, according to official style guide. You should name the model UserImage instead of user_image.
BTW2: show_user_image is a method, not an instance.
I'm trying to write a custom inclusion_tag in django.
Following the example on http://docs.djangoproject.com/en/dev/howto/custom-template-tags/
I'm just writing
from django import template
from libmas import models
register = template.Library()
#register.inclusion_tag('records.html')
def display_records(book_id):
book = models.book.objects.get(id__exact=book_id)
records = models.objects.filter(books=book)[0:10]
return {'records':records}
But I'm getting a
Invalid block tag: 'libmas_tags'
error in ie .
'records.html' file:
{% for record in records %}
<blockquote>{{record.id}}</blockquote>
{% endfor %}
my other html file is :
{% extends "admin/change_form.html" %}
{% libmas_tags %}
{% block after_field_sets %}
{% if object_id %}
{% display_records object_id %}
{% endif %}
{% endlock %}
The problem lies in your template. Its calling {% libmas_tags %}. Have you created template tags called libmas_tags? If so you might need to change it to
{% load libmas_tags %}
What is libmas_tags? The tag you have defined is called display_records, and that's what you should be calling in your template. If the tags file is called libmas_tags, you'll need to load that first as czarchaic points out.