django 1.10 Application level URL does not recognize positional parameter - python

I'm trying to employ positional parameters on a view inside one app of my django application.
The app is called member. and the member/urls.py is called by the project trekfed:
trekfed.py
from member import urls as mviews
from public import views as pviews
urlpatterns = [
url(r'^member/', include(mviews)),
url(r'^admin/', admin.site.urls),
member\urls.py
urlpatterns = [
url(r'$', views.index, name='myprofile'),
url(r'^(?P<mbr>)/$', views.index, name='profile'),
url(r'^api/', include(router.urls)),
]
views.py
#login_required
def index(request, mbr=""):
print(mbr)
data = {}
if mbr:
user = User.objects.filter(Q(id=mbr)|Q(username=mbr)).values('User_id')
else:
user = request.user
data['user'] = user
data['member'] = models.Member.objects.get(User=user)
data['Address'] = models.Address.objects.filter(User=user).get(Primary=True)
data['Phone'] = models.Phone.objects.filter(User=user).get(Primary=True)
data['Family'] = models.Family.objects.filter(Primary=user.member)
data['Sponsor'] = models.Family.objects.filter(Dependent=user.member.pk)
data['rank'] = models.Promotion.objects.filter(User=user).latest('Date_Effective')
return render(request, "member/profile/page_user_profile.html", data)
when authenticated, if I go to http://localhost:8000/member/ I can see my profile. No problems.
If I go to http://localhost:8000/member/user2/ I still see my profile, not user2's.
Is there something that I'm missing here? Thanks.
Update 1
Tried:
url(r'^(?P<mbr>[a-zA-Z0-9]+)/$', views.index, name='profile'),
and
url(r'^(?P<mbr>.+)/$', views.index, name='profile'),
with no change.

Yes there is something you're missing here and it's called regex pattern.
In your urls the url(r'^(?P<mbr>)/$'), pattern does not matches anything (it's just an empty string, ''). You should first think of what pattern you want to capture (say only words, only digits, both words and digits, both word and digits and -, both words and digits and - and _ etc.
It all depends on the captured pattern. Take a look at here for some common url patterns and whatever you choose, place it after the > character (url(r'^(?P<mbr>regex_pattern_here)/$'),).
If you want to make it an optional field then you still have to enter a regex pattern (in case something matches) and leave your urls as is:
urlpatterns = [
url(r'^$', views.index, name='myprofile'),
url(r'^(?P<mbr>regex_pattern_here)/$', views.index, name='profile'),
url(r'^api/', include(router.urls)),
]
With this approach, both http://localhost:8000/member/ (without an mbr) and http://localhost:8000/member/user2/ (with mbr = user2) will hit the views.index view.
[BONUS]: You can test your regex patterns in http://pythex.org/

Related

How to check if the url is not in the i18n_pattern?

I need to check if the request path is outside the i18n_pattern, i.e. it should not have 'lang' prefix. For example, I have the following urls.py:
urlpatterns = [
path('api/', include('api.urls'), name='api'),
]
urlpatterns += i18n_patterns(
path('', include('core.urls'), name='index'),
prefix_default_language=False
)
The reverse for 'api' shows that it will not be prefixed whatever language is used. Are there any other ways to figure out that the path of the current request is not included in i18n_patterns? Thanks!
You can check if url is not in the i18n_pattern using django.urls.LocalePrefixPattern:
from django.urls import LocalePrefixPattern
pattern = LocalePrefixPattern()
def view(request):
if not pattern.match(request.resolver_match.route):
...

Django doesn't render the requested view

people. I'm a beginner Django developer so sorry if it's a basic question.
I have a webpage that shows a list of movies and each movie has a details view, but for some reason, the details view is never rendered.
#views.py
def index(request):
latest_movies = Movie.objects.order_by('-movie_id')[:5]
template = loader.get_template('ytsmirror/index.html')
context = {
'latest_movies' : latest_movies,
}
return HttpResponse(template.render(context, request))
def detail(request, movie_id):
movie = Movie.objects.get(movie_id=movie_id)
template = loader.get_template('ytsmirror/details.html')
context = {
'movie' : movie,
'plot': 'Lorem impsum',
}
return HttpResponse(template.render(context, request))
And my urls.py
#urls.py
from django.conf.urls import url
from . import views
app_name = 'ytsmirror'
urlpatterns = [
url(r'$', views.index, name='index'),
url(r'^(?P<movie_id>\d{4})$', views.detail, name='detail'),
]
When I try to reach /ytsmirror/4200/ for example, I don't get any error and Django apparently reaches the correct URL pattern but doesn't render the details view, it stays on the index view, without any change.
What am I doing wrong? Thanks.
url(r'$', views.index, name='index') matches the end of the string, so basically it will match any url, that's why your code isn't working. You need to replace url(r'$', views.index, name='index') with url(r'^$', views.index, name='index') so that it will match only empty url
^ asserts position at start of the string
$ asserts position at the end of the string, or before the line terminator right at the end of the string (if any)

Wrong url is getting matched

I simply want to get to another directory than index.
What I think Django is doing after I type in "localhost:8000/ysynch/":
Checking "ysynch/urls.py" (my root urls.py file)
Finding "ytlinks/" including "links.urls"
Matching with "ytlinks/" (in file "links.urls") and calling "views.ytlinks"
But instead, views.index is called. Where am I doing a mistake?
root\urls.py
C:\Users\xyron\Desktop\ysynch\ysynch\urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^ytlinks/', include('links.urls')),
url(r'^$', include('links.urls')),
]
links\urls.py
C:\Users\xyron\Desktop\ysynch\links\urls.py
urlpatterns = [
url(r'^ytlinks/', views.ytlinks, name='ytlinks'),
url(r'^$', views.index, name='index'),
]
Because paths are added to inclusion
url(r'^ytlinks/', include('links.urls')),
so you have following
# /ytlinks/ytlinks
url(r'^ytlinks/', views.ytlinks, name='ytlinks'),
# /ytlinks/
url(r'^$', views.index, name='index'),
so when you call /ytlinks/ you get to the view inside ytlinks which is index view again
the view you want to present is /ytlinks/ytlinks/
Checking "ysynch/urls.py" (my root urls.py file)
Finding "ytlinks/" including "links.urls"
Matching with "ytlinks/" (in file "links.urls") and calling "views.ytlinks"
The already matched part of the url will be excluded from further matching inside your includes.
So you basicly try to match "ytlinks/" again which would be true for "ytlinks/ytlinks/". You just want to match like this in your links\urls.py:
urlpatterns = [
url(r'^$', views.ytlinks, name='ytlinks'),
]
All of your urls in this file already match the first part "ytlinks/" and you only have to match the rest which is nothing or ^$ in your case.
The main part of your confusion is that you are expecting each urls.py to be trying to match the entire url, but instead you can think of include as doing a string concatenation and joining the previous parts of the url with the section of the url in the next urls.py
When django tries to match a url, it goes down the list of regexes until it finds one that matches so what you have is the following
r'^ytlinks/' + r'^ytlinks/' ==> views.ytlinks
r'^ytlinks/' + r'^$' ==> views.index
r'^$' + r'^ytlinks/' ==> views.ytlinks (not quite!)
r'^$' + r'^$' ==> views.index(not quite!)
So the first one of those that gets matched would be the second one for your url. $ in regex means end of a string so it won't bother to check anything that follows it here so you can rule out the last two regexes.
So your fix is threefold,
The links/urls you need to remove the first regex
url(r'^ytlinks/', views.ytlinks, name='ytlinks'),
You need to remove the $ from your inclusion url in the other urls.py
url(r'^', include('links.urls')),
You need to modify the views that each link should go to so eventually you end up with the following
root\urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^ytlinks/', include('links.urls')),
url(r'^', views.index, name='index'),
]
links\urls.py
urlpatterns = [
url(r'^$', views.ytlinks, name='ytlinks'),
]

Django reverse lookup rendering the same (wrong) template

I have a small resume site that is not rendering a different template upon hitting a reversed URL.
site/scripts/templates/scripts/index.html:
<p>were at main</p>
python
<br/>
bash
These links 'python' and 'bash' work in the URL bar, they take us to localhost:scripts/bash/ and localhost:scripts/python/, but the exact same webpage is displayed (index.html, or localhost:scripts/)
site/scripts/urls.py:
from django.conf.urls import patterns, include, url
from scripts import views
urlpatterns = patterns('',
url(r'$', views.index, name='index'),
url(r'python/$', views.access_python, name='python'),
url(r'bash/$', views.access_bash, name='bash'),
)
site/scripts/views.py:
from django.shortcuts import render
def index(request):
return render(request, 'scripts/index.html')
def access_python(request):
return render(request, 'scripts/python.html')
def access_bash(request):
return render(request, 'scripts/bash.html')
site/urls.py (main folder w/ settings.py):
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'scripts/', include('scripts.urls', namespace='scripts')),
)
clicking 'bash' should retrieve:
site/scripts/templates/scripts/bash.html:
<p>we're at bash</p>
Why would a reverse lookup reach the correct URL, but not call the associated view that that URL pattern wants? Thank you
The index regex was catching any possible pattern, since it matched any end of string. I found out by moving the index pattern after the other 2. It should be:
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^python/$', views.access_python, name='python'),
url(r'^bash/$', views.access_bash, name='bash'),
)
Any blank index urls (r'^$') need both start and end of string, to match the empty string after the first part of that pattern (in this case, 'scripts/')

Django urls.py bug - some patterns not working

I've encountered a one nasty bug in my code while developing a personal blog in Django. Basically, I've changed my urls.py file by adding a couple of rules to make certain views accessible.
urls.py
from django.conf.urls import include, url
from django.contrib import admin
from blog import views
urlpatterns = [
# Examples:
# url(r'^$', 'blogas.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^$', views.index, name='index'),
url(r'^(?P<slug>\w+)', views.view_post, name='view_blog_post'),
url(r'^about/$', views.about, name='about'),
url(r'^posts/$', views.posts, name='posts'),
]
Everything seems to be working except when I try access http://127.0.0.1:8000/about or /posts, Django throws out a 404 error. What is the reason of this? I've defined both rules but the system seems not to recognize the pattern - maybe I've mispelled something? Maybe I know nothing about url formatting (could be, it's my first time doing this stuff)?
A big thanks from a newbie programmer to everyone who finds the bug :)
The url-patterns are processed from top to bottom. Your third pattern ^(?P<slug>\w+) consumes everything, so about and posts is never reached.
An example: Django wants to find the view for the url about/. The patterns ^admin/ and ^$ do not match. But ^(?P<slug>\w+) does, because about starts with letters or numbers (the character sets contained in \w)
>>> import re
>>> re.search('^(?P<slug>\w+)', 'about/')
<_sre.SRE_Match object at 0x10b5b7be8>
So Django found a match, callBs views.view_post and finishes the request. That means, the more specific rule must come first. Better: avoid ambiguity.
You have to change position of url(r'^(?P<slug>\w+)', views.view_post, name='view_blog_post'),.
urlpatterns = [
# Examples:
# url(r'^$', 'blogas.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^$', views.index, name='index'),
url(r'^about/$', views.about, name='about'),
url(r'^posts/$', views.posts, name='posts'),
url(r'^(?P<slug>\w+)', views.view_post, name='view_blog_post'),
]
urlpatterns is list and order of urls is important.

Categories