0

I have problem similar to this one: Django form data lost on making login required on post I want answer to be added if user is logged in otherwise redirect user to login page, let him login and then add his answer. My problem is that I lose content of the form when redirecting to login page.

These are my views:

def question(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    form = AnswerForm()

    return render(request, 'questions/question.html', {'question': question, 'form' : form},)

@login_required
def answer(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    form = AnswerForm(request.POST) if request.method == 'POST' else AnswerForm()
    if form.is_valid():
        answer = form.save(commit=False)
        answer.author = request.user
        answer.question = question
        answer.save()
    return HttpResponseRedirect(reverse('question', args=(question.id,)))

Form:

<form method="POST" action="{% url 'answer' question.id %}">
    {% csrf_token %}
    {{form.as_p}}
    <input type="submit" value="Odpowiedz">
</form>

Form in login template:

<form method="post" action="{% url 'login' %}">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="hidden" name="next" value="{{request.GET.next}}" />
    <input type="submit" value="login" />
</form>

I don't know if something more than url can be passed by using next.

user3565923
  • 153
  • 2
  • 12

1 Answers1

2

@login_required decorator automatically adds a next GET parameter to the LOGIN_URL, so that user is redirected back to the same page the login was triggered from. Right now, you're triggering it from the answer view, so user will come back directly to answer view. POST Data is lost whenever a redirect occurs, so there's no way you can get the data except for temporarily saving it in cookies or redirecting the user to question page after login.

Implementation 1

POST Data is not saved but the user gets redirected to QuestionView

from django.shortcuts import redirect, reverse
...
...

def answer(request, question_id):

    if not request.user.is_authenticated:
        return redirect("%s?next=%s" % (settings.LOGIN_URL, reverse('question-view-name'))
    ... 
    ...

Implementation 2

POST Data is saved to the session and then retrieved after login. I haven't tried it and it required you to serialize POST data to string. Also, requires django.contrib.sessions in INSTALLED_APPS and django.contrib.sessions.middleware.SessionMiddleware in your MIDDLEWARE. Checkout https://data-flair.training/blogs/django-sessions/ for how to set, create and delete session variables.

from django.shortcuts import redirect, reverse
...
...

def answer(request, question_id):

    if not request.user.is_authenticated:
        request.session['form_data'] = YourSerializerFunctionToSerializeFormData(request.POST) 
        # must retuern a string, use json.dumps() to convert a dictionary to string

        return redirect("%s?next=%s" % (settings.LOGIN_URL, reverse('answer-view-name', args=[question_id]))

    data = None
    if request.method == 'GET':
        if 'form_data' in request.session:
            data = request.session['form_data']
            del request.session['form_data'] # Delete the key once done
    else:
        data = request.POST

    ...
    form = AnswerForm(data) if data else AnswerForm()
    ... 
    ...

Hope it helps.

thisisayush
  • 292
  • 1
  • 8