Нет описания

import_from_excel.py 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. from django.core.management.base import BaseCommand, CommandError
  2. from django.db import transaction
  3. import xlrd
  4. from ... import models
  5. from pick import pick
  6. class SheetWrapper(object):
  7. def __init__(self, sheet):
  8. self.sheet = sheet
  9. def __str__(self):
  10. return self.sheet.name
  11. def import_sheet(sheet, category):
  12. start_row = None
  13. start_col = None
  14. for row in range(sheet.nrows):
  15. for col in range(sheet.ncols):
  16. cell = sheet.cell(row, col)
  17. if cell.ctype == xlrd.XL_CELL_TEXT:
  18. if cell.value.strip().lower() == 'day':
  19. start_row = row + 1
  20. start_col = col
  21. break
  22. if start_row is None:
  23. raise RuntimeError("No 'Day' column found in sheet %s" % sheet.name)
  24. if start_row >= sheet.nrows:
  25. raise RuntimeError("'Day' column in sheet %s contains no data" % sheet.name)
  26. if start_col >= sheet.ncols:
  27. raise RuntimeError("No columns found to the right of the 'Day' column in sheet %s" % sheet.name)
  28. expected_day = 1
  29. end_row = None
  30. feed_items = []
  31. for row in range(start_row, sheet.nrows):
  32. cell = sheet.cell(row, start_col)
  33. if cell.ctype != xlrd.XL_CELL_NUMBER:
  34. break
  35. day = int(cell.value)
  36. if day != expected_day:
  37. raise RuntimeError("'Day' column in sheet %s contains an unexpected value: %s (expecting %s)" % (sheet.name, day, expected_day))
  38. cell = sheet.cell(row, start_col + 1)
  39. if cell.ctype != xlrd.XL_CELL_TEXT:
  40. raise RuntimeError("No text found for day %s in sheet %s" % (day, sheet.name))
  41. feed_items.append({'day': day, 'message_text': cell.value})
  42. expected_day += 1
  43. end_row = row
  44. if end_row + 1 < sheet.nrows:
  45. cell = sheet.cell(end_row + 1, start_col)
  46. if cell.ctype != xlrd.XL_CELL_EMPTY:
  47. raise RuntimeError("'Day' column in sheet %s contains a non-numerical value: %s" % (sheet.name, cell.value))
  48. option, index = pick(['No', 'Yes'], title='You are about to import days %s to %s\nfrom sheet %s\ninto category %s.\nContinue?' % (feed_items[0]['day'], feed_items[-1]['day'], sheet.name, category.name))
  49. if index == 0:
  50. return
  51. with transaction.atomic():
  52. models.FeedItem.objects.filter(feed_category=category).delete()
  53. for feed_item in feed_items:
  54. models.FeedItem.objects.create(
  55. feed_category=category,
  56. day_number=feed_item['day'],
  57. message_text=feed_item['message_text']
  58. )
  59. class Command(BaseCommand):
  60. help = 'Imports feed items from an Excel spreedsheet.'
  61. def add_arguments(self, parser):
  62. parser.add_argument('file_name')
  63. def handle(self, *args, **options):
  64. file_name = options['file_name']
  65. category_choices = ['>> Quit']
  66. for category in models.FeedCategory.objects.order_by('name'):
  67. category_choices.append(category)
  68. book = xlrd.open_workbook(file_name)
  69. sheet_choices = ['>> Quit']
  70. for sheet in book.sheets():
  71. sheet_choices.append(SheetWrapper(sheet))
  72. while True:
  73. option, index = pick(sheet_choices, title='Select the worksheet to be imported:')
  74. if index == 0:
  75. break
  76. sheet = sheet_choices[index].sheet
  77. option, index = pick(category_choices, title='Select the destination category:')
  78. if index == 0:
  79. break
  80. category = category_choices[index]
  81. import_sheet(sheet, category)