project.py
project.py

Reputation: 103

Why I'm unable to download my document with django? and how to do it?

I'm new to django and still learning, and I got here, in my own infinite loop, if I do how I sholud it be but i have an errors and it won't work, but if I do it like this there are no errors but it won't work. I want to user to be able to create excel template as he wish, this is simplified version that I want to work, just input few information and on base of that to be able to create excel template.

This is views.py

from django.http import HttpResponse
from django.shortcuts import render
import xlsxwriter
from xlsxwriter import workbook
from django.forms import Form, CharField, ChoiceField, IntegerField
from django.core.validators import MaxValueValidator, MinValueValidator

def home(request):
    return render(request, 'my_app/home.html')

class TemplateForm(Form):
    doc_name = CharField(label='Document name')
    sheetnames = CharField(label='Sheetnames')
    choices = []
    for year in range (1900, 2050):
        choices.append( (year, year) )
    year1 = ChoiceField(label='Starting Year', initial=2021, choices=choices)
    year2 = ChoiceField(label='Ending Year', initial=2022, choices=choices)    
    row_names = CharField(label='Column names')

def create_template(request):
    if request.method == 'GET':
        form = TemplateForm()
        return render(request, 'my_app/create_template.html', {'form':form})
    else:
        form = TemplateForm(request.POST)

def create_form(doc_name, sheetnames, years, row_names):
    workbook = xlsxwriter.Workbook(doc_name + '_template.xlsx')
    worksheet_introduction = workbook.add_worksheet( "introduction" )
    for i in sheetnames:
        worksheet_data = workbook.add_worksheet(i)
        worksheet_data.write_row(0, 1, years)
        worksheet_data.write_column(1, 0, row_names)
    workbook.close()
    return workbook

This is my_app/templates/my_app/create_template.html

{% extends "my_app/base.html" %}
{% block content %}

<form action="create_template" method="GET">
  {% csrf_token %}
  <h1>Create your template</h1>
  <div class="item">
    <table>
      {{ form.as_table }}
    </table>
  </div>
  <div class="btn-block">
    <input type="button" type="submit" value="Create and Download!"/>
  </div>
</form>
{% endblock content %}

This is my_app/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='my-home'),
    path('create-template/', views.create_template, name='my-create-template'),
]

Upvotes: 0

Views: 270

Answers (1)

Steve Stacha
Steve Stacha

Reputation: 198

When you get stuck the best thing to do is break things down and attack them one at a time. I simplified your example so you could have something working to extend to what you need. Start with Django. I created a urls.py that had a default route to home.

from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='my-home'),
]

This calls the home function in views.py. The first time the page is hit the GET method is used which initializes the form. When you click submit it uses the POST method to the same page (action="", method="POST"). The same view is called again only this time it is not GET so it calls the create_workbook function to use the form data to save the file. Once saved, it lets the user know the filename and if anything goes wrong it redirects back to the form page.

views.py

from django.shortcuts import render, HttpResponse, redirect
import xlsxwriter
from django.forms import Form, CharField, ChoiceField


class TemplateForm(Form):
    doc_name = CharField(label='Document name')
    sheet_name = CharField(label='Sheetname')
    choices = []
    for year in range(1900, 2050):
        choices.append((year, year))
    year1 = ChoiceField(label='Starting Year', initial=2021, choices=choices)
    year2 = ChoiceField(label='Ending Year', initial=2022, choices=choices)


def home(request):
    if request.method == 'GET':
        form = TemplateForm()
        return render(request, 'my_app/create_template.html', {'form': form})
    else:
        form = TemplateForm(request.POST)
        if form.is_valid():
            create_workbook(form.cleaned_data.get('doc_name'), form.cleaned_data.get('sheet_name'), form.cleaned_data.get('year1'), form.cleaned_data.get('year2'))
            return HttpResponse(f"saved workbook to {form.cleaned_data.get('doc_name')}_template.xlsx")
        return redirect('my-home')


def create_workbook(doc_name, sheet_name, year1, year2):
    workbook = xlsxwriter.Workbook(doc_name + '_template.xlsx')
    worksheet = workbook.add_worksheet(sheet_name)
    row = 0
    col = 0
    year1 = int(year1)
    year2 = int(year2)
    if year1 <= year2:
        years = range(year1, year2)
    else:
        years = range(year2, year1)
    for i in years:
        worksheet.write(row, col, i)
        row += 1
    workbook.close()

my_app/base.html

<html>
<head>

</head>
<body>
    {% block content %}{% endblock %}
</body>
</html>

my_app/create_template.html

{% extends "my_app/base.html" %}
{% block content %}

<form action="" method="POST">
  {% csrf_token %}
  <h1>Create your template</h1>
  <div class="item">
    <table>
      {{ form.as_table }}
    </table>
  </div>
  <div class="btn-block">
    <input type="submit" value="Create and Download!"/>
  </div>
</form>
{% endblock content %}

Example output Hopefully this working example will help.

Upvotes: 2

Related Questions