I have a url defined as follows:
url(r'^details/(?P<id>\d+)$', DetailView.as_view(), name='detail_view'),
In my templates, I want to be able to get the following url: /details/ from the defined url.
I tried {% url detail_view %}, but I get an error since I am not specifying the id parameter.
I need the url without the ID because I will be appending it using JS.
How can I accomplish this?
Just add this line to your urls.py:
url(r'^details/$', DetailView.as_view(), name='detail_view'),
or:
url(r'^details/(?P<id>\d*)$', DetailView.as_view(), name='detail_view'),
(This is a cleaner solution - thanks to Thomas Orozco)
You'll need to specify that id is optional in your view function:
def view(request, id=None):
In urls.py:
(r'^bbb/id(?P<user_id>[0-9]+)/$', 'django.views.generic.simple.direct_to_template,
{'template': 'some.html', 'extra_context': {'user_id': user_id}}),
In some.html: {{ user_id }}
But there is an error: name 'user_id' is not defined (in urls.py)
So, how to declare that variable in urls.py and send it directly to 'some.html'???
Thanks.
You don't need to put it in extra_context. It's already captured in the URL, so is present in the params dictionary in the template: {{ params.user_id }}.
See the documentation - and also note that these old function-based generic views are deprecated, and you should be using the class-based TemplateView.
The variable really isn't declared in that python code. :) You do not need to set this variable in the view context. The view will receive named matches as **kwargs.
I am having issues with get_absolute_url in my django templates when using django page cms.
It returns an empty string and does not link to my required page.
I have the following Models, URLs templates and views
Models
class Body(models.Model):
...
url = models.SlugField(unique=True, help_text='---')
urls
(r'^news/', include('news.urls_news')),......
url(r'^/(?P<url>[\w\-]+)/$', 'news_view', name='news_view'),
View
def news_view(request, url):
new = get_object_or_404(Body, url=url)
return render_to_response('news/view.html', {
'news': news
}, context_instance=RequestContext(request))
Template
<li>{{ news.title }}</li>
the following code in my template returns the string I desire however this does to direct to my html page
<li>{{ news.title }}</li>
I know my everything links to the correct files because I have other views that work correctly. Could somebody please point me in the correct direction as to why get_absolute_url is not working correctly and why {{ news.url }} does not direct to the correct page. I am sure it has something to do with my urls.py however I am not certain.
Please bear with me I am new to django. All help is greatly appreciated.
Have you actually defined a get_absolute_url method on the News model? You don't show it.
Is there a way to have reversible, named URLs for Django flatpages (or multilingual-ng, which is flatpages + translations)?
If not, is there a similar app available which can have named URLs for pages which are editable through the admin? (And I'd rather avoid any behemoth CMSs, please.)
edit: Please see the comments in the answers below for more discussion and clarification of the question.
As the very last thing in your root URLConf, put
(r'^(?P<url>.*)$', 'django.contrib.flatpages.views.flatpage'),
Now you can use the {% url %} tag, with the view name flatpage and the keyword argument url. You can also use the reverse() function in views.
{% url %} template tag works with URLconf, whereas flatpages are handling nonexistent urls.
If you really want to reverse flatpages into URLs, my guess is that you have to write your own {% flatpage_url %} tag, which would looks like this:
#register.simple_tag
def flatpage_url(self, name):
return FlatPage.objects.get({param}=name).url
-- where {param} is one of FlatPage model fields.
Also, you can merge {% url %} and {% flatpageurl %} tags together, so that the latter fallbacks to reverse() in case FlatPage is not found (and reverse() is what {% url %} uses).
EDIT: I don't accept any more upvotes as James Bennet's answer is The One for this question (and I'm ashamed I overlooked such trivial solution) - so please upvote it.
Aren't the proposed solutions basically the same as hardcoding the URL in the template? What's the difference between hardcoding the URL in href="URL" vs. doing it in {% url URL %}?
I think a better solution is found on: How can I get the reverse url for a Django Flatpages template, proposed by bufh.
I think the optimal way of achieving this would be adding an extra 'name' field on the FlatPage model.
Before Django 1.0 there was an easy way to get the admin url of an object, and I had written a small filter that I'd use like this: <a href="{{ object|admin_url }}" .... > ... </a>
Basically I was using the url reverse function with the view name being 'django.contrib.admin.views.main.change_stage'
reverse( 'django.contrib.admin.views.main.change_stage', args=[app_label, model_name, object_id] )
to get the url.
As you might have guessed, I'm trying to update to the latest version of Django, and this is one of the obstacles I came across, that method for getting the admin url doesn't work anymore.
How can I do this in django 1.0? (or 1.1 for that matter, as I'm trying to update to the latest version in the svn).
You can use the URL resolver directly in a template, there's no need to write your own filter. E.g.
{% url 'admin:index' %}
{% url 'admin:polls_choice_add' %}
{% url 'admin:polls_choice_change' choice.id %}
{% url 'admin:polls_choice_changelist' %}
Ref: Documentation
from django.core.urlresolvers import reverse
def url_to_edit_object(obj):
url = reverse('admin:%s_%s_change' % (obj._meta.app_label, obj._meta.model_name), args=[obj.id] )
return u'Edit %s' % (url, obj.__unicode__())
This is similar to hansen_j's solution except that it uses url namespaces, admin: being the admin's default application namespace.
I had a similar issue where I would try to call reverse('admin_index') and was constantly getting django.core.urlresolvers.NoReverseMatch errors.
Turns out I had the old format admin urls in my urls.py file.
I had this in my urlpatterns:
(r'^admin/(.*)', admin.site.root),
which gets the admin screens working but is the deprecated way of doing it. I needed to change it to this:
(r'^admin/', include(admin.site.urls) ),
Once I did that, all the goodness that was promised in the Reversing Admin URLs docs started working.
Essentially the same as Mike Ramirez's answer, but simpler and closer in stylistics to django standard get_absolute_url method:
from django.urls import reverse
def get_admin_url(self):
return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name),
args=[self.id])
Using template tag admin_urlname:
There's another way for the later versions (>=1.10), recommend by the Django documentation, using the template tag admin_urlname:
{% load admin_urls %}
Add user
Delete this user
Where opts is something like mymodelinstance._meta or MyModelClass._meta
One gotcha is you can't access underscore attributes directly in Django templates (like {{ myinstance._meta }}) so you have to pass the opts object in from the view as template context.
For pre 1.1 django it is simple (for default admin site instance):
reverse('admin_%s_%s_change' % (app_label, model_name), args=(object_id,))
I solved this by changing the expression to:
reverse( 'django-admin', args=["%s/%s/%s/" % (app_label, model_name, object_id)] )
This requires/assumes that the root url conf has a name for the "admin" url handler, mainly that name is "django-admin",
i.e. in the root url conf:
url(r'^admin/(.*)', admin.site.root, name='django-admin'),
It seems to be working, but I'm not sure of its cleanness.
If you are using 1.0, try making a custom templatetag that looks like this:
def adminpageurl(object, link=None):
if link is None:
link = object
return "%s" % (
instance._meta.app_label,
instance._meta.module_name,
instance.id,
link,
)
then just use {% adminpageurl my_object %} in your template (don't forget to load the templatetag first)
For going to the admin page or admin login page we can use the below link. It works for me -
{% url 'admin:index' %}
This url takes me directly to the admin page.
Here's another option, using models:
Create a base model (or just add the admin_link method to a particular model)
class CommonModel(models.Model):
def admin_link(self):
if self.pk:
return mark_safe(u'<a target="_blank" href="../../../%s/%s/%s/">%s</a>' % (self._meta.app_label,
self._meta.object_name.lower(), self.pk, self))
else:
return mark_safe(u'')
class Meta:
abstract = True
Inherit from that base model
class User(CommonModel):
username = models.CharField(max_length=765)
password = models.CharField(max_length=192)
Use it in a template
{{ user.admin_link }}
Or view
user.admin_link()