Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialBrian Pemberton
4,902 PointsDjango Model | Relationship question. Student->School Class relationship?
My code below:
class Students(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
classChoice1 = ?
classChoice2 = ?
classChouce3 = ?
class Class(models.Model):
class_name = models.CharField(max_length=30)
class_discription = models.CharField(max_length=30)
Say for example I have Nth students, S1 S2 S3 ... and Nth classes (as in college class) C1 C2 C3 ... And I want to create a relationship where each student can only be assigned to one class uniquely for each classChoice selected. How would I create that relationship?
class Class(models.Model): class_name = models.CharField(max_length=30) class_description = models.CharField(max_length=30)
Say for example I have Nth students, S1 S2 S3 ... and Nth classes (as in college class) C1 C2 C3 ... And I want to create a relationship where each student can only be assigned to one class uniquely for each classChoice selected. How would I create that relationship?
Brian Pemberton
4,902 Points@Chris Freeman - "Are you looking to keep S1.classChoice1 unique from S1.classChoice2 and S1classChoice3, etc. " - YES
1 Answer
Chris Freeman
Treehouse Moderator 68,441 PointsThere are two parts to this answer. The first is to create a ForeignKey for each choice to the Classes.
class Students(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
classChoice1 = models.ForeignKey(Class, related_name='choice1')
classChoice2 = models.ForeignKey(Class, related_name='choice2')
classChoice3 = models.ForeignKey(Class, related_name='choice3')
The second part of making the values mutually exclusive is harder. There is a concept of "uniqueness" but that applies to the case you didn't want where choice1 was unique across all students. Since you want to allow multiple student to have the same Choice1, you have to solve it using Student class methods verses a database enforcement.
This can be done by treating the Choices as a Python properties.
Changing the field names to have a leading underscore:
class Students(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
_classChoice1 = models.ForeignKey(Class, related_name='choice1')
_classChoice2 = models.ForeignKey(Class, related_name='choice2')
_classChoice3 = models.ForeignKey(Class, related_name='choice3')
@property
def classChoice1(self):
return self._classChoice1
@classChoice1.setter
def classChoice1(self, input):
# check if new value conflicts with other existing choices
If input != self._classChoice2 and input != self._classChoice3
self._classChoice1 = input
else:
# decide how you handle the error
pass
# repeat for the other two Choice fields
This blog has a similar example.
Chris Freeman
Treehouse Moderator 68,441 PointsAn additional caution is to not use the name "Class" as the name of the class since it is too close to the keyword class
Brian Pemberton
4,902 PointsThank you for your help!
Quick Question:
Could I use the
unique=True
Property on the foreign key instead of the setter method you are showing? Or does the
unique=True
Refer to the data base globally?
Chris Freeman
Treehouse Moderator 68,441 PointsCorrect. Using unique=True
on, say, classChoice1 would mean no other Students
could have that same class also as their classChoice1.
As additional feedback, the name of classes are usually in singular form since each instance represents a single student. So Student
would be the preferred form.
Brian Pemberton
4,902 PointsAnother question. Is there a way to refactor
@property
def classChoice1(self):
return self._classChoice1
@classChoice1.setter
def classChoice1(self, input):
# check if new value conflicts with other existing choices
If input != self._classChoice2 and input != self._classChoice3
self._classChoice1 = input
else:
# decide how you handle the error
pass
into a method that handle Nth class choices ? Could I use a DICT to store the the choices then have only one method to deal with the logic of making sure each choice is unique?
Chris Freeman
Treehouse Moderator 68,441 PointsThere isn't much refactoring to do. Perhaps you could create a helper function that checks if the purposed new value is the same as any other attribute:
def check_attr_match(self, input):
for item in dir(self):
# check for name match and value match
if 'classChoice' in item and input == getattr(self, item):
# attribute match found return True
return True
return False
@property
def classChoice1(self):
return self._classChoice1
@classChoice1.setter
def classChoice1(self, input):
# check if new value conflicts with other existing choices
If check_attr_match(input):
# Match found. Decide how you handle the error
pass
else:
self._classChoice1 = input
Chris Freeman
Treehouse Moderator 68,441 PointsChris Freeman
Treehouse Moderator 68,441 PointsNot sure I follow. Are you looking to keep
S1.classChoice1
unique fromS1.classChoice2
andS1classChoice3
, etc.Or
S1.classChoice1
unique fromS2.classChoice1
and all otherS{3...N}.classChoice1
; and similarly for the other choices?