2

I am working on a django web application. Here the web app generates a pandas dataframe when a form is submitted. This dataframe is stored in the root directory. I have another view that is used for downloading the generated csv file. But when I redirect to the download page, I get a No reverse match error.

this is my code so far

def randomfilename(stringLength=8):
    lettersAndDigits = string.ascii_letters + string.digits
    return ''.join(random.choice(lettersAndDigits) for i in range(stringLength))

def generate_dataframe(request):
    if request.method == 'POST':
        ...
        df = pd.DataFrame(columns=cols)
        df['title'] = title_lst
        df['link'] = product_links[:1]

        fn = randomfilename()
        df.to_csv('./'+fn+'.csv')
        return redirect("download_file", filename = fn)

def download_file(request, filename):
    if request.method == 'POST':

        file_path = './'+filename

        file = open(file_path, 'r')
        mime_type, _ = mimetypes.guess_type(file_path)
        response = HttpResponse(file, content_type=mime_type)
        response['Content-Disposition'] = "attachment; filename=%s" % filename

        return response

project urls.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('scraper.urls')),
]

scraper urls.py

urlpatterns = [
    path('generate', views.generate_dataframe, name='generate_dataframe'),
    path('download/<filename>/', views.download_file, name='download_file'),
]

I know I am messing up the URL somewhere. But I am not sure how to rectify this problem. Please help me. Thanks in advance.

Sashaank
  • 880
  • 2
  • 20
  • 54

1 Answers1

2

Try this:

In your views

from django.urls import reverse

def generate_dataframe(request):
    ...
return redirect(reverse('download_file', kwargs={'filename': fn}))

In your urls.py:

urlpatterns = [
    ...
    path('download/<str:filename>/', views.download_file, name='download_file'),
]

In your template:

{% url 'download_file' filename %}
Wariored
  • 1,303
  • 14
  • 25
  • I am still getting this error `Reverse for 'download_file' with no arguments not found. 1 pattern(s) tried: ['download/(?P[^/]+)/$']` – Sashaank Jun 18 '20 at 11:03
  • is your urls.py in your base app or in another app? – Wariored Jun 18 '20 at 11:27
  • The project contains only the project folder and the app folder. There is only one app in the project. The app name is scraper. The URLs in the question is in the app folder. I have edited the question to add project URLs also. Please take a look – Sashaank Jun 18 '20 at 11:56
  • in your urls.py add a variable before the urlsparterns `app_name='scraper'`. Then in your views, do : `return redirect(reverse('scraper:download_file', kwargs={'filename': fn}))` – Wariored Jun 18 '20 at 13:24
  • I tried that. It did not help. I added another path to the app URLs like this `path('download/', views.download_file, name='download_file'),`, so that when it is a `get request`, display the webpage and when the button is pressed, download the file. Now I get a different error `download_file() missing 1 required positional argument: 'filename' `. Is what I am doing right? – Sashaank Jun 18 '20 at 13:29
  • if you want the filename to be optional, you should initialize it: `def download_file(request, filename=None):`. I would recommend trying to solve your problem. The reverse should find the url. – Wariored Jun 18 '20 at 13:40
  • It is not optional. Basically I want to download the csv file once it is generated with the click of a button. This button resides in a new page that is download_file. I just don't know how to achieve this – Sashaank Jun 18 '20 at 13:43
  • Are you sure the filename is not None or equals to ''. Print the variable `fn` – Wariored Jun 18 '20 at 13:43
  • The filename is not `None`. I checked that. It gives the required value – Sashaank Jun 18 '20 at 13:44
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/216218/discussion-between-wariored-and-sashaank). – Wariored Jun 18 '20 at 13:45