Search code examples
pythondjangoregistration

how can I use LoginView in my own view and show in HTML templates?


I want to use ready Django LoginView, but in the same time I have to use my own view for registration in same HTML template. If in urls.py file I will connect 2 views than i will connect only first. So my question is that how can use LoginView in my own view and use 2 forms with jinja? here is my views.py file and html ;)

def index(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        formlog = auth_views.LoginView.as_view(template_name='main/index.html')

        if 'signup' in request.POST:
            if form.is_valid():
                form.supervalid()
                form.save()
                username = form.cleaned_data.get('username')
                messages.success(request, f'Dear {username} you have been created a new accound!')
                return redirect('main')
        elif 'login' in request.POST:
            if formlog.is_valid():
                formlog.save()
                username = form.cleaned_data.get('username')
                messages.success(request, f'Your account has been created! You are now able to log in')
                return redirect('main')
    else:
        form = UserRegisterForm()
        formlog = auth_views.LoginView.as_view(template_name='main/index.html')
    return render(request, 'main/index.html', {'form': form, 'formlog': formlog})
# this code is not working , but not returning any errors

HTML

{% if not user.is_authenticated %}
    <!-- Login -->
    <div class="container">
        <div class="log-1">
            <div class="log-0">
                <p class="logtitle">BareTalk</p>
                <form method="POST" name="login">
                    {% csrf_token %}
                    {{ formlog|crispy }}
                    <button class="log-button first" type="submit">Login</button>
                </form>
                <button class="log-button second"
                     onclick="modalwindowops.open();" id="signup">Sign Up</button>
            </div>
        </div>
    </div>

    <!-- Signup  -->
    <div class="modal-overlay">
        <div class="modal-window">
            <span class="close-modal" onclick="modalwindowops.close();">&times;</span>
            <form method="POST" name="signup">
                <p>Sign Up</p>
                {% csrf_token %}
                {{ form|crispy }}

                <button type="submit">Sign Up</button>
            </form>
        </div>
    </div>
{% else %}
    <h1>Welcome back Amigo!</h1>
{% endif %}

Solution

  • Neither if 'signup' in request.POST: nor elif 'login' in request.POST: is triggered in your index() view because your HTML forms do not actually contain those inputs. Note that the name attribute is deprecated for the <form> element.

    Instead you can add a hidden <input> inside your forms, like this:

    <form method="POST">
        {% csrf_token %}
        {{ formlog|crispy }}
        <input type="hidden" name="login" value="true" />
        <button class="log-button first" type="submit">Login</button>
    </form>
    

    Also,

    formlog = auth_views.LoginView.as_view(template_name='main/index.html')
    

    saves a view to formlog, not a form, so calling formlog.is_valid() will cause an error.

    Instead of

    elif 'login' in request.POST:
        if formlog.is_valid():
            formlog.save()
            username = form.cleaned_data.get('username')
            messages.success(request, f'Your account has been created! You are now able to log in')
            return redirect('main')
    

    you probably will only need to do

    elif 'login' in request.POST:
        log_view = auth_views.LoginView.as_view(template_name='main/index.html')
        log_view(request)
    

    Calling is_valid(), save(), and doing the redirect is all done by LoginView already. If you want to still do the custom message.success() you will have to override one or more of the LoginView methods, but that is another topic.

    Update:

    You also need to change this line in the view: formlog = auth_views.LoginView.as_view(template_name='main/index.html') (before return render...) to:

    formlog = AuthenticationForm(request)
    

    Take this line outside of the else block.

    Also add the import for the form at the top of your views.py:

    from django.contrib.auth.forms import AuthenticationForm
    

    This change is required because the template needs the form object (which is AuthenticationForm for LoginView by default) instead of the view object. The updated view function will look like:

    from django.contrib.auth.forms import AuthenticationForm
    
    def index(request):
        if request.method == 'POST':
            form = UserRegisterForm(request.POST)
            if 'signup' in request.POST:
                if form.is_valid():
                    form.supervalid()
                    form.save()
                    username = form.cleaned_data.get('username')
                    messages.success(request, f'Dear {username} you have been created a new accound!')
                    return redirect('main')
            elif 'login' in request.POST:
                log_view = auth_views.LoginView.as_view(template_name='main/index.html')
                log_view(request)
        else:
            form = UserRegisterForm()
        formlog = AuthenticationForm(request)
        return render(request, 'main/index.html', {'form': form, 'formlog': formlog})
    

    Note that this can be improved by providing feedback when the login credentials are invalid. As it is, this updated code only reloads a blank login form if the provided credentials don't work.