django reverse() failing - django

simply put mentions of reverse() anywhere in my project were failing, and so was {% url %}.
I have since made some progress if you scroll to the bottom!
relevant files
root/urls.py
from django.conf.urls.defaults import patterns, include, url
from django.contrib.staticfiles.views import serve as serveStatic
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
(r'^dbrowse/', include('dbrowse.urls')),
(r'^static/', serveStatic),
url(r'^$', 'core.views.viewHallo',name='home'),
)
root/core/views.py
from django.shortcuts import render_to_response
from django.template.context import RequestContext
from site import site_store
def viewHallo (request):
pass
return render_to_response ('core.html',
{'site':site_store,
'title':'i am the hallo view',
'content':'Hallo World!',},
context_instance=RequestContext(request))
Notes
I first noticed the reverse() failing when i had a file called site.py in my project that tried to call reverse(). I was using it to store site settings. I was using the file because
I didn't want to use the bother the database with data that would rarely change.
If I nuked my projects database I didn't want my site settings also going down
I have since found a way to use models to achieve the two goals.
but all that is just extra background info, in case you here someone commenting about a site.py.
update 25/02/11
well here goes!
first notice that urls.py has (r'^dbrowse/', include('dbrowse.urls')). that caused reverse() to fail. I'll explain later...
as for the template tag, I've discovered that the {% url %} doesnt take variables. I took this completely for granted.In fact when I was testing the template tag, i'd just go in and hard code something such as {% url 'home' %} which would work and sometimes i'd test {% url home %} with home being a variable. I din't even see this as being completely different test cases.
But i now know {% load url from future %} allows you to use variables as arguments to {% url %}
Anyway, now back to the (r'^dbrowse/', include('dbrowse.urls')) in urls.py
I had a folder like so
project\
--dbrowse\
__init__.py
urls.py
now this is dbrowse/urls.py
from django.conf.urls.defaults import patterns, url
#databrowse
from django.contrib import databrowse
databrowse.site.register(MyModel)
urlpatterns = patterns('',
url(r'(.*)',databrowse.site.root, name='dbrowse'),)
this was my attempt to avoid having to put databrowse.site.register(MyModel) in my project's root urls.py like the docs suggested. I dont like the idea of polluting my projects main urls.py with databrowse.site.register(MyModel)
however I still dont understand why this caused reverse() to break. but i'm supecting it's to do with (.*) being in the pattern.

Related

Python - Django add multiple urlpatterns for multiple views of template

I'm very very new to Python 3 and Django and I get to the following problem: I use a standard Template and now how to set it up when there is 1 view. But I don't get the code right for multiple views. I currently run the page locally
At the moment I have tried to change different orders within urlpatterns, and they do work when only 1 url in in there, but I can't get the second one in
views.py
from django.shortcuts import render, render_to_response
# Create your views here.
def index(request):
return render_to_response('index.html')
def store(request):
return render_to_response('store.html')
urls.py
from django.conf.urls import include, url
from django.contrib import admin
from myapp import views as views
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^store/$', views.store, name='store'),
url(r'^admin/', admin.site.urls)
]
urlpatterns += staticfiles_urlpatterns()
I would like the url pattern that lets me go to the index view and the store view
EDIT:
Full code is shared via: https://github.com/lotwij/DjangoTemplate
The error in the comments shows you are going to http:/127.0.0.1:8000/store.html, but your URL pattern url(r'^store/$', ...) does not include the .html, so you should go to http:/127.0.0.1:8000/store/.
The Django URL system uncouples the URL from the name of the template (sometimes the view doesn't even render a template!). You could change the regex to r'^store.html$ if you really want .html in the URL, but I find the URL without the extension is cleaner.

How can I fix my Wagtail URL namespace and explorer when adding wagtail to a current project?

My issue is my URL is coming up mysite.com/test-news-1/ instead of mysite.com/news/test-news-1/
I've started a new project using cookiecutter-django. I then wanted to add wagtail cms to the project and followed the docs to do so.
I get the wagtail admin page up fine, at /cms/ instead of /admin/ like it says to do on this page - http://docs.wagtail.io/en/v1.3.1/getting_started/integrating_into_django.html
I added a few apps just to practice and get used to wagtail, one directly copied from the wagtail blog example. This is where my issue starts.
The wagtail admin Explorer does not list my apps like it shows on the wagtail site https://wagtail.io/features/explorer/, instead it just says "Welcome to your new Wagtail site!" When I select Add Child Page it allows me to select the app pages I have set up and seems to go by my models just fine. But when I post something and click go to live site it comes up as mysite.com/blog1/ instead of mysite.com/blog/blog1/
I believe my problem that I dont understand the final part of the doc page that I linked above. It says,
Note that there’s one small difference when not using the Wagtail
project template: Wagtail creates an initial homepage of the basic
type Page, which does not include any content fields beyond the title.
You’ll probably want to replace this with your own HomePage class -
when you do so, ensure that you set up a site record (under Settings /
Sites in the Wagtail admin) to point to the new homepage.
I tried adding the homepage model from the doc page, but this didn't seem to help at all.
I'm very inexperienced, this is my urls.py file, if you need to see other files please let me know.
urls.py
from __future__ import unicode_literals
from django.conf import settings
from django.conf.urls import include, url
from django.conf.urls.static import static
from django.contrib import admin
from django.views.generic import TemplateView
from django.views import defaults as default_views
from wagtail.wagtailadmin import urls as wagtailadmin_urls
from wagtail.wagtaildocs import urls as wagtaildocs_urls
from wagtail.wagtailcore import urls as wagtail_urls
urlpatterns = [
url(r'^$', TemplateView.as_view(template_name='pages/home.html'), name="home"),
url(r'^about/$', TemplateView.as_view(template_name='pages/about.html'), name="about"),
# Django Admin, use {% url 'admin:index' %}
url(settings.ADMIN_URL, include(admin.site.urls)),
# User management
url(r'^users/', include("contestchampion.users.urls", namespace="users")),
url(r'^accounts/', include('allauth.urls')),
# Your stuff: custom urls includes go here
# Wagtail cms
url(r'^cms/', include(wagtailadmin_urls)),
url(r'^documents/', include(wagtaildocs_urls)),
url(r'', include(wagtail_urls)),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
if settings.DEBUG:
# This allows the error pages to be debugged during development, just visit
# these url in browser to see how these error pages look like.
urlpatterns += [
url(r'^400/$', default_views.bad_request, kwargs={'exception': Exception("Bad Request!")}),
url(r'^403/$', default_views.permission_denied, kwargs={'exception': Exception("Permission Denied")}),
url(r'^404/$', default_views.page_not_found, kwargs={'exception': Exception("Page not Found")}),
url(r'^500/$', default_views.server_error),
]
These two url confs are in conflict =
url(r'^$', TemplateView.as_view(template_name='pages/home.html'), name="home"),
url(r'', include(wagtail_urls)),
One must change, otherwise Django will always resolve the base url of `yourdomain.com/' to the first entry. One easy way to fix this is to update the second-
url(r'^content/', include(wagtail_urls)),
Now your Wagtail root page will be accessible at yourdomain.com/content.
As for mysite.com/blog/blog1/ not coming up, that Url would assume that, from your Wagtail root page, there's a page w/ slug 'blog', and then a child page of that with slug blog1. The tree structure of your Wagtail site determines the URLs by default. If you want to override that you'll have to use the RoutablePageMixin as described here.

Django URL namespaces - the template has to know its namespace?

I've been tinkering with (my first) Django project that started out with Django 1.6 and has just recently moved to Django 1.8. I've also been working through Django Patterns & Best Practices, learning how I should have structured it all along :-)
My project has several sub-apps and a typical main urls.py with lines like:
(r'', include('noc.apps.frontpage.urls')),
Within each app, I've prefixed all the URL names with the app name, e.g. frontpage_edit_page and used {% url %} throughout the templates to refer between views.
Then I read about URL namespaces, and thought I could de-uglify my URL names. As I first interpreted it, if I added a namespace to each include() in the main urls.py, everything would function as before, because the URL names referred to would all be resolved by the 'local' app. But it doesn't seem to work that way.
With this in the main urls.py:
(r'', include('noc.apps.frontpage.urls', namespace='frontpage', app_name='frontpage')),
This in the app urls.py:
url(r'^frontpage/edit/(?P<slug>[A-Za-z0-9]+)$', views.edit_page, name='front_page_edit_page'),
and {% url 'front_page_edit_page' slug=page.slug %} in a template inside that app, I get a NoReverseMatch exception with 0 URLs tried.
All the examples I can find are talking about prefixing URLs with the namespace - frontpage:front_page_edit_page but 1) how is this an improvement on the previous app prefix on the URL name? and 2) how could you ever have two instances of the same app, which is supposed to be a benefit... So I'm assuming that this is for linking between apps, not within apps.
So what is it that I am missing? Do I need to embed the app_name or namespace in my view function too? It's true that if I do prefix all my URL names with the namespace, even within the app, I get a rendered page, but it seems to defeat the point.
The way you're meant to do it is indeed to add the namespace to the URL tag;
{% url 'frontpage:edit_page' slug='SLUG' %}
But it would be better practice to structure your main project URls file like this;
urlpatterns = patterns(
'',
url(r'^admin/', include(admin.site.urls)), # NOQA
url(r'frontpage', include('noc.apps.frontpage.urls', namespace='frontpage', app_name='frontpage')),
That way you can specify the path for each app in the main URLs file, and avoid repetition;
urlpatterns = patterns(
'noc.apps.frontpage.views',
url(r'^edit/(?P<slug>[A-Za-z0-9]+)$', 'edit_page', name='edit_page'),
With this you can introduce a RESTful URL structure to all your apps so you'll end up with things like;
urlpatterns = patterns(
'',
url(r'^admin/', include(admin.site.urls)), # NOQA
url(r'frontpage/', include('noc.apps.frontpage.urls', namespace='frontpage', app_name='frontpage')),
url(r'contact/', include('noc.apps.contact.urls', namespace='contact', app_name='contact')),
url(r'myapp/', include('noc.apps.myapp.urls', namespace='myapp', app_name='myapp')),
All your apps can follow a similar structure then;
urlpatterns = patterns(
'noc.apps.contact.views',
url(r'^$', 'index', name='index'),
url(r'^add/$', 'add', name='add'),
url(r'^edit/(?P<slug>[A-Za-z0-9]+)$', 'edit', name='edit'),
urlpatterns = patterns(
'noc.apps.myapp.views',
url(r'^$', 'index', name='index'),
url(r'^add/$', 'add', name='add'),
url(r'^edit/(?P<slug>[A-Za-z0-9]+)$', 'edit', name='edit'),
Multiple instances of frontpage could be achieved using the top level namespace;
urlpatterns = patterns(
'',
url(r'^admin/', include(admin.site.urls)), # NOQA
url(r'frontpage/', include('noc.apps.frontpage.urls', namespace='frontpage1', app_name='frontpage')),
url(r'frontpage/', include('noc.apps.frontpage.urls', namespace='frontpage2', app_name='frontpage')),
That way you should be able to target the top level instance namespace, followed by the app namespace like this;
{% url 'frontpage1:frontpage:edit_page' slug='SLUG' %}
{% url 'frontpage2:frontpage:edit_page' slug='SLUG' %}
But if you would like to keep your template links more generic I believe you can leave out the top level namespace and django will resolve to the current app which you have to add to the request object. This is detailed at the end of Reversing Namespaced URLs
For anyone to reference.
This worked for me, Django 2.2.2
# project urls.py
# DjpollsConfig is my app config
from djpolls.apps import DjpollsConfig
djpolls_app_name = DjpollsConfig.name
urlpatterns = [
path(djpolls_app_name, include('djpolls.urls', namespace='djpolls_app_name'))
]
# app urls.py
from django_proj.urls import djpolls_app_name
app_name = djpolls_app_name
# app template
{% url 'djpolls_app_name:detail' question.id %}
Hope it helps!
Try this
(r'', include('noc.apps.frontpage.urls', namespace = 'abc')),
and then in your templates:
{% url 'abc:frontpage:front_page_edit_page' slug=page.slug %}

Using a name for dummy url patterns in django

I have a project with an app named exams. Right now my index page is the index page of one of these apps. So the url patterns is something like this:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^', include('exams.urls', namespace="exams")),
)
However it is possible that in future I want to create a new view for my index page and change the url patterns to something like this:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^exams/', include('exams.urls', namespace="exams")),
url(r'^/$', 'mysite.views.index', name="index"),
)
I want to create some links in my template to index whether it loads the exams app or another view. So I tried to use the name argument for the url method(like above) but it seems it's not working. When I use {% url 'index' %} in my template it returns the following error:
Reverse for 'index' with arguments '()' and keyword arguments '{}' not found. 0 pattern(s) tried: []
UPD: I forgot to mention that I tried using the following code:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^', include('exams.urls', namespace="exams"), name="index"),
)
And I got the error I wrote above.
UPD2: To clarify the problem more:
Right now when I go to http://mydomain/ I'll see my app index. But maybe in the future I like to change my index page and use another view for creating it. So when I go to http://mydomain/ I'll see the page rendered by that view and by going to http://mydomain/exams I'll see my apps index pages. In that case my urls.py will be sth like the second code I wrote above in which I can easily link to index page using {% url 'index' %} tag. However for now I'm using the code I wrote in my first update. I want my templates to render {% url 'index' %} as a link to my index page(instead of using {% url 'exams:index' %} so when I later change the urls.py code I won't have to change all of my templates.
If I understand well, you want an index view that could be easily changed, while not changing the links pointing to it in your templates. You can use your index view as a wrapper for other views ie:
def a_view_that_will_show_all_the_exams(request):
# this is the page displayed for now as default, but this could change
# some logic here
def another_view_that_could_become_the_home_page(request):
# some logic here
def index(request):
return a_view_that_will_show_all_the_exams(request)
# or another_view_that_could_become_the_home_page
# or return exams.views.whatever_view
This way you can easily change the result of the index view while keeping your links static.
If I understood you correctly, right now you don't have a url with the name index, in his case it is normal that when the template renders, it tries to find a url named index, and when it doesn't find it, it fails. What you might need is create the url and redirect to another view for now, like explained here:
Redirect to named url pattern directly from urls.py in django?
UPDATE:
I'm still not completely sure of what you want (sorry about that), but I suspect what you want to do is something similar to this:
from django.conf.urls import patterns, include, url
from django.core.urlresolvers import reverse_lazy
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^exams/', include('exams.urls', namespace="exams")),
url(r'^/$', RedirectView.as_view(url=reverse_lazy('exams:index'), name="index"),
)
The solution that Raphael is giving you is similar, but the user will not be redirected (with both urls the user will see the same content). Maybe that is what you are looking for?

Django admin urlpatterns problems

I'm trying to complete a Django tutorial (https://docs.djangoproject.com/en/dev/intro/tutorial03/) and have run into a problem which, I think, is my understanding of regular expressions and the include() function.
My problematic urls.py:
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^polls/', include('polls.urls')),
)
which, leads me (upon browsing to http://localhost:8000/admin/) to the detail view of polls.urls - the code of which is:
from django.conf.urls import patterns, url
urlpatterns = patterns('polls.views',
url(r'^$', 'index'),
url(r'^(?P<poll_id>\d+)/$', 'detail'),
url(r'^(?P<poll_id>\d+)/results/$', 'results'),
url(r'^(?P<poll_id>\d+)/vote/$', 'vote'),
)
I get why it's matching to polls and getting taken through to polls.urls. Any ideas?
Note: when I comment out the url(r'^polls/, include('polls.urls')), line I can see the admin page again
Thanks!
O.K - so I managed to fix this but am not entirely sure how. It was a case of leaving it and working on other problems and when I came back it was fixed! So, things that I changed:
1.) included {% load url from future %} to ensure forward compatibility in my templates
2.) changed the form action in detail.html to <form action="/polls/{{ poll.id }}/vote/" method="post"> (from <form action="{% url 'polls.views.vote' poll.id %}" method="post">
3.) finally, and probably most importantly - sorted my syntax out! In my views.py file I had Return HttpResponseRedirect(reverse('polls_results', args=(p.id,))) and not Return HttpResponseRedirect(reverse('poll_results', args=(p.id,)))
I still don't know which did it but, if anybody is in the same position as me, some combination of those 3 will do it!