Django Maximum Recursion Depth Exceeded. View loops infinitely

Viewed 125

I am writing an application that will decode make, model, and year information for provided VIN numbers from cars. The script works standalone but when integrated into my django app and called through a button click on my web app, the view begins to loop infinitely and raises a RecursionError. I will provide relevant code below

base html template

<!DOCTYPE html>
{%load static%}

<Html>
  <title>What the F*cking F*ck</title>
  <head>
  
  </head>

  
  <h1>Here I will attempt to recreate the Working Title File in a somewhat nice looking format. </h1>
  <h4>We'll see what happens</h4>
  
  <div>
    {% block header %}
    <p>Upload an IPDF with the Browse Button below</p>
    <form method="post" enctype="multipart/form-data">
      {% csrf_token %}
      {{ form.as_p }}
      <button type="submit">Upload</button>
    </form>
    {% endblock %}
    <p><a href="{% url 'wtf' %}">Return to upload</a></p>
    <p>

  </div>

  <div id="address">
    {% block address %}
      <p>This is where stuff would render if you had uploaded something. But you didn't. Or it broke. So shame on both of us.</p>
    {% endblock %}
  </div>
</Html>

address_render.html (inherits from base, also called wtf). This one works as intended. When I click the button here to call the view vin_decode it breaks.

{% extends "wtf2/wtf.html" %}
<script scr='../../jquery-3.6.0.js'>
</script>
{% block header %}
    <p>Successful Address Validation</p>
    <form action="{% url 'vin' %}" method='post'>
    {% csrf_token %}
    <button type="submit">Click here to begin VIN Decode</button>
    </form>
{% endblock %}

{% block address %}
<div>
    <p>Sick! The address validation portion worked. Now what? Please Check the returned address. This one came back invalid</p>
    <table>
        <thead>
            <tr>
                <th>Street Lines</th>
                <th>City</th>
                <th>State</th>
                <th>ZIP</th>
                <th>Returned StreetLines</th>
                <th>Returned City</th>
                <th>Returned State</th>
                <th>Returned ZIP</th>
                <th>Returned Status</th>
                <th>Resolved</th>
                <th>Delivery Point Valid</th>
                <th>Interpolated Street Address</th>
                <th>City Match?</th>
                <th>ZIP Match?</th>
                <th>Resolved Address?</th>
                <th>Valid?</th>
            </tr>
        </thead>
        <tbody>
        {% if d %}
        {% for i in d%}
        
            <tr>
            {% if i.Valid == "No"%}
                <td>{{ i.StreetLines }}</td>
                <td>{{ i.City }}</td>
                <td>{{ i.State }}</td>
                <td>{{ i.ZIP }}</td>
                <td>{{ i.Returned_StreetLines }}</td>
                <td>{{ i.Returned_City }}</td>
                <td>{{ i.Returned_State }}</td>
                <td>{{ i.Returned_ZIP }}</td>
                <td>{{ i.Returned_Status }}</td>
                <td>{{ i.Resolved }}</td>
                <td>{{ i.DPV }}</td>
                <td>{{ i.InterpolatedStreetAddress }}</td>
                <td>{{ i.City_Match }}</td>
                <td>{{ i.ZIP_Match }}</td>
                <td>{{ i.Resolved_Address }}</td>
                <td>{{ i.Valid }}</td>
            {% endif %}
            </tr>
        {% endfor %}
        {% endif %}
        </tbody>
    </table>
</div>
{% endblock %}

vin_decode.html (also inherits from base.html)

{% extends "wtf2/wtf.html" %}
{% comment %} <script scr='../../jquery-3.6.0.js'>
</script> {% endcomment %}
{% block header %}
    <p>Successful VIN Decoding</p>
    <p><a href="{% url 'wtf' %}">Click here to return to upload</a></p>

    
{% endblock %}

{% block address %}
<div>
    <p>Sick! The VIN Decoding worked!</p>
    <table>
        <thead>
            <tr>
                <th>Site</th>
                <th>Vehicle Number</th>
                <th>VIN</th>
                <th>Current Device</th>
                <th>Make</th>
                <th>Model</th>
                <th>Year</th>
                <th>Old Make</th>
                <th>Old Model</th>
                <th>Old Year</th>
            </tr>
        </thead>
        <tbody>
        {% if d %}
        {% for i in d%}
        
            <tr>
                <td>{{ i.site }}</td>
                <td>{{ i.vehicle_number }}</td>
                <td>{{ i.vin }}</td>
                <td>{{ i.current_device }}</td>
                <td>{{ i.Returned_Make }}</td>
                <td>{{ i.Returned_Model }}</td>
                <td>{{ i.Returned_Year }}</td>
                <td>{{ i.make }}</td>
                <td>{{ i.model }}</td>
                <td>{{ i.year }}</td>
            </tr>
        {% endfor %}
        {% endif %}
        </tbody>
    </table>
</div>
{% endblock %}

views.py

from django.http.response import HttpResponseRedirect
from django.shortcuts import render
from suds.plugin import Context
from .models import Document
from .forms import DocumentForm
import pandas as pd
import sqlite3
import json
from .Scripts.address_validation import address_validation
from .Scripts.vin_decode import vin_decode
from .Scripts.data_collect import *

# cnxn_string = sqlite3.connect('db.sqlite3')

# Create your views here.
def doc_upload(request):
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            doc = Document.objects.latest('id')
            
            # project_upload(doc.document.path, doc.pk)
            # vehicle_upload(doc.document.path, doc.pk)
            data_collection(doc.document.path,doc.pk)
            df = address_validation(doc.pk)
            json_records = df.reset_index().to_json(orient='records')
            data = json.loads(json_records)
            context = {'d': data}
            return render(request, 'wtf2/address_render.html', context)
    else:
        form = DocumentForm()
    return render(request, 'wtf2/wtf.html', {
        'form': form
    })

def vin_decode(request):
    print('Is this thing on')
    doc = Document.objects.latest('id')
    df = vin_decode(doc.pk)
    json_records = df.reset_index().to_json(orient='records')
    df = json.loads(json_records)
    context = {'d': df}
    return render(request, 'wtf2/vin_decode.html', context)

urls.py

from django.contrib import admin
from django.urls import path
from introduction import views
from wtf2 import views as wtviews
from django.conf import settings
from django.conf.urls.static import static
from django.conf.urls import url, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('team', views.team, name='team'),
    path('team', views.showdetails, name='PPTracker'),
    path('wtf', wtviews.doc_upload, name='wtf'),
    path('wtf/vin_decode', wtviews.vin_decode, name='vin')
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Any idea what's going on here? I get a RecursionError that calls the first line of the view "vin_decode" repeatedly. I added a debug

print('Is this thing on')

to test within the vin_decode view, and the error code on the terminal prints 'Is this thing on' 1000 times before breaking. Will also add the full error message.

Is this thing on
Internal Server Error: /wtf/vin_decode
Traceback (most recent call last):
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\ross.martin\Documents\GitHub\Django-Unchained\website-Project\wtf2\views.py", line 40, in vin_decode
    df = vin_decode(doc.pk)
  File "C:\Users\ross.martin\Documents\GitHub\Django-Unchained\website-Project\wtf2\views.py", line 40, in vin_decode
    df = vin_decode(doc.pk)
  File "C:\Users\ross.martin\Documents\GitHub\Django-Unchained\website-Project\wtf2\views.py", line 40, in vin_decode
    df = vin_decode(doc.pk)
  [Previous line repeated 938 more times]
  File "C:\Users\ross.martin\Documents\GitHub\Django-Unchained\website-Project\wtf2\views.py", line 39, in vin_decode
    doc = Document.objects.latest('id')
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\query.py", line 674, in latest
    return self.reverse()._earliest(*fields)
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\query.py", line 668, in _earliest
    return obj.get()
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\query.py", line 425, in get
    num = len(clone)
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\query.py", line 269, in __len__
    self._fetch_all()
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\query.py", line 1308, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\query.py", line 53, in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\sql\compiler.py", line 1143, in execute_sql
    sql, params = self.as_sql()
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\sql\compiler.py", line 498, in as_sql
    extra_select, order_by, group_by = self.pre_sql_setup()
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\sql\compiler.py", line 56, in pre_sql_setup
    order_by = self.get_order_by()
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\sql\compiler.py", line 361, in get_order_by
    resolved = expr.resolve_expression(self.query, allow_joins=True, reuse=None)
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\expressions.py", line 249, in resolve_expression
    c.set_source_expressions([
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\expressions.py", line 250, in <listcomp>
    expr.resolve_expression(query, allow_joins, reuse, summarize)
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\expressions.py", line 247, in resolve_expression
    c = self.copy()
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\expressions.py", line 348, in copy
    return copy.copy(self)
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\copy.py", line 102, in copy
    return _reconstruct(x, None, *rv)
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\copy.py", line 264, in _reconstruct
    y = func(*args)
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\copyreg.py", line 95, in __newobj__
    return cls.__new__(cls, *args)
  File "C:\Users\ross.martin\AppData\Local\Programs\Python\Python39\lib\site-packages\django\utils\deconstruct.py", line 16, in __new__
    obj = super(klass, cls).__new__(cls)
RecursionError: maximum recursion depth exceeded while calling a Python object
2 Answers

You make a recursive call with:

def vin_decode(request):
    print('Is this thing on')
    doc = Document.objects.latest('id')
    df = vin_decode(doc.pk)
    json_records = df.reset_index().to_json(orient='records')
    df = json.loads(json_records)
    context = {'d': df}
    return render(request, 'wtf2/vin_decode.html', context)

It is irrelevant that you imported vin_decode, since you override this by defining a function with the same name.

You can import the vin_decode of the module as another name, and then call that functions, so:

from .Scripts.vin_decode import vin_decode as vin_decode_func

# …

def vin_decode(request):
    print('Is this thing on')
    doc = Document.objects.latest('id')
    df = vin_decode_func(doc.pk)
    json_records = df.reset_index().to_json(orient='records')
    df = json.loads(json_records)
    context = {'d': df}
    return render(request, 'wtf2/vin_decode.html', context)

you are using vin_decode name for two things: one function you import

from .Scripts.vin_decode import vin_decode

and then the view itself.

In df = vin_decode(doc.pk) you think you are calling the function but the view is calling itself in an endless loop.

Easiest solution: name your view with another name, like vin_decode_view

Related