【Django】データをCSV化する方法

　CSVダウンロード機能を実装してみたので、記事に記録しておきます。今回の実装で参考になった記事を以下に記載しておきます。

[Python + Django でCSVのダウンロード／アップロード](https://qiita.com/t-iguchi/items/d2862e7ef7ec7f1b07e5)
[【django】csvのダウンロード・アップロードの方法](https://kuma-server.com/djangocsv/)
[Django逆引きチートシート（QuerySet編）](https://qiita.com/uenosy/items/54136aff0f6373957d22)

## 挙動

[![Image from Gyazo](https://i.gyazo.com/b6852eb7ea5533d40fbe01b2a4d6e6ce.gif)](https://gyazo.com/b6852eb7ea5533d40fbe01b2a4d6e6ce)

[![Image from Gyazo](https://i.gyazo.com/823e86b3b05650443ba06d0c603cca8a.png)](https://gyazo.com/823e86b3b05650443ba06d0c603cca8a)

## 実装内容

templates/index.html
```django
{% extends "base.html" %}
{% block title %}トップページ{% endblock %}
{% block header%}
<div>
  <a class="user_registration" href="{% url 'e_comic:users' %}">ユーザー登録</a>
  <a class="test" href="{% url 'e_comic:test' %}">テストページ</a>
</div>
{% endblock %}
{% block content %}
<h1>トップページ</h1>
<div>
 <a class="user_registration" href="{% url 'e_comic:comic_create' %}">漫画登録</a>
</div>
<br>
<div>
  <table border="1">
    <tr>
      <th>漫画名</th>
      <th>評点</th>
      <th>コメント</th>
    </tr>
    {% for comic_evaluation in comic_evaluation_list %}
      <tr>
        <td>{{comic_evaluation.comic_name.comic_name}}</td>
        <td>{{comic_evaluation.comic_score}}</td>
        <td>{{comic_evaluation.comment}}</td>
      </tr>
    {% endfor %}
  </table>
  <br>
  <div>
    <a href="{% url 'e_comic:csv_export' %}" class="btn btn-primary">csv出力</a>
  </div>
</div>
{% endblock %}
```

urls.py
```python
from django.urls import path
from . import views

app_name = "e_comic"
urlpatterns = [
    path('',views.index,name="index"),
    path('export/', views.csv_export, name='csv_export'),
]
```

models.py
```python
import uuid
from django.db import models
from django.core.validators import MaxValueValidator

class Comic(models.Model):
    comic_pk = models.UUIDField(primary_key=True, default=uuid.uuid4,editable=False)
    comic_name = models.CharField(verbose_name="漫画名",max_length=128,null=False,unique=True)
    created_at = models.DateTimeField(verbose_name='作成日時', auto_now_add=True)
    updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True)

class ComicEvaluation(models.Model):
    comic_evaluation_pk = models.UUIDField(primary_key=True, default=uuid.uuid4,editable=False)
    comic_name = models.ForeignKey(Comic,verbose_name="漫画名",to_field="comic_name",db_column="comic_name",related_name="c_names",max_length=128,null=False,on_delete=models.PROTECT)
    comic_score = models.PositiveSmallIntegerField(verbose_name="評点",validators=[MaxValueValidator(100)],null=False)
    comment = models.TextField(verbose_name="コメント",null=True)
    nickname = models.ForeignKey(User,to_field="nickname",verbose_name="作成者",db_column="created_by",max_length=100,null=True,on_delete=models.PROTECT)
    created_at = models.DateTimeField(verbose_name='作成日時', auto_now_add=True)
    updated_at = models.DateTimeField(verbose_name='更新日時', auto_now=True)
```

views.py
```python
from django.http import HttpResponse
from django.shortcuts import render
from e_comic.DAO.EComicDao import getComicEvaluations,getDateTime
import csv,urllib

def index(request):
  comic_evaluation_list = getComicEvaluations()
  context = {
    'comic_evaluation_list' : comic_evaluation_list,
  }
  return render(request, 'index.html', context)

def csv_export(request):
    response = HttpResponse(content_type='text/csv; charset=Shift-JIS')
    date_time = getDateTime()
    str_time = date_time.strftime('%Y%m%d%H%M')
    f = "漫画評価" + "_" + str_time + ".csv"
    filename = urllib.parse.quote((f).encode("utf8"))
    response['Content-Disposition'] = 'attachment; filename*=UTF-8\'\'{}'.format(filename)

    writer = csv.writer(response)
    comic_evaluation_list = getComicEvaluations()
    for evaluation in comic_evaluation_list:
        writer.writerow([evaluation.comic_name.comic_name, evaluation.comic_score,evaluation.comment,evaluation.created_at])
    return response
```

　こちらはViewに記載できる内容ですが、ファイル分けしてみたものです。
EComicDao.py
```python
from e_comic.models import ComicEvaluation

def getComicEvaluations():
  comic_evaluation_list = ComicEvaluation.objects.all()
  return comic_evaluation_list

def getDateTime():
  latest_time = ComicEvaluation.objects.latest("updated_at")
  latest_time = latest_time.updated_at
  return latest_time
```

　以上です。