Django скачать файл с помощью CBV

#django

Вопрос:

Как использовать представления на основе классов, например. TemplateView для отображения шаблона Django со ссылками на скачивание? Перейдя по ссылке, вы должны начать загрузку выбранного файла. Я уже знаю, как это сделать с помощью представлений, основанных на функциях.

Кроме того, хорошая ли идея использовать filename slug в качестве параметра URL (имя файла) для запросов GET или мне следует использовать другой метод?

Ответ №1:

По сути, вы хотите отправить запрос в CBV и ответить ответом, содержащим ваш CSV.

Я собираюсь предположить, что вы хотите использовать тот же CBV, который вы используете, например, для вашего TemplateView уже. Для этого я бы настроил def post(self, request) метод на CBV для обработки вашего конкретного запроса, что-то вроде:

 class MyTemplateView(TemplateView):

    def post(self, request, *args, **kwargs):
        request_type = request.POST.get("type", [])
        
        # Check whether the request type indicates we should generate
        # a CSV
        if "generate_csv" in request_type:
            return self.generate_csv()

        return super(MyTemplateView, self).post(*args, **kwarfs)

    def generate_csv(self):
        response = HttpResponse(content_type="text/csv")
        response[
            "Content-Disposition"
        ] = 'attachment; filename="name_of_csv_download_{}.csv"'.format(
            time.strftime("%d/%m/%Y")
        )

        writer = csv.writer(response)
        writer.writerow(
            [
                "Heading 1",
                "Heading 2",
                "Heading 3",
                etc
            ]
        )

        data = ...get data you want to write to csv...

        for row in data:
            writer.writerow(
                [
                    row.id,
                    row.property1,
                    row.property2,
                    etc
                ]
            )

        return response
 

Таким образом, ключ здесь в том, чтобы установить правильный content_type ответ вместе с Content-Disposition заголовком. По сути, это ничем не отличается от того, как мы работаем с представлениями на основе функций, как подробно описано здесь, и вы можете применить ту же логику к def get(self, request) использованию параметров запроса, а не параметров публикации, чтобы добиться того же самого.

Ответ №2:

Это не так уж плохо-создать слиток с именем файла, как только вы выполните свою бизнес-логику и проблему, связанную с безопасностью