| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- # -*- coding: utf-8 -*-
- from __future__ import unicode_literals
- from django.db import models
- from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
- from django.db.utils import IntegrityError
- from django.utils.text import Truncator
- import re
- #import logging
- #logger = logging.getLogger('console')
- unique_constraint_re = re.compile(r'^UNIQUE\s+constraint\s+failed:(.*)$', re.IGNORECASE)
- class ModelEx(models.Model):
- class Meta:
- abstract = True
- def get_duplicate_key_error_dict(self, fields):
- return {NON_FIELD_ERRORS: 'Duplicate value for %s' % ', '.join(fields)}
- def save(self, *args, **kwargs):
- try:
- super(ModelEx, self).save(*args, **kwargs)
- except IntegrityError as e:
- match = unique_constraint_re.search(e.message)
- if match:
- fields = [x.strip().split('.')[-1] for x in match.group(1).split(',')]
- raise ValidationError(self.get_duplicate_key_error_dict(fields))
- else:
- raise
- class FeedCategory(ModelEx):
- name = models.CharField(max_length=50, unique=True)
- description = models.CharField(max_length=255, blank=True)
- days_required = models.PositiveIntegerField(default=366)
- class Meta:
- verbose_name = 'Category'
- verbose_name_plural = 'Categories'
- def get_duplicate_key_error_dict(self, fields):
- if fields[0] == 'name':
- return {'name': 'There is already a category with this name'}
- else:
- return super(FeedCategory, self).get_duplicate_key_error_dict(fields)
- @property
- def status(self):
- last_day = 0
- total_missing = 0
- missing_days = []
- for item in FeedItem.objects.filter(feed_category=self).order_by('feed_category_id', 'day_number'):
- day = item.day_number
- missing_count = day - last_day - 1
- total_missing += missing_count
- # The unique key and order_by on FeedItem ensure that missing_count
- # cannot be less than 0.
- if missing_count == 1:
- missing_days.append(str(day - 1))
- elif missing_count > 1:
- missing_days.append('{0}-{1}'.format(last_day + 1, day - 1))
- last_day = day
- missing_count = self.days_required - last_day
- if missing_count > 0:
- total_missing += missing_count
- if missing_count == 1:
- missing_days.append(str(self.days_required))
- elif missing_count > 1:
- missing_days.append('{0}-{1}'.format(last_day + 1, self.days_required))
- if missing_days:
- return "WARNING: Missing {0} day{1}: {2}".format(total_missing, '' if total_missing == 1 else 's', ', '.join(missing_days))
- else:
- return "Complete"
- def __unicode__(self):
- return self.name
- class FeedItem(ModelEx):
- feed_category = models.ForeignKey(FeedCategory, on_delete=models.CASCADE)
- day_number = models.PositiveIntegerField()
- message_text = models.CharField(max_length=160)
- class Meta:
- verbose_name = 'Item'
- verbose_name_plural = 'Items'
- unique_together = ('feed_category', 'day_number')
- def get_duplicate_key_error_dict(self, fields):
- return {'day_number': 'There is already an item with this day number'}
- def __unicode__(self):
- return u'{0}: {1}'.format(self.day_number, Truncator(self.message_text).chars(20))
|