class Entry(models.Model): author = models.CharField(max_length=20) published = models.BooleanField() feature = models.BooleanField(default=False) objects = manager_from(AuthorMixin, PublishedMixin, unpublished) broken = manager_from(PublishedMixin, manager_cls=FeaturedManager) featured = manager_from(PublishedMixin, manager_cls=FeaturedManager, queryset_cls=ByAuthorQuerySet)
class InheritanceCastModel(models.Model): """ An abstract base class that provides a ``real_type`` FK to ContentType. For use in trees of inherited models, to be able to downcast parent instances to their child types. Pending deprecation; use InheritanceManager instead. """ real_type = models.ForeignKey(ContentType, editable=False, null=True) objects = manager_from(InheritanceCastMixin) def __init__(self, *args, **kwargs): warnings.warn( "InheritanceCastModel is pending deprecation. " "Use InheritanceManager instead.", PendingDeprecationWarning, stacklevel=2) super(InheritanceCastModel, self).__init__(*args, **kwargs) def save(self, *args, **kwargs): if not self.id: self.real_type = self._get_real_type() super(InheritanceCastModel, self).save(*args, **kwargs) def _get_real_type(self): return ContentType.objects.get_for_model(type(self)) def cast(self): return self.real_type.get_object_for_this_type(pk=self.pk) class Meta: abstract = True
class InheritanceCastModel(models.Model): """ An abstract base class that provides a ``real_type`` FK to ContentType. For use in trees of inherited models, to be able to downcast parent instances to their child types. """ real_type = models.ForeignKey(ContentType, editable=False, null=True) objects = manager_from(InheritanceCastMixin) def save(self, *args, **kwargs): if not self.id: self.real_type = self._get_real_type() super(InheritanceCastModel, self).save(*args, **kwargs) def _get_real_type(self): return ContentType.objects.get_for_model(type(self)) def cast(self): return self.real_type.get_object_for_this_type(pk=self.pk) class Meta: abstract = True
def test_pending_deprecation(self): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") manager_from() self.assertEqual(len(w), 1) assert issubclass(w[-1].category, PendingDeprecationWarning)
''' return self.with_reviewed_on_dates().values( 'reviewed_on').order_by().annotate( repetitions=Count('id')) def daily_duration(self, user, date=None): ''' Returns the time spent reviewing on the given date (defaulting to today) for `user`, in seconds. ''' items = self.of_user(user).of_day(user, date=date) return items.aggregate(Sum('duration'))['duration__sum'] CardHistoryManager = lambda: manager_from( CardHistoryManagerMixin, CardHistoryStatsMixin) class CardHistory(models.Model): objects = CardHistoryManager() card = models.ForeignKey('Card') response = models.PositiveIntegerField(editable=False) reviewed_at = models.DateTimeField() ease_factor = models.FloatField(null=True, blank=True) interval = models.FloatField(null=True, blank=True, db_index=True) #days # Was the card new when it was reviewed this time? was_new = models.BooleanField(default=False, db_index=True)
def recognition(self): return self.get(name='Recognition') @property def production(self): return self.get(name='Production') @property def kanji_reading(self): return self.get(name='Kanji Reading') @property def kanji_writing(self): return self.get(name='Kanji Writing') CardTemplateManager = lambda: manager_from(_CardTemplateManager) class CardTemplate(models.Model): objects = CardTemplateManager() fact_type = models.ForeignKey('flashcards.FactType') name = models.CharField(max_length=50) description = models.TextField(max_length=200, blank=True) front_template_name = models.CharField(max_length=50) back_template_name = models.CharField(max_length=50) #TODO use a template marker for 'answer' fields to be typed in, optionally front_prompt = models.CharField(max_length=200, blank=True) back_prompt = models.CharField(max_length=200, blank=True)
from itertools import chain import cards import usertagging class _DeckManager(object): def of_user(self, user): return self.filter(owner=user, active=True) def shared_decks(self): return self.filter(shared=True, active=True) def synchronized_decks(self, user): return self.filter(owner=user, synchronized_with__isnull=False) DeckManager = lambda: manager_from(_DeckManager) class Deck(models.Model): #manager objects = DeckManager() name = models.CharField(max_length=100) description = models.TextField(max_length=2000, blank=True) owner = models.ForeignKey(User, db_index=True) textbook_source = models.ForeignKey(Textbook, null=True, blank=True) picture = models.FileField(upload_to='/deck_media/', null=True, blank=True) #TODO upload to user directory, using .storage
def seconds_to_days(s): return s / 86400.0 class _FactTypeManager(object): @property def japanese(self): # Unfortunately hard-coded for now, since we only have 2 types, and # this is a relic of an old abandoned design that should be refactored. return self.get(id=1) def example_sentences(self): return self.get(id=2) FactTypeManager = lambda: manager_from(_FactTypeManager) class FactType(models.Model): objects = FactTypeManager() name = models.CharField(max_length=50) active = models.BooleanField(default=True, blank=True) #e.g. for Example Sentences for Japanese facts parent_fact_type = models.ForeignKey('self', blank=True, null=True, related_name='child_fact_types') many_children_per_fact = models.NullBooleanField(blank=True, null=True) # separate the cards of this fact initially # not used for child fact types (?) min_card_space = models.FloatField(default=seconds_to_days(600),
@property def expression(self): from apps.flashcards.models import FactType return self.get(name='expression', fact_type=FactType.objects.japanese) @property def reading(self): from apps.flashcards.models import FactType return self.get(name='reading', fact_type=FactType.objects.japanese) @property def meaning(self): from apps.flashcards.models import FactType return self.get(name='meaning', fact_type=FactType.objects.japanese) FieldTypeManager = lambda: manager_from(_FieldTypeManager) class FieldType(models.Model): objects = FieldTypeManager() fact_type = models.ForeignKey('flashcards.FactType') # Used for referencing fields by name in code, instead of by id name = models.CharField(max_length=50, blank=False) display_name = models.CharField(max_length=50, blank=False) #fk to the FieldType which contains a transliteration of this FieldType transliteration_field_type = models.OneToOneField('self', blank=True, null=True,
'''Stats data methods, primarily used for graphs and things.''' def with_due_dates(self): ''' Adds a `due_on` DateField-like value. Same as `due_at` minus its time information -- so just the day. ''' return self.extra(select={'due_on': 'date(due_at)'}) def due_counts(self): '''Number of cards due per day in the future.''' return self.with_due_dates().values('due_on').annotate( due_count=Count('id')) def due_today_count(self): '''The # of cards already due right now or later today.''' return self.filter( due_at__isnull=False, due_at__lte=datetime.datetime.today()).count() def future_due_counts(self): '''Same as `due_counts` but only for future, after today.''' return self.filter( due_at__gt=datetime.datetime.today()).with_due_dates().values( 'due_on').annotate(due_count=Count('id')) CardManager = lambda: manager_from( CommonFiltersMixin, SchedulerMixin, CardStatsMixin)