My work on the KidsTasks app has hit a bit of a roadblock. I’ve been looking at adding forms for the users (i.e. mom) to assign new tasks to kids. As I’ve worked, I’ve realized that I made two important mistakes when starting this project. The first was unavoidable; not taking the structure of how Django works into account when creating the design.
The second mistake was more avoidable. True to my education and experience, I focused the original design on the internal data structures of the problem rather than the user interface.
The two mistakes together brought me to the point where, while it’s possible to create the UI I want on the models I currently have, it’s much more cumbersome than I feel it should be. Therefore it’s time to re-evaluate the design.
User Scenarios
Most of my experience comes from embedded systems where the user interface is trivial if not completely absent. Focusing on the UI earlier is not something in my normal skill set. That said, let’s dive in.
I envision two primary user scenarios:
- After school, the parents sit down with the kids and evaluate what homework and other tasks need to be accomplished. These get added to the list for the day. There should be recurring tasks that occur on given days every week and ad-hoc tasks for that day only.
- The kids, when they have completed a task, can go to the app and indicate that it is completed, having its status changed. (changing color from red to green, strike-through, etc)
User Interface
To satisfy the first user scenario, I envision a form that looks similar to the the following:
Task Name: My New Task
Which Kid:
x kid1 _ kid2
Repeat Every
x Mon _ Tue _ Wed x Thu x Fri _ Sat _ Sun
<save and add another> <save> <exit>
For the second user scenario, I’m envisioning a horizontal row of colored boxes with the name of each task inside. Each row would correspond to a particular kid. Clicking on a box would change its state (from red to green to indicate it was completed).
___________________________________ Kid1: | piano | sleep | chew gum | walk | ___________________________________ ___________________________________ Kid2: | piano | sleep | spelling | talk | ___________________________________
New Models
Considering all this, I threw the old design out and started with a new set of models. This actually made things much simpler and fits into the Django world view a bit better.
The Kid model changed to just a name. I was mistaken in my earlier thinking that the Kid needed to “own” the set of tasks. Once I saw the database modeling underneath the hood, it made sense that I merely needed to create a table of tasks which had a foreign key to the Kid, allowing me to do a simple query to get all the tasks for a given Kid.
I still ended up with two different types of tasks; the first is a RepeatingTask which is in reality a template for a Task. It stores the idea of a task that is repeated on various days of the week. Note that I did some searches on the best way to store days of week in a Django model. There are clearly more efficient ways to store this, but using separate boolean fields makes creating forms for that info much easier. I chose to stick with “easy” over “efficient” for this project.
The second task is an actual task assigned to a Kid on a particular date. This is, thankfully, fairly straightforward.
Here’s the code:
#tasks/models.py """ Define the data models for the KidsTasks app """ import datetime from django.db import models class Kid(models.Model): """ Defines the kids which have to do the tasks. """ name = models.CharField(max_length=256) def __str__(self): return self.name class Meta: ordering = ['name', ] class Task(models.Model): """ A Task is associated with a kid and a date. This is the actual thing the kid has to do! """ name = models.CharField(max_length=256) completed = models.BooleanField() date = models.DateField(default=datetime.datetime.now) kid = models.ForeignKey(Kid) def __str__(self): return self.name class Meta: ordering = ['name', ] class RepeatingTask(models.Model): """ Defines a repeating task """ name = models.CharField(max_length=256) kid = models.ForeignKey(Kid) # NOTE: RepeatingTasks are kid specific monday = models.BooleanField(default=False) tuesday = models.BooleanField(default=False) wednesday = models.BooleanField(default=False) thursday = models.BooleanField(default=False) friday = models.BooleanField(default=False) saturday = models.BooleanField(default=False) sunday = models.BooleanField(default=False) def __str__(self): return "{0}:{1}".format(self.kid.name, self.name) class Meta: ordering = ['kid', 'name', ]
That’s where I ended this time. Hopefully I’ll get back on track next time in creating views and forms for this app.
If you’re interested, this code will be stored in the blog/04-Redesign branch.
thanks for reading!
jima