Django (mezzanine) urls catching everything - python

I'm writing some custom views in the admin of a django project, should be simple. I have an "events" page and i want to create a "event" page (exactly the same as the django polls tutorial but in the admin, the event page would be the same as the detail view.)
No i cannot use the built in functionality as normal using foreignkeys etc and need to build from scratch.
urls.py:
admin.autodiscover()
def get_admin_urls(urls):
def get_urls():
my_urls = [
url(r'^my_cms/events', views.events, name="events"),
url(r'^my_cms/events/(?P<event_id>[0-9]+)/$', views.detail, name='detail'),
]
return my_urls + urls
return get_urls
admin_urls = get_admin_urls(admin.site.get_urls())
admin.site.get_urls = admin_urls
urlpatterns = i18n_patterns("",
("^admin/", include(admin.site.urls)),
)
So..
visiting .../admin/my_cms/events/ works
but .../admin/my_cms/events/xxxxxx just displays the same events page, rather than the detail view
if i change the url pattern to anything other than "events" eg:
url(r'^my_cms/events', views.events, name="events"),
url(r'^my_cms/[anything]/(?P<event_id>[0-9]+)/$',
then it will display the event view correctly...
So my question is why is the first url catching everything? i can put anything (.../admin/my_cms/events/anythingilike) and it will display the events page?
Joe

Because r'^my_cms/events' doesn't have a $ at the end. That means, only the beginning of this URL is checked, not the ending.
To illustrate, r'^my_cms/events' will match any URL that begins with 'my_cms/events', example:
'my_cms/events'
'my_cms/events/xxxxxx'
'my_cms/eventsxxxxxx'
So, even if you make a request to the detail view at 'my_cms/events/xxxxxx', the events page URL is matched. Once Django finds a match, it doesn't check further URLs and calls the related view.
To fix, add a $ sign at end of your URL regexp, like this:
url(r'^my_cms/events/$', views.events, name="events"),

Related

How to redirect in django while using django-hosts?

I'm using django-hosts package to manage content that's supposed to be set in various different subdomains. I started by making a view in which a form is used to change something. Once the form is validated and processed, user is supposed to be redirected to some other page. Looking through documentation there's an easy way to render():
settings_url = reverse('settings', host='dashboard')
return render(request, 'dashboard/settings.html', {'settings_url': settings_url})
However, there's no mention of redirect(). So how would I go about redirecting to somewhere else, instead of the usual return redirect("dashboard:settings")
myapp/hosts.py :
host_patterns = patterns('',
host(r'www', settings.ROOT_URLCONF, name='www'),
host(r'dashboard\.myapp\.com', 'dashboard.urls', name='dashboard'),
)
dashboard/urls.py
from .views import home, websitesettings
urlpatterns = [
url(r'^$', home, name='home'),
url(r'^settings/$', websitesettings, name='settings'),
]
Basically all I want is to redirect back to the same page after form is submitted (in the render example, I'm submitting a form to change certain website settings, which is a model on it's own, and then I want to redirect back to the same page after that).
Well took couple of different and convoluted tries, only to take a night off and come up with a solution that's ironically easy. Use of dajngos native redirect with django-hosts reverse function and it works like a charm:
from django_hosts.resolvers import reverse
return redirect(reverse('home', host='dashboard'))

How to ignore or redirect a http request in Django?

I use an Angular 4 frontend and Python Django in the backend.
If I click on the detail button I run the openDetail method in my component
openDetail(id:number){
this.router.navigate(['/motor/detail', {"id": id}])
}
the browser opens the detail component with the URL http://localhost:8000/motor/detail;id=21. Perfect. Important to know is, that I just need the id to work with them in my detail component.
But if I refresh the page I run into a 404 error. --> The current path, motor/detail;id=21, didn't match any of these. Well, this is also clear and jumped into the backend.
main - urls.py
#... some other urls...
url(r'^motor/', include('motorControll.urls')),
motors - urls.py
url(r'^$', views.index, name="index"),
url(r'^overview/$', views.MotorMapping.as_view({'get': 'getAllData'})),
url(r'^detail/$', views.index, name="index"),
url(r'^detail/(?P<id>\d+)/$', views.MotorMapping.as_view({'get': 'getById'})),
url(r'^detail/save/$', views.MotorMapping.as_view({'post': 'save'})),
How can I ignore this call or run a redirect to the index page?
I need the id, because the next step, after load the detail page is to load the details by this url http://localhost:8000/motor/detail/21 , it returns JSON with all data.
Your URL mapping in motors.urls is configured properly for the URL /motor/detail/21 -- so it works. But it's not configured for a URL like /motor/detail;id=21.
If you added another route to motors.url so that /motor/detail;id=21 works -- something like url(r'^detail;id=(?P<id>\d+)$', views.MotorMapping.as_view({'get': 'getById'})), then the URL would return raw JSON, so that's NOT what you want.
Instead, the actual solution is more complicated -- you want the URL to be routed to your single page app, and not Django, and have Angular take care of loading the data from Django Rest Framework.

URL Regular Expression mismatch

I am trying to learn Django and I am currently stuck in an issue.
I created an app Contact and run the server, I get the error.
The error page displayed by server:
The urls.py file in the app Contact
urls.py in conatct
When the pattern in urls.py is
urlpatterns =[url(r'^$', views.form, name ='form')]
it works properly, but not with other pattern shown in the picture
Your help would be greatly appreciated.
The Page not found error message tells you what went wrong: For the URL (/contact) you requested, Django was unable to find a suitable view. Because you have debugging enabled, you get some information, including a list of registered views.
First things first: You probably have url(r'^contact/', include('contact.urls')) somewhere in your top level urls.py. This makes the URLs defined in the contact/urls.py available under the prefix /contact.
With
urlpatterns = [
url(r'^form/', views.form, name='form'),
]
in contact/urls.py you are telling Django that you want urls starting with contact/form/ to be handled by views.form.
Consequently, when you access http://localhost:8000/contact/ in your browser, there is no view associated with that URL, hence the 404. Your view is reacting to to http://localhost:8000/contact/form, not http://localhost:8000/contact.
When you change the URL pattern to
urlpatterns = [
url(r'^$', views.form, name='form'),
]
you modify the URL views.form reacts to.

How to change the url in urls.py? (Django app)

I'm trying to change the url of http://localhost:8000/stories-and-literature/fairy-tales/ to http://localhost:8000/stories-and-literature/classic-literature/, and I'm not to sure how I can change it in my urls.py. So far, I have this code in urls.py:
from django.conf.urls import patterns, url
from topictree import views
urlpatterns = patterns('',
(r'^$', 'topictree.views.index'),
(r'^(?P<slug>\D+)/$', 'topictree.views.tree')
)
I want to change the slug of url from "fairy-tales" to "classic-literature" because I want to present the url like a tree. In this case, both "fairy-tales" and "classic-literature" are children of "story-and-literature", so when I click on the "fairy-tales" link and then click on the "classic-literature" link, the "fairy-tales" slug should be removed, and be replaced by the "classic-literature" slug.
I was thinking of changing the url in views.py instead of urls.py since views.py contains the control flow of the program. Is it possible to change the url in views.py instead of urls.py?
Any help would be much appreciated.
Foo Bar User's link is a good place to start but judging by your question I would say you should go straight to the Django Docs
https://docs.djangoproject.com/en/1.6/topics/http/urls/
That should get you back on your feet. :)

Multiple django apps using same url pattern

I'd like to run two apps with the same url patterns. I would like to avoid having an app-specific slug like domain.com/pages/something-here or domain.com/blog/something-there.
I tried this:
# urls.py
urlpatterns = patterns('',
url(r'^$', 'my.homepage.view'),
url(r'^admin/', include(admin.site.urls)),
url(r'^', include('pages.urls')),
url(r'^', include('blog.urls')),
)
# pages/urls.py
urlpatterns = patterns('',
url(r'^(.+)/$', views.page),
)
# blog/urls.py
urlpatterns = patterns('',
url(r'^(.+)/$', views.post),
)
My code doesn't work, whichever include comes first (here, pages.urls) works ok, other urls (for blog) throw 404.
Thanks in advance
EDIT: I did it like this: created glue.py in the same directory as settings.py. It will handle my homepage and this dispatcher view:
def dispatcher(request, slug):
try:
page = get_object_or_404(Page, slug=slug)
return render(request, 'pages/page.html', {'page': page})
except:
post = get_object_or_404(Post, slug=slug)
return render(request, 'blog/post.html', {'post': post})
I don't know if it's ok. I hope there is a better way.
Thanks for the comments.
I don't know if this is a better answer. But, if these situations are satisfied for you..
if your django app is based on django template rendering.
The url you are talking about, need not be accessed directly by typing the endpoint in the browser itself.
Then, maybe you could consider url namespaces and template redirections.
https://docs.djangoproject.com/en/1.11/topics/http/urls/#url-namespaces
This doesn't work because django urls are resolved in order, meaning that the first url that matches the regexp will be the resolved one. In your case, the the urls included from the blogs application will never be searched, as django already resolved the url on the pages includes line.
Also, the django url module is not supposed to know if a certain page or blog post exists, as i believe in your application this is determined with a database lookup.
The urls module just executes the view that is connected to the first regexp that matches.
You should change your logic, e.g. with perpending "blog/" to blog urls (what's wrong with that?)
url(r'^blog/', include('blog.urls')),
url(r'^', include('pages.urls')),
Notice that the i moved the blog url up, as most generic regxexp should always be the last to be tried by django url resolver.
Alternatively, you could code a proxy view that tries both blog posts and pages. but it doesn't seem the best way to do it to me.
How would you like this to work? They're both using the same URL (which of course is causing problems). How would a user get to a "page" rather than a "blog" or vice versa?
In general, you can't have overlapping URLs in your URL patterns (without including additional data).
EDIT:
So you want the first app to check if it has a view to match the URL and next to take over if the first doesn't? You could do something complicated like writing a "view matcher" to do want you want, but there are much more straigtforward solutions.
The easiest way would be to alter the slug generation function for one of your apps. Have one use some delimeter other than underscores, or always append the name of the app to the slug. This way you could find pages because their url would be "some-slug-page" and blogs would be "some-slug-blog", which you could then write a URL pattern for. If you don't want to add the entire URL, you can append/prepend just the first letter, or whatever you want.
Just think about a way that's acceptable to you to generate URLs for each app which, just by reading the URL, lets you know which app the page belongs to.

Categories

Resources