Commit d6a663553957fa87b9715b4f75f5bfb4afb551ba
1 parent
86fde4fa00
Exists in
master
Fixed up some model errors, added docstrings to some
Showing 2 changed files with 195 additions and 36 deletions Inline Diff
flashcards/migrations/0003_auto_20150429_0344.py
View file @
d6a6635
File was created | 1 | # -*- coding: utf-8 -*- | ||
2 | from __future__ import unicode_literals | |||
3 | ||||
4 | from django.db import models, migrations | |||
5 | ||||
6 | ||||
7 | class Migration(migrations.Migration): | |||
8 | ||||
9 | dependencies = [ | |||
10 | ('flashcards', '0002_auto_20150429_0248'), | |||
11 | ] | |||
12 | ||||
13 | operations = [ | |||
14 | migrations.AlterModelOptions( | |||
15 | name='class', | |||
16 | options={'ordering': ['-quarter']}, | |||
17 | ), | |||
18 | migrations.AlterModelOptions( | |||
19 | name='flashcard', | |||
20 | options={'ordering': ['-pushed']}, | |||
21 | ), | |||
22 | migrations.RenameField( | |||
23 | model_name='class', | |||
24 | old_name='professor', | |||
25 | new_name='instructor', | |||
26 | ), | |||
27 | migrations.RemoveField( | |||
28 | model_name='flashcard', | |||
29 | name='hidden', | |||
30 | ), | |||
31 | migrations.AddField( | |||
32 | model_name='flashcard', | |||
33 | name='hide_reason', | |||
34 | field=models.CharField(help_text=b'Reason for hiding this card', max_length=255, blank=True), | |||
35 | ), | |||
36 | migrations.AddField( | |||
37 | model_name='flashcard', | |||
38 | name='is_hidden', | |||
39 | field=models.BooleanField(default=False), | |||
40 | ), | |||
41 | migrations.AlterField( | |||
42 | model_name='flashcard', | |||
43 | name='associated_class', | |||
44 | field=models.ForeignKey(help_text=b'The class with which the card is associated', to='flashcards.Class'), | |||
45 | ), | |||
46 | migrations.AlterField( | |||
47 | model_name='flashcard', | |||
48 | name='mask', | |||
49 | field=models.ForeignKey(blank=True, to='flashcards.FlashcardMask', help_text=b'The default mask for this card', null=True), | |||
50 | ), | |||
51 | migrations.AlterField( | |||
52 | model_name='flashcard', | |||
53 | name='material_date', | |||
54 | field=models.DateTimeField(help_text=b'The date with which the card is associated'), | |||
55 | ), | |||
56 | migrations.AlterField( | |||
57 | model_name='flashcard', | |||
58 | name='previous', | |||
59 | field=models.ForeignKey(blank=True, to='flashcards.Flashcard', help_text=b'The previous version of this card, if one exists', null=True), | |||
60 | ), | |||
61 | migrations.AlterField( | |||
62 | model_name='flashcard', | |||
63 | name='pushed', | |||
64 | field=models.DateTimeField(help_text=b'When the card was first pushed', auto_now_add=True), | |||
65 | ), | |||
66 | migrations.AlterField( | |||
67 | model_name='flashcard', | |||
68 | name='text', | |||
69 | field=models.CharField(help_text=b'The text on the card', max_length=255), | |||
70 | ), | |||
71 | migrations.AlterField( | |||
72 | model_name='userflashcard', | |||
73 | name='mask', | |||
74 | field=models.ForeignKey(help_text=b"A mask which overrides the card's mask", to='flashcards.FlashcardMask'), | |||
75 | ), | |||
76 | migrations.AlterField( | |||
77 | model_name='userflashcard', | |||
78 | name='pulled', | |||
79 | field=models.DateTimeField(help_text=b'When the user pulled the card', null=True, blank=True), | |||
80 | ), | |||
81 | migrations.AlterField( | |||
82 | model_name='userflashcard', | |||
83 | name='unpulled', | |||
84 | field=models.DateTimeField(help_text=b'When the user unpulled this card', null=True, blank=True), | |||
85 | ), | |||
86 | migrations.AlterField( | |||
87 | model_name='userflashcardreview', | |||
88 | name='blanked_word', | |||
89 | field=models.CharField(help_text=b'The character range which was blanked', max_length=8, blank=True), | |||
90 | ), | |||
91 | migrations.AlterField( | |||
92 | model_name='userflashcardreview', | |||
93 | name='correct', | |||
94 | field=models.NullBooleanField(help_text=b"The user's self-evaluation of their response"), | |||
95 | ), | |||
96 | migrations.AlterField( | |||
97 | model_name='userflashcardreview', | |||
98 | name='response', | |||
99 | field=models.CharField(help_text=b"The user's response", max_length=255, null=True, blank=True), | |||
100 | ), |
flashcards/models.py
View file @
d6a6635
from django.contrib.auth.models import User | 1 | 1 | from django.contrib.auth.models import User | |
from django.db import models | 2 | 2 | from django.db.models import * | |
3 | 3 | |||
4 | 4 | |||
class UserFlashcard(models.Model): | 5 | 5 | class UserFlashcard(Model): | |
""" | 6 | 6 | """ | |
Represents the relationship between a user and a flashcard by: | 7 | 7 | Represents the relationship between a user and a flashcard by: | |
1. A user has a flashcard in their deck | 8 | 8 | 1. A user has a flashcard in their deck | |
2. A user used to have a flashcard in their deck | 9 | 9 | 2. A user used to have a flashcard in their deck | |
3. A user has a flashcard hidden from them | 10 | 10 | 3. A user has a flashcard hidden from them | |
""" | 11 | 11 | """ | |
user = models.ForeignKey(User) | 12 | 12 | user = ForeignKey(User) | |
mask = models.ForeignKey('FlashcardMask') | 13 | 13 | mask = ForeignKey('FlashcardMask', help_text="A mask which overrides the card's mask") | |
pulled = models.DateTimeField(null=True) | 14 | 14 | pulled = DateTimeField(blank=True, null=True, help_text="When the user pulled the card") | |
flashcard = models.ForeignKey('Flashcard') | 15 | 15 | flashcard = ForeignKey('Flashcard') | |
unpulled = models.DateTimeField(null=True) | 16 | 16 | unpulled = DateTimeField(blank=True, null=True, help_text="When the user unpulled this card") | |
17 | 17 | |||
class Meta: | 18 | 18 | class Meta: | |
19 | # There can be at most one UserFlashcard for each User and Flashcard | |||
unique_together = (('user', 'flashcard'),) | 19 | 20 | unique_together = (('user', 'flashcard'),) | |
index_together = ["user", "flashcard"] | 20 | 21 | index_together = ["user", "flashcard"] | |
22 | # By default, order by most recently pulled | |||
ordering = ['-pulled'] | 21 | 23 | ordering = ['-pulled'] | |
22 | 24 | |||
def is_hidden(self): | 23 | 25 | def is_hidden(self): | |
26 | """ | |||
27 | A card is hidden only if a user has not ever added it to their deck. | |||
28 | :return: Whether the flashcard is hidden from the user | |||
29 | """ | |||
return not self.pulled | 24 | 30 | return not self.pulled | |
25 | 31 | |||
def is_active(self): | 26 | 32 | def is_in_deck(self): | |
33 | """ | |||
34 | :return:Whether the flashcard is in the user's deck | |||
35 | """ | |||
return self.pulled and not self.unpulled | 27 | 36 | return self.pulled and not self.unpulled | |
28 | 37 | |||
29 | 38 | |||
class FlashcardMask(models.Model): | 30 | 39 | class FlashcardMask(Model): | |
ranges = models.CharField(max_length=255) | 31 | 40 | """ | |
41 | A serialized list of character ranges that can be blanked out during review. | |||
42 | This is encoded as '13-145,150-195' | |||
43 | """ | |||
44 | ranges = CharField(max_length=255) | |||
32 | 45 | |||
33 | 46 | |||
class Flashcard(models.Model): | 34 | 47 | class Flashcard(Model): | |
text = models.CharField(max_length=255) | 35 | 48 | text = CharField(max_length=255, help_text='The text on the card') | |
associated_class = models.ForeignKey('Class') | 36 | 49 | associated_class = ForeignKey('Class', help_text='The class with which the card is associated') | |
pushed = models.DateTimeField() | 37 | 50 | pushed = DateTimeField(auto_now_add=True, help_text="When the card was first pushed") | |
material_date = models.DateTimeField() | 38 | 51 | material_date = DateTimeField(help_text="The date with which the card is associated") | |
previous = models.ForeignKey('Flashcard', null=True) | 39 | 52 | previous = ForeignKey('Flashcard', null=True, blank=True, | |
author = models.ForeignKey(User) | 40 | 53 | help_text="The previous version of this card, if one exists") | |
hidden = models.CharField(null=True, blank=True, max_length=255) | 41 | 54 | author = ForeignKey(User) | |
mask = models.ForeignKey(FlashcardMask, null=True) | 42 | 55 | is_hidden = BooleanField(default=False) | |
56 | hide_reason = CharField(blank=True, max_length=255, help_text="Reason for hiding this card") | |||
57 | mask = ForeignKey(FlashcardMask, blank=True, null=True, help_text="The default mask for this card") | |||
43 | 58 | |||
def is_visible_to(self, user): | 44 | 59 | class Meta: | |
result = self.userflashcard_set.filter(user=user) | 45 | 60 | # By default, order by most recently pushed | |
61 | ordering = ['-pushed'] | |||
46 | 62 | |||
63 | def is_hidden_from(self, user): | |||
64 | """ | |||
65 | A card can be hidden globally, but if a user has the card in their deck, | |||
66 | this visibility overrides a global hide. | |||
67 | :param user: | |||
68 | :return: Whether the card is hidden from the user. | |||
69 | """ | |||
70 | result = user.userflashcard_set.filter(flashcard=self) | |||
71 | if not result.exists(): return self.is_hidden | |||
72 | return result[0].is_hidden() | |||
73 | ||||
74 | ||||
@classmethod | 47 | 75 | @classmethod | |
def cards_visible_to(cls, user): | 48 | 76 | def cards_visible_to(cls, user): | |
return cls.objects.filter(hidden=False).exclude(userflashcard=user, | 49 | 77 | """ | |
userflashcard__pulled=None) | 50 | 78 | :param user: | |
79 | :return: A queryset with all cards that should be visible to a user. | |||
80 | """ | |||
81 | return cls.objects.filter(hidden=False).exclude(userflashcard=user, userflashcard__pulled=None) | |||
51 | 82 | |||
52 | 83 | |||
class UserFlashcardReview(models.Model): | 53 | 84 | class UserFlashcardReview(Model): | |
user_flashcard = models.ForeignKey(UserFlashcard) | 54 | 85 | """ | |
when = models.DateTimeField() | 55 | 86 | An event of a user reviewing a flashcard. | |
blanked_word = models.CharField(max_length=8) | 56 | 87 | """ | |
response = models.CharField(max_length=255, blank=True, null=True) | 57 | 88 | user_flashcard = ForeignKey(UserFlashcard) | |
correct = models.NullBooleanField() | 58 | 89 | when = DateTimeField() | |
90 | blanked_word = CharField(max_length=8, blank=True, help_text="The character range which was blanked") | |||
91 | response = CharField(max_length=255, blank=True, null=True, help_text="The user's response") | |||
92 | correct = NullBooleanField(help_text="The user's self-evaluation of their response") | |||
59 | 93 | |||
94 | def status(self): | |||
95 | """ | |||
96 | There are three stages of a review object: | |||
97 | 1. the user has been shown the card | |||
98 | 2. the user has answered the card | |||
99 | 3. the user has self-evaluated their responses's correctness | |||
100 | :return: string (evaluated, answered, viewed) | |||
101 | """ | |||
102 | if self.correct != None: return "evaluated" | |||
103 | if self.response: return "answered" | |||
104 | return "viewed" | |||
60 | 105 | |||
class Class(models.Model): | 61 | 106 | ||
department = models.CharField(max_length=50) | 62 | 107 | class Class(Model): | |
course_num = models.IntegerField() | 63 | 108 | """ | |
name = models.CharField(max_length=50) | 64 | 109 | A UCSD course taught by an instructor during a quarter. | |
professor = models.CharField(max_length=50) | 65 | 110 | Different sections taught by the same instructor in the same quarter are considered identical.s | |
quarter = models.CharField(max_length=4) | 66 | 111 | """ | |
members = models.ManyToManyField(User) | 67 | 112 | department = CharField(max_length=50) | |
113 | course_num = IntegerField() | |||
114 | name = CharField(max_length=50) | |||
115 | instructor = CharField(max_length=50) | |||
116 | quarter = CharField(max_length=4) | |||
117 | members = ManyToManyField(User) | |||
118 | ||||
119 | class Meta: | |||
120 | unique_together = (('department', 'course_num', 'quarter', 'instructor'),) | |||
121 | ordering = ['-quarter'] | |||
68 | ||||