I don't know if its me but {% tag ??? %} has bee behaving a bit sporadically round me (django ver 1.2.3). I have the following main.html file:
<html>
{% include 'main/main_css.html' %}
<body>
test! logout
test! logout
</body>
</html>
with the urls.py being:
from django.conf.urls.defaults import *
import settings
from login.views import *
from mainapp.views import *
from client.views import *
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Example:
# (r'^weclaim/', include('weclaim.foo.urls')),
(r'^login/$', 'login.views.login_view'),
(r'^logout/$', 'login.views.logout_view'),
(r'^$', 'mainapp.views.main_view'),
(r'^client/search/last_name/(A-Za-z)/$', 'client.views.client_search_last_name_view'),
#(r'^client/search/post_code/(A-Za-z)/$', 'client.views.client_search_last_name_view'),
# Uncomment the next line to enable the admin:
(r'^admin/', include(admin.site.urls)),
(r'^static/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.MEDIA_ROOT}),
)
and the views.py for login being:
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from django.contrib import auth
import mainapp.views
def login_view(request):
if request.method == 'POST':
uname = request.POST.get('username', '')
psword = request.POST.get('password', '')
user = auth.authenticate(username=uname, password=psword)
# if the user logs in and is active
if user is not None and user.is_active:
auth.login(request, user)
return redirect(mainapp.views.main_view)
else:
return render_to_response('loginpage.html', {'login_failed': '1',}, context_instance=RequestContext(request))
else:
return render_to_response('loginpage.html', {'dave': '1',}, context_instance=RequestContext(request))
def logout_view(request):
auth.logout(request)
return render_to_response('loginpage.html', {'logged_out': '1',}, context_instance=RequestContext(request))
and the views.py for clients being:
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
import login.views
def client_search_last_name_view(request):
if request.user.is_authenticated():
return render_to_response('client/client_search_last_name.html', {}, context_instance=RequestContext(request))
else:
return redirect(login.views.login_view)
Yet when I login it django raises an 'NoReverseMatch' for {% url client.views.client_search_last_name_view %} but not for {% url login.views.logout_view %}
Now why would this be?
The "client.views.client_search_last_name_view" url's regex capatures a value (with the parens), so in order to {% url %} it, you need to pass it a value for that parameter.
If you are creating a URL which is supposed to accept a last name the correct way would be as follows:
(r'^client/search/last_name/(?P<last_name>[a-zA-Z]+)/$',
'client.views.client_search_last_name_view'),
The (?P<last_name>[a-zA-Z]+) part of the regex allows you to capture the last name which is at least one character in length and then have it passed as an argument to your view function.
However you then need to ensure that your view does accept this argument:
def client_search_last_name_view(request, last_name):
...
The reason you cannot then do:
{% url client.views.client_search_last_name_view %}
is because your regex states (like the view) that it needs one argument, which is a string consisting of lower or upper cases letters from A to Z. So for example this would work:
{% url client.views.client_search_last_name_view 'somelastname' %}
If you want to give your URL a name as another answer has suggested you can, but that is a separate matter and has no effect other than shortening that template tag.
The reason {% url login.views.logout_view %} does work is because its entry in urls.py does not specify any arguments to be passed to the view and, through default alone you have not passed any.
AFAIK you want to add a name='foo' arg to each of your url regexes. That name is what is used in the reverse match. Like this:
urls.py
(r'^login/$', 'login.views.login_view', name="login"),
template.html
{% url login %}
Related
I have written the most basic Django application to understand forms as below. When I enter the required data into the fields and press Submit, the code after "if request.method == 'POST'" is ignored. I am redirected to the appropriate page and an entry with the first name "John" and last name "Smith" is created in my database. As you can see in the code below, this object should only be created if the request method is not POST. I know that I have set the request method to POST because that is what is shown on my CMD so what is happening??
Here is my template 'index.html':
<!DOCTYPE html>
<html>
<head>
<title>Welcome to the site</title>
</head>
<body>
<form action="thanks/" method='POST'>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" vlaue="Submit">
</form>
</body>
</html>
Here is my views.py file:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import NewObjectForm
from .models import Object
# Create your views here.
def index(request):
if request.method == 'POST':
form=NewObjectForm(request.POST)
if form.is_valid():
first_name=form.cleaned_data['first_name']
last_name=form.cleaned_data['last_name']
a=Object.create(first_name=first_name,last_name=last_name)
a.save()
return HttpResponseRedirect('/thanks/')
else:
new=Object.create(first_name="Not",last_name="Valid")
new.save()
else:
#Code which is run if the request.method is not equal to 'POST'
form=NewObjectForm()
newer=Object.objects.create(first_name="John",last_name="Smith")
newer.save()
return render(request,'formapp/index.html',{'form':form})
def end(request):
return render(request,'formapp/thanks.html')
Here is the urls.py file from the main project:
"""experimentalForms URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('',include('formapp.urls')),
path('admin/', admin.site.urls),
]
And here is the urls.py file from my application:
'''
URLs for formapp
'''
from django.urls import path
from . import views
app_name="formapp"
urlpatterns=[
path('',views.index,name='index'),
path('thanks/',views.end),
]
Thanks #mbieren! I have changed my the action attribute of my form and it is working perfectly!
I have internationalization correctly installed.
It's works with urls like:
/en/bookings/ #English
/es/reservas/ #Spanish
In the home page the language switching works fine too.
- What's the issue?
When I change the language in a translated page, like /en/bookings/, if I turn the language to Spanish (es) I am redirected to /en/bookings/ again and I see the page in English.
If I change the prefix (like this answer) the redirection goes to /es/bookings/ that doesn't exists.
I don't want to be redirected to the home page.
- What I like?
If I am in the /en/bookings/ and switch to Spanish I want to be redirected to /es/reservas/, for all the translated urls.
What is the best way?
Thanks.
I had similar problem so I sending my resolution to save Your time.
main(urls.py)
from django.conf.urls import include, url
from django.conf.urls.i18n import i18n_patterns
urlpatterns = [
url(r'^i18n/', include('django.conf.urls.i18n')),
]
urlpatterns += i18n_patterns(
url(r'^', include('index.urls', namespace='index')),
)
(index.urls.py)
from django.conf.urls import url
from django.views.generic import TemplateView
from django.utils.translation import ugettext_lazy as _
urlpatterns = [
url(r'^$', TemplateView.as_view(template_name='index/index.html'), name='index'),
url(_(r'^python-programming/$'), TemplateView.as_view(template_name='index/new_page.html'),
name='new_page'),
]
Creating template tag to return urls for current location in all languages that we support (index.templatetags.helper_tags.py)
from django.template import Library
from django.core.urlresolvers import resolve, reverse
from django.utils.translation import activate, get_language
register = Library()
#register.simple_tag(takes_context=True)
def change_lang(context, lang=None, *args, **kwargs):
"""
Get active page's url by a specified language
Usage: {% change_lang 'en' %}
"""
path = context['request'].path
url_parts = resolve(path)
url = path
cur_language = get_language()
try:
activate(lang)
url = reverse(url_parts.view_name, kwargs=url_parts.kwargs)
finally:
activate(cur_language)
return "%s" % url
Creating middleware to change site language when user will click at alternative link to this sub site but in different language
(middleware.py)
from django.utils import translation
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
class LangBasedOnUrlMiddleware(MiddlewareMixin):
#staticmethod
def process_request(request):
if hasattr(request, 'session'):
active_session_lang = request.session.get(translation.LANGUAGE_SESSION_KEY)
if active_session_lang == request.LANGUAGE_CODE:
return
if any(request.LANGUAGE_CODE in language for language in settings.LANGUAGES):
translation.activate(request.LANGUAGE_CODE)
request.session[translation.LANGUAGE_SESSION_KEY] = request.LANGUAGE_CODE
Adding it to (settings.py) just after LocaleMiddleware
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'our_app.middleware.LangBasedOnUrlMiddleware',
]
Sample usage in template:
{% load i18n %}
{% load helper_tags %}
{% get_available_languages as languages %}
{% for lang_code, lang_name in languages %}
<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{% change_lang lang_code %}">
{% endfor %}
When I had the same problem, I implemented a custom template tag (current_url) that, given the request in context, re-renders the url for the active language:
{% load custom_tags %}
<ul>
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
{# IMPORTANT! enclose the 'current_url' tag in a 'language' block #}
{% language language.code %}
<li {% if language.code == LANGUAGE_CODE %}class="active"{% endif %}>
{{ language.name_local }}
</li>
{% endlanguage %}
{% endfor %}
</ul>
Here is the code for the custom tag (custom_tags.py):
import six
import sys
from django.template import Node, TemplateSyntaxError, Library
from django.conf import settings
register = Library()
class CurrentURLNode(Node):
def __init__(self, asvar=None):
self.asvar = asvar
def render(self, context):
request = context['request']
from django.core.urlresolvers import reverse, NoReverseMatch
url = ''
try:
url = reverse(request.resolver_match.view_name, args=request.resolver_match.args, kwargs=request.resolver_match.kwargs, current_app=context.current_app)
except NoReverseMatch:
exc_info = sys.exc_info()
if settings.SETTINGS_MODULE:
project_name = settings.SETTINGS_MODULE.split('.')[0]
try:
url = reverse(project_name + '.' + request.resolver_match.view_name,
args=request.resolver_match.args, kwargs=request.resolver_match.kwargs,
current_app=context.current_app)
except NoReverseMatch:
if self.asvar is None:
six.reraise(*exc_info)
else:
if self.asvar is None:
raise
if self.asvar:
context[self.asvar] = url
return ''
else:
return url
#register.tag
def current_url(parser, token):
bits = token.split_contents()
bits = bits[1:]
asvar = None
if len(bits) >= 2 and bits[-2] == 'as':
asvar = bits[-1]
bits = bits[:-2]
if len(bits):
raise TemplateSyntaxError("Unexpected arguments to current_url tag")
return CurrentURLNode(asvar)
There is no need to use the 'set_language' django view. There is no need to make a POST request to change the active language. With only html archors linking all your internationalized content together, it's better for SEO.
I am building my first django app that uses user authentication and I'm using
some examples I found on the web for reference. My examples use a method 'direct_to_template'.
The problem is that I get a blank screen when I use this. I know that the
template is in my templates directory.
Why am I getting a blank screen at login? How can I fix this?
The examples I'm using:
Example #1: https://docs.djangoproject.com/en/dev/topics/auth/
Example #2:
http://www.nerdydork.com/django-login-form-on-every-page.html
My code is below:
-------------base.html-------------
Here is the trigger it's in the header bar.
<li>Log-In</li>
--------- views.py -----------------------
from django.template import Context, loader
from django.conf.urls import patterns, url, include
from django.views.generic.simple import direct_to_template
from django.http import HttpResponse
VER = "1a" # Global I like to print; making sure my latest code is running.
def mylogin(request):
print "mylogin called [%s] " % VER
if request.method == 'POST':
user = authenticate(username=request.POST['username'],
password=request.POST['password'])
if user is not None:
if user.is_active:
login(request, user)
# success
return HttpResponseRedirect('/')
else:
# disabled account
return direct_to_template(request, 'inactive_account.html')
else:
# invalid login
return direct_to_template(request, 'invalid_login.html')
# User just clicked login
# *** I know this is getting called and I get a blank screen here ***
print "calling: direct_to_template('login.html')"
return direct_to_template(request, 'login.html')
def mylogout(request):
print "mylogout called"
logout(request)
return direct_to_template(request, 'logged_out.html')
--------- urls.py -----------------------
from django.conf.urls import patterns, include, url
from django.views.generic.simple import direct_to_template
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^customers/$', 'jim.views.index'),
(r'^customers/(?P<customer_id>\d+)/$', 'jim.views.detail'),
(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/media'}),
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/static'}),
(r'^login/$', 'jim.views.mylogin'),
(r'^logout/$', 'jim.views.mylogout'),
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/media'}),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
)
urlpatterns += patterns('django.views.generic.simple', (r'^accounts/login/$', 'direct_to_template', {'template': 'login_required.html'}),
)
--------- templates/login.html -----------------------
{% if user.is_authenticated %}
<!-- Authenticate account menu -->
{% else %}
<h3>Login</h3>
<form action="/login/" method="post" accept-charset="utf-8">
<label for="username">Username</label><input type="text" name="username" value="" id="username" />
<label for="password">Password</label><input type="password" name="password" value="" id="password" />
<p><input type="submit" value="Login"></p>
</form>
{% endif %}
Errr if your template is such
{% if user.is_authenticated %}
<!-- Authenticate account menu -->
{% else %}
stuff
{% endif %}
it seems pretty logical that your template is blank -_-
further more.. 200 is not an HTTP error it means 200 OK: Standard response for successful HTTP requests.
I have added a comment for you question asking for more details. But without those details my wild guess is that you need a view to display your "login.html" template.
You can write a sepearate view for that and put it in the urls.py. You can use the generic direct_to_template view in urls.py. Or you can modify your current "mylogin" view, for example:
def mylogin(request):
print "mylogin called [%s] " % VER
if request.method == 'POST':
user = authenticate(username=request.POST['username'],
password=request.POST['password'])
if user is not None:
if user.is_active:
login(request, user)
# success
return HttpResponseRedirect('/')
else:
# disabled account
return direct_to_template(request, 'inactive_account.html')
else:
# display login form
return direct_to_template(request, 'login.html')
The difference is in the indendation and in the last line (no POST data, means it's a GET request to display the login form).
But as I said, there are w few ways to handle it, mine is only a suggestion and I'm not going into any of your design decisions :)
I have the following setup:
/landing_pages
views.py
urls.py
In urls.py I have the following which works when I try to access /competition:
from django.conf.urls.defaults import *
from django.conf import settings
from django.views.generic.simple import direct_to_template
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^competition$', 'landing_pages.views.page', {'page_name': 'competition'}, name="competition_landing"),
)
My views.py has something like this:
def page(request, page_name):
return HttpResponse('ok')
Then in a template I'm trying to do this:
{% load url from future %}
<a href="{% url 'landing_pages.views.page' page_name='competition'%}">
Competition
</a>
Which I apparently can't do:
Caught NoReverseMatch while rendering: Reverse for 'landing_pages.views.page' with arguments '()' and keyword arguments '{'page_name': u'competition'}' not found.
What am I doing wrong?
You ask in your comment to DrTyrsa why you can't use args or kwargs. Just think about it for a moment. The {% url %} tag outputs - as the name implies - an actual URL which the user can click on. But you've provided no space in the URL pattern for the arguments. Where would they go? What would the URL look like? How would it work?
If you want to allow the user to specify arguments to your view, you have to provide a URL pattern with a space for those arguments to go.
{% url [project_name].landing_pages.views.page page_name='competition' %}
Or better
{% url competition_landing 'competition' %}
I have looked a lot on google for answers of how to use the 'url' tag in templates only to find many responses saying 'You just insert it into your template and point it at the view you want the url for'. Well no joy for me :( I have tried every permutation possible and have resorted to posting here as a last resort.
So here it is. My urls.py looks like this:
from django.conf.urls.defaults import *
from login.views import *
from mainapp.views import *
import settings
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Example:
# (r'^weclaim/', include('weclaim.foo.urls')),
(r'^login/', login_view),
(r'^logout/', logout_view),
('^$', main_view),
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
# to INSTALLED_APPS to enable admin documentation:
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
(r'^admin/', include(admin.site.urls)),
#(r'^static/(?P<path>.*)$', 'django.views.static.serve',{'document_root': '/home/arthur/Software/django/weclaim/templates/static'}),
(r'^static/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.MEDIA_ROOT}),
)
My 'views.py' in my 'login' directory looks like:
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from django.contrib import auth
def login_view(request):
if request.method == 'POST':
uname = request.POST.get('username', '')
psword = request.POST.get('password', '')
user = auth.authenticate(username=uname, password=psword)
# if the user logs in and is active
if user is not None and user.is_active:
auth.login(request, user)
return render_to_response('main/main.html', {}, context_instance=RequestContext(request))
#return redirect(main_view)
else:
return render_to_response('loginpage.html', {'box_width': '402', 'login_failed': '1',}, context_instance=RequestContext(request))
else:
return render_to_response('loginpage.html', {'box_width': '400',}, context_instance=RequestContext(request))
def logout_view(request):
auth.logout(request)
return render_to_response('loginpage.html', {'box_width': '402', 'logged_out': '1',}, context_instance=RequestContext(request))
and finally the main.html to which the login_view points looks like:
<html>
<body>
test! logout
</body>
</html>
So why do I get 'NoReverseMatch' every time?
*(on a slightly different note I had to use 'context_instance=RequestContext(request)' at the end of all my render-to-response's because otherwise it would not recognise {{ MEDIA_URL }} in my templates and I couldn't reference any css or js files. I'm not to sure why this is. Doesn't seem right to me)*
The selected answer is out of date and no others worked for me (Django 1.6 and [apparantly] no registered namespace.)
For Django 1.5 and later (from the docs)
Warning
Don’t forget to put quotes around the function path or pattern name!
With a named URL you could do:
(r'^login/', login_view, name='login'),
...
logout
Just as easy if the view takes another parameter
def login(request, extra_param):
...
login
Instead of importing the logout_view function, you should provide a string in your urls.py file:
So not (r'^login/', login_view),
but (r'^login/', 'login.views.login_view'),
That is the standard way of doing things. Then you can access the URL in your templates using:
{% url login.views.login_view %}
Make sure (django 1.5 and beyond) that you put the url name in quotes, and if your url takes parameters they should be outside of the quotes (I spent hours figuring out this mistake!).
{% url 'namespace:view_name' arg1=value1 arg2=value2 as the_url %}
link_name
The url template tag will pass the parameter as a string and not as a function reference to reverse(). The simplest way to get this working is adding a name to the view:
url(r'^/logout/' , logout_view, name='logout_view')
I run into same problem.
What I found from documentation, we should use namedspace.
in your case {% url login:login_view %}
Judging from your example, shouldn't it be {% url myproject.login.views.login_view %} and end of story? (replace myproject with your actual project name)