Reputation: 23
I’m having trouble generating the absolute url for a Django model. In "courses.html" template I iterate through two models, category
and course
, but am only able to generate the relative url <slug>
rather than the full url /courses/<slug>
from each object.
Is there any way to generate an absolute url for each object?
main views.py
def courses(request):
return render(request=request,
template_name="main/courses.html",
context={'courses': Course.objects.all,
'categories': Category.objects.all},
)
courses.html
{% extends "main/header.html" %}
{% block content %}
{% for category in categories %}
<a href="{{ category.slug }}"/>
<p>{{ category }}</p>
</a>
{% endfor %}
{% for course in courses %}
<a href="{{ course.slug }}"/>
<p>{{ course }}</p>
</a>
{% endfor %}
Upvotes: 1
Views: 7507
Reputation: 416
@pygeek answer is not the right one:
@register.simple_tag(takes_context=True)
def absolute_url(context, relative_url):
request = context['request']
return request.get_absolute_uri(relative_url)
then, in the template:
{%load myapp_tags%}
...
{%url 'main:course_detail' category.slug as relative_url %}
<a href="{%absolute_url relative_url%}">...</a>
Note: This works only for templates invoked with
def my_view(request):
return render(request, 'template.html', {'context': 'data'})
It won't work if you directly render the template w/o the request like in
template = loader.get_template('template.html')
return HttpResponse(template.render({'context': 'data'}))
Upvotes: 0
Reputation: 7404
Get absolute url for a model object that correlates with a url.
A common idiosyncrasy in django is to define get_absolute_url
on the model and use reverse to build the url with context from the model. Keeping business logic contextual to the model in the model simplifies maintenance and automated testing. This pattern is used throughout the Django framework (ie: https://github.com/django/django/blob/555e3a848e7ac13580371c7eafbc89195fee6ea9/tests/contenttypes_tests/models.py#L16-L20).
urls.py
...
path('<int:course_id>/', views.CourseDetail.as_view(), name='course_detail'),
path('<int:category_id>/', views.CategoryDetail.as_view(), name='category_detail'),
...
models.py
class Course(models.Model):
def get_absolute_url(self):
return reverse('course_detail', kwargs={"id": str(self.id)})
class Category(models.Model):
def get_absolute_url(self):
return reverse('category_detail', kwargs={"id": str(self.id)})
courses.html
{% extends "main/header.html" %}
{% block content %}
{% for category in categories %}
<a href="{{ category.get_absolute_url }}"/>
<p>{{ category }}</p>
</a>
{% endfor %}
{% for course in courses %}
<a href="{{ course.get_absolute_url }}"/>
<p>{{ course }}</p>
</a>
{% endfor %}
Upvotes: 2