Home > Software design >  Fixing No Reverse Match in a Django Project
Fixing No Reverse Match in a Django Project

Time:10-12

I am getting the following error: Reverse for 'order_pdf' with arguments '('',)' not found. 1 pattern(s) tried: ['business_plan/(?P<id>[0-9] )/pdf/$']

I am not sure exactly what is the reason for it.

Here is the model:

class Info(models.Model):
    logo                = models.ImageField(default='report-cover.jpg', null=True, blank=True)
    date_posted         = models.DateTimeField(default=timezone.now)
    name                = models.CharField(null=True, blank=True, max_length=100)

Here is the views.py

def add_business_plan(request):
    # info=Info.objects.all()

    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = infoForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            form.save()
            business_name = form.cleaned_data.get('businessName')
            messages.success(request, f'PDF created for {business_name}!')
            # return redirect('businessplan:businessplan')
            # redirect(reverse('businessplan:businessplan', kwargs={'successful_submit': True}))
            return render(request, 'businessplan/businessplan.html', {'successful_submit': True})

    # if a GET (or any other method) we'll create a blank form
    else:
        form = infoForm()
        print(form.errors)
    return render(request, 'businessplan/businessplan.html', {'form': form, 'successful_submit': False,
  # "Info": info
 })

def order_pdf(request, info_id):
    info = get_object_or_404(Info, id=info_id)
    html = render_to_string('businessplan/pdf.html', {'info': info})
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="{}-Business Plan.pdf"'.format(info.businessName)
    weasyprint.HTML(string=html, base_url=request.build_absolute_uri()).write_pdf(response,
                                                                                  stylesheets=[weasyprint.CSS(settings.STATICFILES_DIRS[0]   '\css\\report.css')], presentational_hints=True)
    return response

def admin_order_pdf(request, info_id):
    info = get_object_or_404(Info, id=info_id)
    html = render_to_string('businessplan/pdf.html', {'info': info})
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'filename="{}-Business Plan.pdf"'.format(info.businessName)
    weasyprint.HTML(string=html, base_url=request.build_absolute_uri()).write_pdf(response,
                                                                                  stylesheets=[weasyprint.CSS(settings.STATICFILES_DIRS[0]   '\css\\report.css')], presentational_hints=True)
    return response

Here is the urls.py

urlpatterns = [
    path('', add_business_plan, name='businessplan'),
    path('businessplan/admin/info/<str:info_id>/pdf/', admin_order_pdf, name='admin_order_pdf'),
    #path('<str:info_id>/pdf/', admin_order_pdf, name='admin_order_pdf'),
    path('<str:info_id>/pdf/', order_pdf, name='order_pdf'),

]

Here is the businessplan.html snippet of the template:

....modal divs
<a href="{% url 'businessplan:order_pdf' Info.id %}">
<!--<a href="{% url 'businessplan:order_pdf' obj.id %}">-->
<!--<a href="{% url 'businessplan:order_pdf' Info.info_id %}">-->

....modal divs

            <form class="needs-validation" method="post" novalidate enctype="multipart/form-data">

              {% csrf_token %}
                <div class="form-outline mb-4 mt-3">
                    <input required autocomplete="off" type="text" class="form-control" name=" name"
                           {% if form.is_bound %} value= "{{ form.name.value }}" {% endif %}>
                    <label class="form-label">Name</label>
                </div>
                {% for err in form.name.errors %}
                    <small class="text-danger ml-2">{{ err }}</small>
                {% endfor %}
              </div>
            </form>

    {% if successful_submit %}
        <script type="text/javascript">
            $(document).ready(function(){
                $("#exampleModal").modal('show');
            });
        </script>
    {% endif %}

I can access the pdf from the admin but I am trying to access to add this button for easier functionality.

I have tried changing the info_id to id it didn't work.

What is the reason for this error?

Here is the traceback:

Internal Server Error: /business_plan/
Traceback (most recent call last):
  File "C:\Users\User\Desktop\Portfolio\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\User\Desktop\Portfolio\venv\lib\site-packages\django\core\handlers\base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\User\Desktop\Portfolio\businessplan\views.py", line 30, in add_business_plan
    return render(request, 'businessplan/businessplan.html', {'form': form, 'successful_submit': False })
  File "C:\Users\User\Desktop\Portfolio\venv\lib\site-packages\django\shortcuts.py", line 19, in render
    content = loader.render_to_string(template_name, context, request, using=using)
  File "C:\Users\User\Desktop\Portfolio\venv\lib\site-packages\django\template\loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "C:\Users\User\Desktop\Portfolio\venv\lib\site-packages\django\template\backends\django.py", line 61, in render
    return self.template.render(context)
  File "C:\Users\User\Desktop\Portfolio\venv\lib\site-packages\django\template\base.py", line 170, in render
    return self._render(context)
  File "C:\Users\User\Desktop\Portfolio\venv\lib\site-packages\django\template\base.py", line 162, in _render
    return self.nodelist.render(context)
  File "C:\Users\User\Desktop\Portfolio\venv\lib\site-packages\django\template\base.py", line 938, in render
    bit = node.render_annotated(context)
  File "C:\Users\User\Desktop\Portfolio\venv\lib\site-packages\django\template\base.py", line 905, in render_annotated
    return self.render(context)
  File "C:\Users\User\Desktop\Portfolio\venv\lib\site-packages\django\template\defaulttags.py", line 446, in render
    url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)
  File "C:\Users\User\Desktop\Portfolio\venv\lib\site-packages\django\urls\base.py", line 87, in reverse
    return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
  File "C:\Users\User\Desktop\Portfolio\venv\lib\site-packages\django\urls\resolvers.py", line 685, in _reverse_with_prefix
    raise NoReverseMatch(msg)
django.urls.exceptions.NoReverseMatch: Reverse for 'order_pdf' with arguments '('',)' not found. 1 pattern(s) tried: ['business_plan/(?P<info_id>[^/] )/pdf/$']
[10/Oct/2021 06:58:51] "GET /business_plan/ HTTP/1.1" 500 143694

CodePudding user response:

Looks like <a href="{% url 'businessplan:order_pdf' Info.id %}"> doesn't work because you don't pass it to the template context.

As a result, the call fails because Info.id is an empty string (cf https://docs.djangoproject.com/en/3.2/ref/templates/api/#invalid-template-variables), hence breaking the URL reversing logic.

You should pass your info instance to the template context to make this work, e.g like this:

return render(
    request,
    'businessplan/businessplan.html',
    {
        'form': form,
        'successful_submit': False,
        "Info": info_instance
    }
)
  • Related