3 from django.db import models as _models
4 from django.forms import ValidationError as _ValidationError
6 from . import LOG as LOG
7 from . import util as _util
10 class NamedItem (_models.Model):
11 name = _models.CharField(max_length=100)
12 abbrev = _models.CharField('abbreviation', max_length=20)
18 def __unicode__(self):
19 return u'{0.abbrev}'.format(self)
22 class NFPASpecial (NamedItem):
23 """An NFPA Special rating (e.g. 'OX', '-W-', 'SA', ...).
25 symbol = _models.CharField(max_length=3, blank=True, null=True)
27 def __unicode__(self):
29 return u'{0.symbol}'.format(self)
30 return super(NFPASpecial, self).__unicode__()
33 class CASNumber (NamedItem):
34 "Chemical Abstracts Service registery number"
35 cas = _models.CharField(
36 'CAS#', max_length=20, unique=True)
39 if not _util.valid_CASno(self.cas):
40 raise _ValidationError("invalid CAS number '{}'".format(self.cas))
43 class Chemical (NamedItem):
44 """A chemical (in the abstract, not an instance of the chemical)
46 Separating ``Chemical``\s from ``ChemicalInstance``\s avoids
47 duplicate information (e.g. you can have two bottles of acetic
50 cas = _models.ManyToManyField(CASNumber, blank=True, null=True)
51 msds = _models.FileField(
52 'Material safety data sheet', upload_to=_util.chemical_upload_to,
53 blank=True, null=True)
54 health = _models.PositiveIntegerField(
55 'NFPA health rating', blank=True, null=True)
56 fire = _models.PositiveIntegerField(
57 'NFPA fire rating', blank=True, null=True)
58 reactivity = _models.PositiveIntegerField(
59 'NFPA reactivity rating', blank=True, null=True)
60 special = _models.ManyToManyField(NFPASpecial, blank=True, null=True)
61 mutagen = _models.NullBooleanField()
62 carcinogen = _models.NullBooleanField()
63 teratogen = _models.NullBooleanField()
64 note = _models.TextField('notes', blank=True, null=True)
66 def cas_numbers(self):
67 if self.cas.count() == 0:
69 return ', '.join(cas.cas for cas in self.cas.all())
72 return ' '.join(str(special) for special in self.special.all())
75 class Location (NamedItem):
76 "A chemical storage location (e.g. 'acidic liquids')"
80 class Vendor (NamedItem):
82 url = _models.URLField('URL', blank=True, null=True)
83 note = _models.TextField('notes', blank=True, null=True)
86 class ChemicalInstance (_models.Model):
87 """An instance of a ``Chemical``
89 For example, 1L of acetic acid from Vendor X.
91 chemical = _models.ForeignKey(Chemical, related_name='chemical_instances')
92 location = _models.ForeignKey(Location, related_name='chemical_instances')
93 amount = _models.CharField(max_length=100)
94 vendor = _models.ForeignKey(Vendor, related_name='chemical_instances')
95 catalog = _models.CharField('vendor catalog number', max_length=100)
96 received = _models.DateField(auto_now_add=True, editable=True)
97 disposed = _models.DateField(blank=True, null=True)
100 ordering = ['chemical', 'received', 'disposed', 'id']