Zach
Zach

Reputation: 429

Creating a Foreign Key in Django Model

I have the following in my Student model. I want to track the date of each point given to each student. The idea would be so that I could see not only how many points each student has, but also see the date each point was given. In the future I want to see the trend of students' points. How should I go about this? Should I use a Foreign Key in another class. I am new to this so thanks for reading.

class Student(models.Model): 
  CLASS_CHOICES = ( 
    (u'Yoga','Yoga'), 
    (u'Spanish', 'Spanish'), 
    (u'French', 'French'), 
    (u'Dance', 'Dance'), 
  ) 
  name = models.CharField(max_length=30) 
  points = models.IntegerField(max_length=4) 
  classname = models.CharField("Class Name",max_length=20, choices=CLASS_CHOICES) 

Upvotes: 5

Views: 22362

Answers (3)

alan
alan

Reputation: 4842

I think you may want to split out both the Class (I'm calling it 'Course', so as not to conflict with the Python idea of class), and tracking of points (i.e., scores) earned.

class Student(models.Model): 
    name = models.CharField(max_length=30)
    courses = models.ManyToManyField('Course')

class Course(models.Model):
    # Yoga, Spanish, French, etc.
    name = models.CharField(max_length=30)

class Score(models.Model):
    date = models.DateTimeField(auto_now_add=True)
    points = models.IntegerField(max_length=4)
    course = models.ForeignKey('Course', on_delete=models.CASCADE)
    student = models.ForeignKey('Student', on_delete=models.CASCADE)

Then the student can take many courses and get a series of point scores (i.e., test scores?) for each course.

Upvotes: 12

jpic
jpic

Reputation: 33420

You could have something like this:

class Student(models.Model): 
    CLASS_CHOICES = ( 
        (u'Yoga','Yoga'), 
        (u'Spanish', 'Spanish'), 
        (u'French', 'French'), 
        (u'Dance', 'Dance'), 
        ) 
    name = models.CharField(max_length=30) 
    classname = models.CharField("Class Name",max_length=20, choices = CLASS_CHOICES)

    @property
    def points(self):
        return self.point_set.count()

class Point(models.Model):
    creation_datetime = models.DateTimeField(auto_now_add=True)
    student = models.ForeignKey('Student')

Very easy to use:

In [3]: james = Student(classname='Yoga', name='James')

In [4]: james.save()
DEBUG (0.002) INSERT INTO "testapp_student" ("name", "classname") VALUES (James, Yoga); args=['James', 'Yoga']

In [5]: james.points
DEBUG (0.000) SELECT COUNT(*) FROM "testapp_point" WHERE "testapp_point"."student_id" = 1 ; args=(1,)
Out[5]: 0

In [6]: james.point_set.create()
DEBUG (0.001) INSERT INTO "testapp_point" ("creation_datetime", "student_id") VALUES (2012-03-28 09:38:35.593110, 1); args=[u'2012-03-28 09:38:35.593110', 1]
Out[6]: <Point: Point object>

In [7]: james.points
DEBUG (0.001) SELECT COUNT(*) FROM "testapp_point" WHERE "testapp_point"."student_id" = 1 ; args=(1,)
Out[7]: 1

In [8]: james.point_set.create()
DEBUG (0.001) INSERT INTO "testapp_point" ("creation_datetime", "student_id") VALUES (2012-03-28 09:38:41.516848, 1); args=[u'2012-03-28 09:38:41.516848', 1]
Out[8]: <Point: Point object>

In [9]: james.points
DEBUG (0.000) SELECT COUNT(*) FROM "testapp_point" WHERE "testapp_point"."student_id" = 1 ; args=(1,)
Out[9]: 2

I wasn't sure if you wanted to track points per class too. In that case, just add classname to the Point model.

Also, note that Point.creation_datetime will automatically be set to the date and time that the model is saved. I just posted a basic pattern you can customize to your needs.

Upvotes: 3

Sid
Sid

Reputation: 7631

I would make a new Document named Points which has a datetime field and modify Student to have a Reference to the Document Points instead of points as an IntegerField.

If you were using mongoengine, I'd recommend making Points an EmbeddedDocument and Embedding it in Student.

Upvotes: 0

Related Questions