3

I've struggled with this problem for the last two days and could use some help. The home page for my Django 1.6 application will include two forms, one that a user can use to sign in to the site and one they can use to sign up (create a login) for the site:

# templates/home/home_page.html
<div class="sign-in-form">
    <form action="{% url 'apps.home.views.sign_in' %}" method="post">
        {% csrf_token %}

        {{ sign_in_form.as_p }}

        {% if next %}
            <input type="hidden" name="next" value="{{ next }}">
        {% else %}
            <input type="hidden" name="next" value="{% url 'view-members' %}">
        {% endif %}
        <input type="submit" value="Sign in">
    </form>
</div>

<div class="sign-up-form">
<fieldset>
    <legend>Sign up</legend>
    <form action="{% url 'apps.home.views.sign_up' %}" method="post">
        {% csrf_token %}

        {{ sign_up_form.as_p}}

        <p><input type="submit" value="Sign up" /></p>
    </form>
</fieldset>
</div>

If the user submits, the sign_in form, they'll be taken to a page where they can view other site members. If they submit the sign_up form, they'll be taken to a second signup page where they'll create a user profile, etc.

Originally, I was going to use the technique shown in this question and use one view to handle the homepage. However, I decided to try to use two views because I'm using the Django's actual login view (django.contrib.auth.views.login) so that I can add code to it to detect the user's device (phone, tablet, or computer), and merging that view with my sign_up view would create a very long and complicated view to maintain. I'd prefer to keep the views for both forms separate.

Here's the home page and sign_in views:

# apps/home/views:
def home_page(request, template):
    sign_in_form = SignInAuthenticationForm()
    sign_up_form = CreateAccountForm()
    return render(request, template, {"sign_in_form": sign_in_form,
                                      "sign_up_form": sign_up_form})

@sensitive_post_parameters()
@csrf_protect
@never_cache
def sign_in(request, 
            template='home_page.html',
            redirect_field_name=REDIRECT_FIELD_NAME,
            # authentication_form=AuthenticationForm,
            authentication_form=SignInAuthenticationForm,
            current_app=None, extra_context=None):

    # Do device detection here...
    # django.contrib.auth.views code goes here...

    return response

The signup view will just be your typical, function-based view for processing a form as described in the Django documentation.

What I'm struggling with is my URLconf files. Here's my main and "home" URLconf files:

# conf/urls.py
urlpatterns = patterns('',
    url(r'^$',         include('apps.home.urls')),
    # Other url patterns...
)

# apps/home/urls.py
urlpatterns = patterns('apps.home.views',
    url(r'^$',
        'home_page',
        {'template': 'home/home_page.html'},
        name='home-page'),
    url(r'^sign_in/$',
        'sign_in',
        {'template': 'home/home_page.html'},
        name='sign-in'),
    url(r'^sign_up/$',
        'sign_up',
        {'template': 'home/home_page.html'},
        name='sign-up'),
)

The problem is that I get this error during template rendering:

NoReverseMatch at /

Reverse for 'apps.home.views.sign_in' with arguments '()' and keyword arguments '{}' not found. 1 pattern(s) tried: ['$sign_in/$']

Request Method: GET
Request URL:    http://localhost:8000/
Django Version: 1.6.2
Exception Type: NoReverseMatch
Exception Value:    
Reverse for 'apps.home.views.sign_in' with arguments '()' and keyword arguments '{}' not found. 1 pattern(s) tried: ['$sign_in/$']
Exception Location: /Users/smith/venv/swing/lib/python2.7/site-packages/django/core/urlresolvers.py in _reverse_with_prefix, line 429
Python Executable:  /Users/smith/venv/swing/bin/python
Python Version: 2.7.5
Python Path:    
['/Users/smith/Dropbox/www/swing',
 '/Users/smith/venv/swing/lib/python2.7/site-packages/wurfl_cloud-1.0.1-py2.7.egg',
 '/Users/smith/venv/swing/lib/python27.zip',
 '/Users/smith/venv/swing/lib/python2.7',
 '/Users/smith/venv/swing/lib/python2.7/plat-darwin',
 '/Users/smith/venv/swing/lib/python2.7/plat-mac',
 '/Users/smith/venv/swing/lib/python2.7/plat-mac/lib-scriptpackages',
 '/Users/smith/venv/swing/Extras/lib/python',
 '/Users/smith/venv/swing/lib/python2.7/lib-tk',
 '/Users/smith/venv/swing/lib/python2.7/lib-old',
 '/Users/smith/venv/swing/lib/python2.7/lib-dynload',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
 '/Users/smith/venv/swing/lib/python2.7/site-packages']

At first I started to think that maybe it's telling me that it can's find the correct URL pattern in my home/urls.py file because the URL signature in my form is incorrect. Maybe I needed to do this to match the arguments in the sign_in view:

<form action="{% url 'apps.home.views.sign_in' 'home/home_page.html' %}" method="post">

But I'm already showing the template name in the home URLconf. And I don't think I need to pass the other view arguments in the form action (e.g. redirect_field_name) because their optional. In any case, adding this argument to the form action didn't fix it.

One of the things that confuses me is how to set the first url argument. I've set them to r'^sign_in/$' and r'^sign_up/$' because if I set them both to r'^$', the page will render properly but when I submit either form, it justs posts back to the home page. You can see this will happen by doing a "view source" on the page. It shows each form's action will be "/". On the other hand, the way I have it now seems incorrect to me because the site won't actually have a "/sign_in/" and "/sign_up/" URL since both forms are on the home page. Also, is there going to be a problem in which if the user submits one for or the other improperly, errors for both forms will be rendered on the page?

The Django documentation, to the best of my knowledge, doesn't really describe a standard approach for doing what I'm trying to do. It describes how to render multiple versions of the same form. Can anyone tell me what I'm doing wrong?

Thanks.

3
  • why y don't try to use formsets to collect the 2 forms and test in the view if form1 valid do something(sign) or if form2 valid do something else docs.djangoproject.com/en/1.6/topics/forms/formsets Commented Jul 31, 2014 at 17:41
  • 1
    Because, as I understand it,FormSets are geared towards iterating through multiple copies of the same form. In my situation, I have two different forms. But perhaps I'm not understanding them. They still don't seem like the right solution. Commented Jul 31, 2014 at 17:51
  • yes that right but you can also use multi formset in the same view in your case 2 formsets evry formset has one form Commented Jul 31, 2014 at 19:25

2 Answers 2

1

Your form names are 'sign_in_form' and 'sign_up_form', but in your html you wrote them 'form.as_p' instead of 'sign_in_form.as_p' and 'sign_up_form.as_p' this is the first bug a saw in your code.

The real problem is in your urls configuration. In your main urls.py you have

 url(r'^$', include('apps.home.urls')),
 Other ...

Though you will not be able to get to localhost:8000/sign_in/ because initially it does not satisfy to ^$ .

Try to change it by

url(r'', include('apps.home.urls')),

and put it to the end of urls.py.

Sign up to request clarification or add additional context in comments.

3 Comments

While I haven't fully tested it, this looks like may fix the problem. Can you explain why this works? I didn't see the "url(r'',...)," syntax described anywhere in the Django documentation. Thanks.
Note that include('apps.home.urls') are only for '/' not 'sign_in' or 'sign_out'. url(r'',...) basically means every pattern, but I don't think that is good way to write urls. It is acceptable only during development.
user2309693, thanks very much for your help with this problem. I've done all my testing and it looks like it works. You said in your most recent comment that this way of handling urls is only appropriate during development. What should I do in a production environment? Your fix does make things work so I'm reluctant to change it. Thanks again!!
1

i test this see if this what you want: view.py

def loginUser(request,**Kargs):
LoginFormSet = formset_factory(LoginForm)
SignFormSet = formset_factory(SignForm)
if request.method == 'POST':
    login_formset = LoginFormSet(request.POST, prefix='login')
    sign_formset = SignFormSet(request.POST ,prefix='sign')
    if login_formset.is_valid():
        #do somthing

    elif sign_formset.is_valid():
        #do somthing

    return render(request, 'reservetion/login.html',{'login_formset': login_formset,'sign_formset':sign_formset})

else:
    login_formset = LoginFormSet(prefix='login')
    sign_formset = SignFormSet(prefix='sign')
    return render(request, 'reservetion/login.html',{'login_formset': login_formset,'sign_formset':sign_formset})

page.html:

            <form action="{% url 'loginUser'  %}" method="post">
                    {% csrf_token %}
{{ login_formset.management_form }}
{% for form in login_formset %}
    {{ form }}
{% endfor %}

{{ sign_formset.management_form }}
{% for form in sign_formset %}


 {{ form }}


 {% endfor %}

1 Comment

Thanks slim_ch but I think I'm going to go with the other solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.