0

I am using Python 2.7, Django 1.3.1.

I am trying to implement a sign in functionality that can be called from arbitrary page and redirects to the same page without any code duplication. The current way that I have is that I have two views: one for the homepage and one for sign in. I want to be able redirect from sign_in view to the home view with a bound form. The main problem is that when the user enters incorrect data (e.g wrong password) I want to redirect to the same page but want to send the context of the original form. I want to be able to do this without explicitly calling the view function since I want to be able to do it from arbitrary page. How do I do this? My current attempts always return an unbound form in case the data is invalid.

My current code is (simplfied):

urls.py

urlpatterns = patterns('myapp.views',
    url(r'^$', 'index', name='home'),
    url(r'sign_in/^$', 'signin', name='sign_in')
)

views.py

def index(request, loginForm=LoginForm)
    extra_context = dict()
    extra_context['login_form'] = loginForm
    return direct_to_template(request, 'home.html', extra_context=extra_context)

def signin(request)
    if request.method == 'POST':
        login_form = LoginForm(request.POST, request.FILES)
        if login_form.is_valid():
            # login user 
        redirect_view = reverse('home')
        return redirect(redirect_view, kwargs={'loginForm': login_form})
        # I also tried:  
        # return redirect(redirect_view, loginForm=login_form)
        # what works is:
        # return index(request, loginForm = login_form)

home.html

<form action="{% url sign_in %}" method="post">
    {{ form.as_p }}
</form>
fedosov
  • 1,989
  • 15
  • 26
saurabh
  • 137
  • 2
  • 9

1 Answers1

2

Not with reverse. Reverse gets you a path /my-homepage/

The django paradigm for this is to use a hidden "next" variable set to the initial page.

#In your template
<input type="hidden" value="{{ request.path }}" name="next" />

Then, on success return an HttpResponseRedirect to next:

     if login_form.is_valid():
         # login user 
         return HttpResponseRedirect(form.cleaned_data['next'])

This is durable, because if there is an issue, you display a form with errors on the /account/login/ page with the hidden next variable and the user still gets back to where they were.

Ted
  • 12,122
  • 4
  • 31
  • 39
  • This is simply redirecting to the orignal page upon success. I am concerned when the login_form is not valid. I would like to redirect to the view corresponding to the original page (yes, the link to that could be obtained through the 'next' parameter) with the bound form indicating errors. – saurabh Jan 14 '12 at 19:00
  • That could be cute, but could also be a disaster. If there are errors, don't you want the user on a single page with their focus explicitly on fixing the error? – Ted Jan 14 '12 at 22:06
  • Yes. That is one feasible solution, but the downside being that the user is being redirected to a page that looks different. I want to know if the failed redirect can be done to the same page. Seems like the answer is no? – saurabh Jan 14 '12 at 22:21
  • if you really want "same page" errors, use an ajax system that degrades to displaying the errors on its own page. http://stackoverflow.com/questions/312925/django-authentication-and-ajax-urls-that-require-login – Ted Jan 15 '12 at 00:26