Multiple django apps using same url pattern - python

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.

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'))

Django (mezzanine) urls catching everything

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"),

Django redirect based on parts of url pattern

So I have this small simple problem that I can't really find a solution to.
I would like to redirect all links on the form r'^blogg/ to r'^blog/'. I would think there is a solution similar to the accepted answer in this post here, but it doesn't work that well. Note that the blog-application has many sub-url-patterns, so a solution like RedirectView.as_view(url="/blog/") would not work.
In my main urls.py
urlpatterns = patterns('',
url(r'^blogg/', RedirectView.as_view(pattern_name="blog")),
url(r'^blog/', include("blog.urls", namespace="blog")),
The solution above returns HTTP 410 (Gone) for all sub-urls of blogg. I suspect this is due to the missing url argument in RedirectView.as_view().
Thanks in advance for all answers!
You won't be able to do this entirely in urls.py. But a simple view function could work:
url(r'^blogg/(?P<rest>.+)$', views.redirect_prefix),
from django.shortcuts import redirect
def redirect_prefix(request, rest):
return redirect('/blog/{}'.format(rest))
What about
urlpatterns = patterns('',
url(r'^blogg/',include("blog.urls", namespace="ignoreme") ),
url(r'^blog/', include("blog.urls", namespace="blog")),
it both should strip the first part (blog/ or blogg/) from url and then manage the rest equally. And if you will use {% url "blog:this_view" %} then on next page your customer will be on the blog/ part anyway

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. :)

Django index page best/most common practice

I am working on a site currently (first one solo) and went to go make an index page. I have been attempting to follow django best practices as I go, so naturally I go search for this but couldn't a real standard in regards to this.
I have seen folks creating apps to serve this purpose named various things (main, home, misc) and have seen a views.py in the root of the project. I am really just looking for what the majority out there do for this.
The index page is not static, since I want to detect if the user is logged in and such.
Thanks.
If all of your dynamic content is handled in the template (for example, if it's just simple checking if a user is present on the request), then I recommend using a generic view, specificially the direct to template view:
urlpatterns = patterns('django.views.generic.simple',
(r'^$', 'direct_to_template', {'template': 'index.html'}),
)
If you want to add a few more bits of information to the template context, there is another argument, extra_context, that you can pass to the generic view to include it:
extra_context = {
'foo': 'bar',
# etc
}
urlpatterns = patterns('django.views.generic.simple',
(r'^$', 'direct_to_template', {'template': 'index.html', 'extra_context': extra_context }),
)
I tend to create a views.py in the root of the project where I keep the index view.

Categories

Resources