Carl Brubaker
Carl Brubaker

Reputation: 1665

Django 2 - reverse for view not found

I know there are already a hundred of these, but I have one app that I made, that works, and a new one I'm trying to make, that doesn't work.

I can't redirect to my 'detail' view from my create view. If I put a number into the address, it works, it is just the redirect that doesn't work. I've tried a couple of things to no avail. I'm sure it is something simple, I just can't see it.

urls.py

from django.urls import path

from . import views
app_name = 'service'
urlpatterns = [
        path('', views.create_employee_profile,    
            name='create_employee_profile'),
        path('<int:pk>/', views.customer_employee_profile_detail,
            name='detail'),
]

view.py

from django.shortcuts import render, redirect

from service.forms import EmployeeNameForm

def create_employee_profile(request):

    if request.POST:
        name_form = EmployeeNameForm(request.POST)

        if name_form.is_valid():
            new_name_form = name_form.save()
            return redirect('service:detail', pk=new_name_form.pk)

        else:
            return render(request, 'service/create_or_update_profile.html',
                        {'name_form': name_form})

    else:
        name_form = EmployeeNameForm()
        return render(request, 'service/create_or_update_profile.html',
                        {'name_form': name_form})

def customer_employee_profile_detail(request, pk):
    name = get_object_or_404(CustomerEmployeeName, pk=pk)
    return render(request,
                    'service/customer_employee_profile_detail.html', 
                    {'name': name}
                )

I've tried both 'detail' and 'service: detail' as well. Error is: Reverse for 'detail' not found. 'detail' is not a valid view function or pattern name.

Template

{% extends 'base.html' %}

{% block content %}
    <form method="post" action="">
        {% csrf_token %}

        <!--Content Header Bar-->
        <nav class="navbar navbar-light bg-light">
            <span class="navbar-brand mb-0 h1">Name and Address</span>
        </nav>
        <div class="form-group">
            {% include 'service/name_form_template.html' %}
        </div>
        <button type="submit" class="btn btn-primary" style="background-color: SteelBlue;">
            Save
        </button>
    </form>
{% endblock %}

The included template holds the layout.

The reason I’m not using generic views is because these will views will eventually contain multiple forms. I’m trying to build it like legos, start small and add on.

Upvotes: 1

Views: 698

Answers (1)

cezar
cezar

Reputation: 12032

The shortcut function redirect can accept also a model object as a first argument. In that case it would call the get_absolute_url method of the model class. I'd recommend to go with this approach, as it would put the logic in the model class. That would result in the so called fat models - thin controllers pattern. In Django it would be rather fat models - thin views.

So, without knowing anything about your models, I'm assuming some details and propose this:

class CustomerEmployeeName(models.Model):
    # fields

    def get_absolute_url(self):
        from django.urls import reverse
        return reverse('service:detail', kwargs={'pk': self.pk})

In your views you can change the line with the redirect to:

redirect(new_name_form)

This eventualy won't solve your problem immediately, as it is probably somewhere else, but it's in my opinion a better approach. The code is reusable and follows the DRY-principles.

Upvotes: 1

Related Questions