I don't understand my problem here is my code:
urls.py
urlpatterns = patterns('blog.views',
...
url(r'^(?P<slug>.+)$', 'blog', name='blog'),
url(r'^membres$', 'membres', name='membres'),
)
views:
def blog(request, slug):
posts = Post.objects.filter(blog__slug=slug)
return render(request, 'blog/blog.html', locals())
def membres(request):
membres = User.objects.all()
return render(request, 'blog/membres.html', {'membres': membres})
Here is my link in my base.html template
<li>List</li>
When I click the link it redirect me to the blog view and then render blog.html instead of using membres view.
I got no error in console or in my template.
All my code is in my app called 'blog'
Django uses the first pattern that matches. Your first URL regex matches any string, including /membres, so Django never tries the second one. I suggest something like this:
urlpatterns = patterns('blog.views',
url(r'^/blog/(?P<slug>[-\w]+)/$', 'blog', name='blog'),
url(r'^membres/$', 'membres', name='membres'),
)
If you must have a catch-all pattern, it should be the last one in the list, so the other patterns have a chance to match before:
urlpatterns = patterns('blog.views',
url(r'^membres/$', 'membres', name='membres'),
# other patterns...
url(r'^(?P<slug>[-\w]+)/$', 'blog', name='blog'),
)
It's also a good habit to always include the trailing slash (Django will append it to requests by default). To match a slug, I suggest [-\w]+, which will match any sequence of alphanumeric characters, _ and -.
It's because urlresolver takes patterns from top to bottom and 'membres' matches (?P<slug>.+) so urlresolver returns blog view. Put more concrete urlpatterns higher. Also I suggest using more specific characters in slug regexp, i.e. (?P<slug>[A-Za-z0-9_\-]+).
Django stops at the first URL pattern that matches. This means that your
blog view -- which simply looks for one or more characters -- will interpret your mysite.com/membres URL to be a blog post with the slug membres.
To fix it, try swapping the order of your URL patterns:
urlpatterns = patterns('blog.views',
...
url(r'^membres$', 'membres', name='membres'),
url(r'^(?P<slug>.+)$', 'blog', name='blog'),
)
In general, you want your most general patterns at the bottom for exactly this reason.
Related
I am relatively new to Django. I've set up my URLs in my core/urls.py file this way and I do get a 404 error when I opened localhost:8000/posts/ on the browser. Code is shown here
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<slug:slug>/', views.SingleView.as_view(), name='single'),
path('posts/', views.PostsView.as_view(), name='posts'),
]
However, everything works fine when I reverse the slug and posts/ to make the posts come before the slug. Like this:
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('posts/', views.PostsView.as_view(), name='posts'),
path('<slug:slug>/', views.SingleView.as_view(), name='single'),
]
Please help me figure it out.
That's how Django (and most other frameworks) work. When a request comes in, Django will check the routes that you specified and it uses the same order that you specified them. So in your first example, '' is the first one and then '<slug:slug>/' and 'posts/' after that. this means that every time a request comes in, Django will check for routes on that order. basically how a for loop works:
Example URL: yoursite.com/posts/
Path: "posts/"
routes = ["", "<slug:slug>/", "posts/"]
path = "posts/"
for route in routes:
if route == path:
# use view for this route
return
So in this case, it will match with index 1 which is <slug:slug>/, and returns the view specified for it.
Now to understand why <slug:slug>/ == "posts/" returns True you need to understand what slug means in Django:
slug - Matches any slug string consisting of ASCII letters or numbers, plus the hyphen and underscore characters. https://docs.djangoproject.com/en/3.1/topics/http/urls/#example
So it will accept any path that matches those requirements and posts/ actually matches those requirements. Django doesn't check any other routes if it finds a match so it will never gets to path('posts/', views.PostsView.as_view(), name='posts') because '<slug:slug>/' has higher priority being in the smaller index over 'posts/'. And you probably check for that slug in your models which isn't there so it will return a 404.
By changing the route order, you change the routes to ["", "posts/", "<slug:slug>/"]. Now "posts/" has higher priority and django will use PostsView.
I have url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic') in urls.py but when I try to go to localhost:8000/topics/1 it tells me that it tried one pattern: topics/(?P<topic_id>**\\**d+)/$
I would think it would be topics/(?P<topic_id>**\**d+)/$
I'm using a book called The Python Crash Course (1st edition)(ch. 18).
This is a local server using Django 1.11 with Python. I've tried a lot of reformatting on the url pattern but I am new at this so I don't know what else to do.
...
urlpatterns = [
url(r'^$', views.index, name='index'),
# Show all topics.
url(r'^topics/$', views.topics, name='topics'),
# Detail page for a single topic.
url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
]
I expected it to pop up with the correct page but it always says 'NoReverseMatch at /topics/01/'
So you've forgotten the trailing slash at the end of your URL, hence why it's not matching.
You could remove the slash from the regex, but that would shift the problem: it wouldn't work if you put a slash.
I guess you could end the pattern with /?$, but here's a solution that's probably more robust: Jiaaro's answer to: django urls without a trailing slash do not redirect
Basically:
check your APPEND_SLASH setting in the settings.py file
I'm having the 404 error when trying to handle a view that is not related to the main page. For example, if I initially start at the main page home, and want to navigate to another page called, otherpage, I receive a 404 otherpage.html not found.
The way I'm doing is based off intuition. So if there's a better way to do this, please mention it:
in the file:
prd/
views.py
url.py
otherstuffthatshouldbehere.py..
I have views.py (this is where I think the error is):
from django.shortcuts import render
def home(request):
context = {}
template = "index.html"
return render(request, template, context)
def otherpage(request):
context = {}
template = "otherpage.html"
return render(request, template, context)
Then urls.py:
from django.conf.urls import patterns, include, url
from django.contrib import admin
urlpatterns = patterns('',
url(r'^$', 'prd.views.home', name='home'),
url(r'^$', 'prd.views.otherpage', name='otherpage'),
url(r'^admin/', include(admin.site.urls)),
)
This returns a 404 for the otherpage.html. I have the template directory working fine. But how do I go about handling multiple views?
EDIT:
Upon adding:
url(r'^otherpage$', 'prd.views.otherpage', name='otherpage'),
I received this error:
Using the URLconf defined in prd.urls, Django tried these URL patterns, in this order:
^$ [name='home']
^about$ [name='about']
^projects$ [name='projects']
^admin/
The current URL, about.html, didn't match any of these.
The urlpatterns starts at the top and then goes down until it matches a URL based on the regex. In order for Django to serve up the page located at otherpage.html there has to be a URL defined in urlpatterns that matches otherpage.html otherwise you will get the 404.
In this case you have:
url(r'^$', 'prd.views.home', name='home'),
url(r'^$', 'prd.views.otherpage', name='otherpage'),
Note that nothing will ever get to otherpage here because home has the same pattern (regex) and will therefore always match first. You want to have a different URL for both those so that you can differentiate between them. Perhaps you could do something like:
url(r'^$', 'prd.views.home', name='home'),
url(r'^otherpage.html$', 'prd.views.otherpage', name='otherpage'),
After making this change you now have a match for otherpage and hopefully no more 404.
EDIT:
url(r'^otherpage.html$', 'prd.views.otherpage', name='otherpage'),
This matches www.example.com/otherpage.html but it will not match www.example.com/otherpage
To match www.example.com/otherpage you need to use:
url(r'^otherpage$', 'prd.views.otherpage', name='otherpage'),
Note the difference in the regex, there's no .html here. The regex matches exactly what you put in it.
I have this regex in my urls.py for my blog app and I'd like to know why is it not working.
url(r'^/tag/(?P<tag_text>\w+)/$', views.tag, name='tag'),
and I have defined this in the blog's views.py
def tag(request,tag_text):
and this in the application's urls.py
url(r'^blog/', include('blog.urls')),
I have tried
localhost/blog/tag/sport
but I still get: The current URL, blog/tag/sport, didn't match any of these.
Am I doing something wrong?
Your pattern is trying to match an extra /, since your include url requires a trailing slash, and your tag url is trying to match a leading slash.
You should remove either one to make it work:
# tag url in blog/urls.py
url(r'^tag/(?P<tag_text>\w+)/$', views.tag, name='tag'),
# include in project/urls.py
url(r'^blog/', include('blog.urls')),
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.