Reputation: 69
I am trying to display a link to the next and previous object according the title field using get_next_or_previous_by_FIELD. Django 1.6 is throwing me this error.
Error during template rendering
'str' object has no attribute 'attname'
Error occurs here in template.
{% with next_lesson=lesson.get_next_by_title %}
And here in my models.
return self._get_next_or_previous_by_FIELD('title', is_next=True)
Here is my model.
class LessonManager(models.Manager):
def all(self):
return super(LessonManager, self).filter(active=True)
class Lesson(models.Model):
active = models.BooleanField(default=False)
title = models.CharField(max_length=65)
slug = models.SlugField(unique=True)
objects = LessonManager()
def __unicode__(self, ):
return self.title
class Meta:
ordering = ['title']
def get_absolute_url(self):
return reverse('lesson', args=[str(self.slug)])
def get_next_by_title(self):
try:
return self._get_next_or_previous_by_FIELD('title', is_next=True)
except Lesson.DoesNotExist:
return None
def get_previous_by_title(self):
try:
return self._get_next_or_previous_by_FIELD(order='title', is_next=False)
except Lesson.DoesNotExist:
return None
And here is my template.
<a class="col-md-6" href="{{ lesson.get_previous_by_title.get_absolute_url }}" title="{% trans "View previous post" %}">« {{ lesson.get_previous_by_title.title }}</a>
<a class="col-md-6" href="{{ lesson.get_next_by_title.get_absolute_url }}" title="{% trans "View previous post" %}">« {{ lesson.get_next_by_title.title }}</a>
Here is the full traceback as requested.
Environment:
Request Method: GET
Request URL: /tutorials/lesson/lesson-name/
Django Version: 1.6.2
Python Version: 2.7.6
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'ckeditor',
'tutorials')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware')
Template error:
In template C:\Users\Shaun\Desktop\sg\static\templates\tutorials\lesson.html, error at line 22
'str' object has no attribute 'attname'
12 : {% endif %}
13 : {% if lesson.get_next_by_timestamp %}
14 : <a class="right" href="{{ lesson.get_next_post.get_absolute_url }}">{{ lesson.get_next_post.title|truncatewords:'4' }} »</a>
15 : {% endif %}
16 :
17 : <div class='clearfix'></div>
18 :
19 : <h2>{{ lesson.title|upper }}</h2>
20 : <p>{{ lesson.content|safe }}</p>
21 :
22 : <a class="col-md-6" href=" {{ lesson.get_previous_by_title.get_absolute_url }} " title="{% trans "View previous post" %}">« {{ lesson.get_previous_by_title.title }}</a>
23 : <a class="col-md-6" href="{{ lesson.get_next_by_title.get_absolute_url }}" title="{% trans "View previous post" %}">« {{ lesson.get_next_by_title.title }}</a>
24 :
25 : {% endblock %}
Traceback:
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\core\handlers\base.py" in get_response
114. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Shaun\Desktop\sg\src\tutorials\views.py" in single_lesson
13. return render_to_response('tutorials/lesson.html', locals(), context_instance=RequestContext(request))
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\shortcuts\__init__.py" in render_to_response
29. return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\loader.py" in render_to_string
169. return t.render(context_instance)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in render
140. return self._render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in _render
134. return self.nodelist.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in render
840. bit = self.render_node(node, context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\debug.py" in render_node
78. return node.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\loader_tags.py" in render
123. return compiled_parent._render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in _render
134. return self.nodelist.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in render
840. bit = self.render_node(node, context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\debug.py" in render_node
78. return node.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\loader_tags.py" in render
62. result = block.nodelist.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in render
840. bit = self.render_node(node, context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\debug.py" in render_node
78. return node.render(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\debug.py" in render
88. output = self.filter_expression.resolve(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in resolve
585. obj = self.var.resolve(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in resolve
735. value = self._resolve_lookup(context)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\template\base.py" in _resolve_lookup
789. current = current()
File "C:\Users\Shaun\Desktop\sg\src\tutorials\models.py" in get_previous_by_title
64. return self._get_next_or_previous_by_FIELD('title', is_next=False)
File "C:\Users\Shaun\Desktop\sg\lib\site-packages\django\db\models\base.py" in _get_next_or_previous_by_FIELD
708. param = force_text(getattr(self, field.attname))
Exception Type: AttributeError at /tutorials/lesson/setting-up-your-django-blog-application/
Exception Value: 'str' object has no attribute 'attname'
Upvotes: 0
Views: 1399
Reputation: 599470
_get_next_or_previous_by_FIELD
isn't supposed to be something you call yourself.
The main problem you're having is that it is expecting a Field object, not a string, hence the error. This is because the method is actually used as part of a curried function that is created by the field class itself, which in turn is called by the model metaclass when the model is first imported.
The currying creates the actual get_next_by_foo
and get_previous_by_foo
methods. In fact, these are only created for Date and Datetime fields.
Note that the uncurried method name begins with an underscore, which - with the exception of Model._meta
- is a good sign that you're not supposed to be using it in your own code.
Upvotes: 1