Search code examples
djangodjango-3.1

django 3 redirect with pk in form verification


@MODS- Although it has been asked on here before I can not find a suitable answer in Django 3, please read through all I have tried before deleting

Preamble: I am working through This Tutorial that is taught in Django 1, I am following it but making necessary changes for Django 3.

QUESTION: I receive an error when loading my page with a form on it.enter image description here

HTML for the form page:


{% block title %}Start a New Topic{% endblock %}

{% block breadcrumb %}
  <li class="breadcrumb-item"><a href="{% url 'home' %}">Boards</a></li>
  <li class="breadcrumb-item"><a href="{% url 'board_topics' board.pk %}">{{ board.name }}</a></li>
  <li class="breadcrumb-item active">New topic</li>
{% endblock %}

{% block content %}
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit" class="btn btn-success">Post</button>
  </form>
{% endblock %}

Base HTML:

{% block title %}Start a New Topic{% endblock %}

{% block breadcrumb %}
  <li class="breadcrumb-item"><a href="{% url 'home' %}">Boards</a></li>
  <li class="breadcrumb-item"><a href="{% url 'board_topics' board.pk %}">{{ board.name }}</a></li>
  <li class="breadcrumb-item active">New topic</li>
{% endblock %}

{% block content %}
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit" class="btn btn-success">Post</button>
  </form>
{% endblock %}

urls.py

from django.contrib import admin
from django.urls import path , re_path
#uses path and re_path for regex when needed.


from boards import views

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path('boards/(?P<pk>\d+)/$', views.board_topics, name='board_topics'),
    re_path('boards/(?P<pk>\d+)/new/$', views.new_topic, name='new_topic'),
    path('', views.home,name='home'),
]

Forms.py

from .models import Topic

class NewTopicForm(forms.ModelForm):
    message = forms.CharField(
        widget=forms.Textarea(
            attrs={'rows': 5, 'placeholder': 'What is on your mind?'}
        ),
        max_length=4000,
        help_text='The max length of the text is 4000.'
    )

    class Meta:
        model = Topic
        fields = ['subject', 'message']

views.py

from .models import Board, Topic, Post
from django.contrib.auth.models import User
from .forms import NewTopicForm
from django.http import HttpResponseRedirect

# Create your views here.
def home(request):
    boards = Board.objects.all()
    return render(request, 'home.html', {'boards': boards})

    
def board_topics(request, pk):
    try:
        board = Board.objects.get(pk=pk)
    except Board.DoesNotExist:
        raise Http404
    
    return render(request, 'topics.html', {'board': board})


def new_topic(request, pk):
    board = Board.objects.get(pk=pk)
    user = User.objects.first()  # TODO: get the currently logged in user

    if request.method == 'POST':
        form = NewTopicForm(request.POST)
        if form.is_valid():
            topic = form.save()
            return HttpResponseRedirect('/')

    else:
        form = NewTopicForm()
    return render(request, 'new_topic.html', {'form': form})

I believe my issue is coming from return HttpResponseRedirect('/').

in the tutorial they use a redirect return redirect('board_topics', pk=board.pk)

However to my knowledge this is not possible in django 3. Also when I looked on the official django 3.1 documentation in forms they use a HttpResponseRedirect aswell.

I have tried using a render but was not able to make it work either.

Any suggestions? I have been stuck on this for a few hours and want to get past it.


Solution

  • Try using reverse:

    from django.shortcuts import reverse
    
    ... your form ...
    return redirect(reverse('board_topics', kwargs={'pk': board.pk}))
    

    btw the regular redirect should also work, try it.

    edit

    you actually need to pass board as a parameter in your context in your form view:

     return render(request, 'new_topic.html', {'form': form, 'board': board})