Files
rockviewer/three_d_viewer/models.py

138 lines
4.2 KiB
Python

"""
Defines the models that that Django application uses
"""
from django.db import models
from model_utils.managers import InheritanceManager
class CommonInfo(models.Model):
"""
Common base class for models that need a name and active field. It is
intended to be an abstract class.
"""
name = models.CharField(max_length=100)
active = models.BooleanField(default=True)
def __unicode__(self):
return self.name
class Meta:
"""
Declare the class as abstract
"""
abstract = True
class Category(CommonInfo):
"""
Contains the details for a category of samples. Categories have a parent
category field to another category which creates a tree structure.
"""
parent = models.ForeignKey('self', blank=True, null=True,
on_delete=models.SET_NULL,
related_name='children')
objects = InheritanceManager()
@property
def active_children(self):
return self.children.filter(active=True).order_by('name')
@property
def active_samples(self):
return self.samples.select_subclasses(Sample, Mineral).filter(active=True).order_by('name')
class Sample(CommonInfo):
"""
The definition of a model itself. The model_filename is the path relative
to the models directory.
"""
model_filename = models.CharField(max_length=1000)
description = models.CharField(max_length=2000, default='', blank=True,
null=True)
parent = models.ForeignKey(Category, blank=True, null=True,
on_delete=models.SET_NULL,
related_name="samples")
#Use the inheritance manager for handling subclasses
objects = InheritanceManager()
def GetTopParent(self, current_parent):
if current_parent.parent is None:
return current_parent
else:
return self.GetTopParent(current_parent.parent)
@property
def url(self):
cat = self.GetTopParent(self.parent)
if cat.name == 'Fossils':
return 'three_d_viewer:fossil_detail'
elif cat.name == 'Rocks':
return 'three_d_viewer:rock_detail'
else:
return 'three_d_viewer:sample_detail'
class Mineral(Sample):
"""
Extending the Sample class to add details specific to minerals
"""
chemical_formula = models.CharField(max_length=100, blank=True)
hardness = models.DecimalField(max_digits=3, decimal_places=2, blank=True, null=True)
specific_gravity = models.DecimalField(max_digits=4, decimal_places=2, blank=True, null=True)
cleavage_fracture = models.CharField(max_length=100, blank=True)
lustre = models.CharField(max_length=100, blank=True)
colour = models.CharField(max_length=100, blank=True)
streak = models.CharField(max_length=100, blank=True)
habit = models.CharField(max_length=1000, blank=True)
crystallography = models.CharField(max_length=100, blank=True)
identifying_features = models.CharField(max_length=1000, blank=True)
occurance = models.CharField(max_length=1000, blank=True)
@property
def url(self):
return 'three_d_viewer:mineral_detail'
class Question(models.Model):
"""
The definition of a multiple choice question, associated with a Sample
"""
text = models.CharField(max_length=2000)
sample = models.ForeignKey(Sample, related_name='questions')
def correct_answers(self):
"""
Return a list of correct answers to the question
"""
return self.answers.filter(correct=True)
def check_answer(self, answerid):
"""
Check if answerid is correct. Returns True if correct, else False
"""
for answer in self.correct_answers():
if answer.id == int(answerid):
return True
return False
def __unicode__(self):
return self.text
class Answer(models.Model):
"""
The definition of an answer to a Question
"""
text = models.CharField(max_length=2000)
correct = models.BooleanField(default=False)
question = models.ForeignKey(Question, related_name='answers')
def __unicode__(self):
return self.text