|
| 1 | +import csv |
| 2 | +import io |
1 | 3 | import logging
|
2 | 4 | import uuid
|
3 | 5 |
|
| 6 | +from django.http import StreamingHttpResponse |
4 | 7 | from rest_framework import status, viewsets
|
5 | 8 | from rest_framework.permissions import IsAuthenticated
|
6 | 9 | from rest_framework.response import Response as DRFResponse
|
|
18 | 21 | logger = logging.getLogger(__name__)
|
19 | 22 |
|
20 | 23 |
|
| 24 | +def _get_sheet_csv(columns, cells, total_rows): |
| 25 | + output = io.StringIO() |
| 26 | + writer = csv.writer(output, quoting=csv.QUOTE_MINIMAL) |
| 27 | + |
| 28 | + # Write header |
| 29 | + writer.writerow([col.title for col in columns]) |
| 30 | + yield output.getvalue() |
| 31 | + output.seek(0) |
| 32 | + output.truncate(0) |
| 33 | + |
| 34 | + for row in range(1, total_rows + 1): |
| 35 | + # Create a dict of cell_id to cell from this row |
| 36 | + row_cells = {cell.cell_id: cell for cell in cells.values() if cell.row == row} |
| 37 | + |
| 38 | + # Create a list of cell values for this row, using an empty string if the cell doesn't exist |
| 39 | + row_values = [] |
| 40 | + for column in columns: |
| 41 | + cell = row_cells.get(f"{column.col}{row}") |
| 42 | + row_values.append(cell.display_data if cell else "") |
| 43 | + |
| 44 | + writer.writerow(row_values) |
| 45 | + yield output.getvalue() |
| 46 | + output.seek(0) |
| 47 | + output.truncate(0) |
| 48 | + |
| 49 | + |
21 | 50 | class PromptlySheetAppExecuteJob(ProcessingJob):
|
22 | 51 | @classmethod
|
23 | 52 | def generate_job_id(cls):
|
@@ -141,3 +170,39 @@ def run_async(self, request, sheet_uuid=None):
|
141 | 170 | ).add_to_queue()
|
142 | 171 |
|
143 | 172 | return DRFResponse({"job_id": job.id, "run_id": run_entry.uuid}, status=202)
|
| 173 | + |
| 174 | + def download(self, request, sheet_uuid=None): |
| 175 | + if not sheet_uuid: |
| 176 | + return DRFResponse(status=status.HTTP_400_BAD_REQUEST) |
| 177 | + |
| 178 | + profile = Profile.objects.get(user=request.user) |
| 179 | + |
| 180 | + sheet = PromptlySheet.objects.get(uuid=sheet_uuid, profile_uuid=profile.uuid) |
| 181 | + if not sheet: |
| 182 | + return DRFResponse(status=status.HTTP_404_NOT_FOUND) |
| 183 | + |
| 184 | + response = StreamingHttpResponse( |
| 185 | + streaming_content=_get_sheet_csv(sheet.columns, sheet.cells, sheet.data.get("total_rows", 0)), |
| 186 | + content_type="text/csv", |
| 187 | + ) |
| 188 | + response["Content-Disposition"] = f'attachment; filename="sheet_{sheet_uuid}.csv"' |
| 189 | + return response |
| 190 | + |
| 191 | + def download_run(self, request, sheet_uuid=None, run_id=None): |
| 192 | + if not sheet_uuid or not run_id: |
| 193 | + return DRFResponse(status=status.HTTP_400_BAD_REQUEST) |
| 194 | + |
| 195 | + profile = Profile.objects.get(user=request.user) |
| 196 | + |
| 197 | + sheet = PromptlySheet.objects.get(uuid=sheet_uuid, profile_uuid=profile.uuid) |
| 198 | + run_entry = PromptlySheetRunEntry.objects.get(uuid=run_id, sheet_uuid=sheet.uuid) |
| 199 | + |
| 200 | + if not run_entry: |
| 201 | + return DRFResponse(status=status.HTTP_404_NOT_FOUND) |
| 202 | + |
| 203 | + response = StreamingHttpResponse( |
| 204 | + streaming_content=_get_sheet_csv(sheet.columns, sheet.cells, sheet.data.get("total_rows", 0)), |
| 205 | + content_type="text/csv", |
| 206 | + ) |
| 207 | + response["Content-Disposition"] = f'attachment; filename="sheet_{sheet_uuid}_{run_id}.csv"' |
| 208 | + return response |
0 commit comments