Een loginformulier inbedden in een Wagtail-pagina

Wanneer een geregistreerde gebruiker toegang wil krijgen tot beveiligde functionaliteit op een specifieke pagina, zou het gebruikersvriendelijker zijn om hem / haar in staat te stellen in te loggen op die pagina in plaats van omgeleid te worden naar een inlogpagina.

12 juli 2020 18:00
Thema's: Authenticatie

In een eerdere tutorial hebben we geregistreerde gebruikers in staat gesteld om gemakkelijk op artikelen te reageren. Als een geregistreerde gebruiker echter niet is ingelogd, moet hij / zij naar de inlogpagina gaan en dan terugkeren naar het specifieke artikel. Er zijn veel manieren om dit op te lossen, waaronder een pop-up loginformulier dat toegankelijk is via het menu. In deze tutorial zullen we een eenvoudig inlogformulier inbedden in de specifieke artikelpagina.

De stappen zijn:

  • een inlogformulier toevoegen aan de pagina door de serve () methode van de pagina te overschrijven,
  • een inlogtemplate toevoegen aan de pagina en dit in eerste instantie verbergen,
  • een link toevoegen om het formulier zichtbaar te maken via jQuery,
  • het ingevulde formulier insturen via jQuery,
  • terugkeren naar de pagina zodat de gebruiker zijn commentaar kan plaatsen.

Om de serve() methode te overschrijven, voeg je het volgende toe aan het paginamodel (in ons geval ArticlePage):

from allauth.account.forms import LoginForm

def serve(self, request, *args, **kwargs):
    response = super().serve(request, 'cms/article_page.html')
    response.context_data['login_form'] = LoginForm()
    return response

We gebruiken de standaard LoginForm uit het pakket allauth; gebruik je eigen formulier als je een ander hebt. Eerst roepen we de methode super() aan om de standaard respons te krijgen. Wagtail retourneert een TemplateResponse-object met een veld context_data waaraan we het formulier kunnen toevoegen.

De html-code die aan de template moet worden toegevoegd, heeft alleen een veld login (in ons geval email), een veld password en een verzendknop:

{% if not request.user.is_authenticated %}
    <div class="container mt-4 ml-0">
        <form method="POST" id="id_login_form" action="{% url 'account_login' %}" style="display: none">
            {% csrf_token %}
            <div class="row align-items-end">
                <div class="col-6 form-group">
                    {% with field=login_form.login %}{% include "account/form_field.html" %}{% endwith %}
                </div>
                <div class="col-4 form-group">
                    {% with field=login_form.password %}{% include "account/form_field.html" %}{% endwith %}
                </div>
                <div class="col-2 form-group">
                    <button id="id_submit_login_form" class="btn btn-outline-primary">{% trans "Sign in" %}</button>
                </div>
            </div>
        </form>
    </div>
{% endif %}

We verbergen het formulier in eerste instantie door style="display: none" in te stellen in het formulier. Een link om het zichtbaar te maken wordt toegevoegd door:

{% if not request.user.is_authenticated %}
    <div id="id_comment_invite" class="container-fluid mt-4">
        <p>{% trans "Comment on this article ("%}<a href="#" id="id_login_first_link">{% trans "sign in first" %}</a>{% trans " or confirm by name and email below)" %}</p>
    </div>
{% endif %}

Pas de tekst naar behoefte aan. Wagtail heeft standaard een blok extra_js in het basistemplate; voeg het toe indien nodig. Aangezien we ajax gaan gebruiken om ons formulier te verzenden, zorg ervoor dat jQuery het aankan. Wanneer je eerder een jQuery-link voor Bootstrap hebt gebruikt, is het mogelijk een afgeslankte (slim) versie, die ajax niet aankan. Kopieer de link van https://code.jquery.com/ en vervang de bestaande jQuery-link in base.html onderaan:

<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>

Voeg op de template article_page.html toe:

{% block extra_js %}
    <script>
        $(document).ready(function(){

            $("#id_login_first_link").click(function(event) {
                event.preventDefault();
                $("#id_login_form").show();
            });

            ADD CODE FOR LOGIN FORM
       });
    </script>
{% endblock %}

Deze eenvoudige Javascript-code toont het inlogformulier wanneer de gebruiker op de link klikt. De opdracht event.preventDefault() voorkomt het scrollen van de pagina. De code voor het inlogformulier die hierboven moet worden toegevoegd, is één ajax-opdracht:

$("#id_submit_login_form").click(function(event){
    event.preventDefault();

    $.ajax({
        type:"POST",
        url: "{% url 'account_login' %}",
        data: $('#id_login_form').serialize(),
        success: function(response, status){
            $("#id_login_form").hide();
            $("#id_login_first_link").hide();
            location.reload();
       },
        error: function(xhr, status, error){
            $('#id_login_form').submit();
        }
    });
});

De event.preventDefault() voorkomt dat het formulier wordt verzonden, wat de gebruiker naar een andere pagina zou leiden. De url waarnaar het POST-formulier moet worden verzonden, is account_login, gedefinieerd in onze authenticatie-app. De te verzenden gegevens bestaan uit het geserialiseerde formulier. Bij succes verbergen we het formulier en de link en laden we de pagina opnieuw. Herladen zou voorkomen kunnen worden, maar dan moeten we een nieuw csrf-token genereren om een ​​foutmelding te voorkomen wanneer er daarna een comment zou worden verzonden. Bovendien zouden we de velden voor opmerkingen die we niet nodig hebben, moeten verbergen en nog meer dingen wijzigen, zoals het reageren op een bepaalde opmerking (waarvoor de gebruiker ook ingelogd moet zijn). Dus kiezen we hier de luie optie en laden de pagina opnieuw. Als het inloggen niet lukt, b.v. omdat de gebruiker niet het juiste wachtwoord heeft ingevuld, dienen we het inlogformulier in. Dit leidt de gebruiker om naar de pagina die een mislukte login genereert. Voor onze doeleinden hier willen we niet alle aanmeldopties afhandelen op de artikelpagina.

Het is niet nodig om de database te migreren. Probeer of alles werkt zoals verwacht.

Een aanvullende opmerking over Django Comments Xtd. Het pakket heeft ook een Javascript-optie die ook opmerkingen via ajax indient, zonder de pagina opnieuw te laden. Het laadt ook automatisch nieuwe opmerkingen. Dit werkt prachtig out-of-the-box. Een nadeel is dat het niet triviaal is om de vormgeving van de html-elementen te veranderen; dit vereist verdiepen in de React-code. Het integreren van de inlogfunctionaliteit vereist ook wat meer werk. Dus we laten het voor nu zo en komen er misschien een andere keer op terug.

Als je bewerkbare formulieren aan je Wagtail-pagina's wilt toevoegen, lees dan verder.

Reageer op dit artikel (log eerst in of bevestig hieronder met naam en email)