Say, in the post method of my registration class, I want to redirect the user to the login page if the user is already registered, simple enough.
class Register(View):
...
def post(self, request):
# Some code to check if the email address is already in the db
message = {'message': 'You are already a member and registered the project. Please just log-in',
'registration_date': the_registered_date}# The form with the filled-in data is returned
return HttpResponseRedirect(reverse('accounts:login', kwargs = message))
in my urls.py:
#urls.py
...
url(r'^login/{0,1}$', Login.as_view(), name='login', kwargs={'message': None, 'date': None}),
This gives me the error message:
Reverse for 'login' with arguments '()' and keyword arguments '{'message': 'You are already a member and registered the project. Please just log-in', 'registration_date': datetime.datetime(2015, 10, 15, 14, 3, 39, 864000, tzinfo=<UTC>)}' not found. 2 pattern(s) tried: [u'accounts/$', u'accounts/login/{0,1}$']
What am I doing wrong?
Your url definition is wrong, also sounds like your misunderstood what kwargs does in reverse. It feeds the named arguments of your url definition with it's value, not passing context to the view.
For example, you could do this:
url(r'test_suite/(?P<test_name>\w+)/(?P<test_id>\d+)$', 'test', name='test')
reverse('test', kwargs={'test_name': 'haha', 'test_id': 1})
kwargs will substitute your test_name in url definition with haha and test_id with 1. This will produce a url: test_suite/haha/1.
Kwargs in reverse are the variables that go into your URL to make it unique. It would be really odd to see a message/date inside a URL...which is what your URLconf is trying to do.
Also, you can't redirect with context in Django without going to trouble that makes the juice not worth the squeeze. One option is to use the messages framework to display a message on the login page if you want to do that after the redirect.
My solution would be to remove the kwargs from your URLConf for /login/ and use the messages framework (or sessions) to pass the information to the login page after the redirect.
Related
I see the following error when trying to render my item_detail template, which uses a url tag in a link to the item_update view:
NoReverseMatch at /mcadb/27/items/17
Reverse for 'item_update' with arguments '()' and keyword arguments '{u'course_id': '', u'pk': 17}' not found. 1 pattern(s) tried: [u'mcadb/(?P<course_id>[0-9]+)/items/(?P<pk>[0-9]+)/update/$']
What is the problem trying to match the pattern tried? Is it because of the u? I'm not sure why that is happening.
In views.py, I try to add 'course_id' to the context for the DetailView. I try to get 'course_id' from the kwargs for the view (I don't know why it's blank)
views.py
class ItemDetailView(DetailView):
DetailView.model=Item
template_name='mcadb/item_detail.html'
def get_context_data(self, **kwargs):
context = super(ItemDetailView, self).get_context_data(**kwargs)
context['course_id'] = self.kwargs['course_id']
return context
urls.py
url(r'^(?P<course_id>[0-9]+)/items/(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='item_detail'),
url(r'^(?P<course_id>[0-9]+)/items/(?P<pk>[0-9]+)/update/$', views.ItemUpdate.as_view(), name='item_update'),
item_detail.html
Edit Item
The problem is with the 'course_id=course_id' line. If I change it to 'course_id=26', item_detail.html renders fine.
I have two questions.
1. what does the error mean, when it looks like I'm passing two kwargs as expected?
2. why does it work if I hardcode a course_id?
Thank you very much, Carrie
I think this is the error:
url(r'^(?P<course_id>[0-9]+)/items/(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='item_detail'),
Note that you are use a generic DetailView (from django.views.generic.DetailView) with this url.
You need to use your own View myapp.views.ItemDetailView.
So in your urls.py file:
from myapp.views import ItemDetailView
url(r'^(?P<course_id>[0-9]+)/items/(?P<pk>[0-9]+)/$', ItemDetailView.as_view(), name='item_detail'),
Explanation for your exact error is here:
Reverse for 'item_update' with arguments '()' and keyword arguments '{u'course_id': '', u'pk': 17}' not found. 1 pattern(s) tried: [u'mcadb/(?P[0-9]+)/items/(?P[0-9]+)/update/$']
As you can see, reverse is getting empty course_id and URL can't be built with empty, because there must be at least 1 number (+ sign in regex pattern). so there is definetly something wrong with passing course_id into context or into url tag. Try to print that variable next to url tag and check it's value. Check if you can access this variable somewhere else in your template (maybe outside of all for loops, includes and with tags) and if you can access it directly from your view (try to create URL here using reverse or just print variable to logs).
Below is the code from views.py where I am using render_to_response to direct the user to done.html along with a dictionary of variables. But, I actually want to direct the user to a url /home_main/#signin_completeand pass the dictionary of variables that are callable. Can someone please suggest if there is a way of doing this ?
def done(request):
"""Login complete view, displays user data"""
scope = ' '.join(GooglePlusAuth.DEFAULT_SCOPE)
return render_to_response('done.html', {
'user': request.user,
'plus_id': getattr(settings, 'SOCIAL_AUTH_GOOGLE_PLUS_KEY', None),
'plus_scope': scope
}, RequestContext(request))
EDIT
My requirement is to render a second page (signin_complete) from a multipage html (home_main.html). Currently, I am achieving this by redirecting the user with HttpResponseRedirect as shown below. But, I would also like to pass a callable dictionary that I can use in the second page of the multipage html.
Here is a link that gives more information of a multipage html under multipage template structure.
def done(request):
"""Login complete view, displays user data"""
scope = ' '.join(GooglePlusAuth.DEFAULT_SCOPE)
return HttpResponseRedirect('/home_main/#signin_complete')
Below is the dictionary that I would like to pass to the second page (sign_complete) in the multi page html.
{
'user': request.user,
'plus_id': getattr(settings, 'SOCIAL_AUTH_GOOGLE_PLUS_KEY', None),
'plus_scope': scope
}
The session is the place to store data between requests.
# in done():
request.session['dict_to_save'] = my_dict_to_save
return redirect('/new/url/to/redirect/to')
# in the new view:
values_from_session = request.session.pop('dict_to_save', None)
It would be much better if you would redirect request inside done() method, like the docs advises you to do.
This solves your issue as well, since you can define your own url to redirect to, there's related SO question of how to add hash tags when redirecting.
I have a URL like this:
url(r'^(?P<user_id>\d+)/profile/$', views.ProfileView.as_view(), name='profile'),
When the user clicks on Update Profile I do the update of form and redirect to the same Profile URL with message using messaging framework.
# views
# Use the message framework to pass the message profile successfully updated
messages.success(request, 'Profile details updated.')
# Redirect to the same view with the profile updated successfully message
return HttpResponseRedirect(reverse('profile', args=(request.user.id,)))
But I get this error:
NoReverseMatch at /5/profile/
Reverse for 'profile' with arguments '(5L,)' and keyword arguments '{}' not found.
What's wrong?
You're getting that because of how Python 2.x.x works.
All integers that comes from a database row will get suffixed with L or l (t commonly the capital L).
One way that'll work quick and dirty is
return HttpResponseRedirect(reverse('profile', args=(int(long(request.user.id)),)))
In a urls.py file:
url(r'^api/user_info/(?P<username>[a-zA-Z\d]+)\&', 'corresponding.view')
url(r'^api/user_info/(?P<username>[a-zA-Z\d]+)', 'corresponding.view')
There will always be HTTP Get arguments to /api/user_info/username.
The problem is that in the corresponding.view function, username will evaluate to something like "myusername?clientversion=2.0", instead of it evaluating to "myusername" and request.GET['clientversion'] = "2.0".
The first url call is to try to catch the ampersand in there, but it doesn't help.
Thanks in advance.
See this question; you don't access query parameters using Django's URLConf. Trying to process ? or & characters using the URL resolver will not lead to happiness.
Just use the following URL pattern:
url(r'^api/user_info/(?P<username>\w\+)/$', 'corresponding.view')
and access the clientversion query parameter in your corresponding.view() function:
def view(request):
client_version = request.GET.get('clientversion')
...
Or, if you're saying it should be mandatory,
from django.http import Http404
def view(request):
try:
client_version = request.GET['clientversion']
except KeyError:
raise Http404
i have something like this in my views.py
instance = get_object_or_404(register,pk=request.user.id)
Now if there is no related object against this user i receive i standard django 404 eror
saying no matches found.
what i want here is instead of receiving this 404 error redirect it to another page say "something.html". but i dont know how. i am using method = "POST"
is there any way to redirect it to other page instead of receiving a 404 error
using a try/except block you can redirect if the object is not found
try:
instance = register.get(pk=request.user.id)
except register.DoesNotExist:
return HttpResponseRedirect('url that renders something.html')
FYI, definition of django get_object_or_404 function looks like this
def get_object_or_404(klass, *args, **kwargs):
"""
Uses get() to return an object, or raises a Http404 exception if the object
does not exist.
klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the get() query.
Note: Like with get(), an MultipleObjectsReturned will be raised if more than one
object is found.
"""
queryset = _get_queryset(klass)
try:
return queryset.get(*args, **kwargs)
except queryset.model.DoesNotExist:
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
from the docs, If you raise Http404 at any point in a view function, Django will catch it and return the standard error page for your application, along with an HTTP error code 404.
look at customizing error views if you want to render a custom 404.html based on the context variables
Depending on what the Big Picture is, you might want to look at django.contrib.flatpages and see what they are doing. Basically they are dealing with the 404 in middleware and then looking at the path to decided if there is something they can return. I have used variations on this on a couple of sites.