I need to store some values in the database, distance, weight etc. In my model, i have field that contains quantity of something and IntegerField whith choices option, that determines what this quantity means(length, time duration etc). Should i create model for units and physical quantity or should i use IntegerField that contains type of unit?
It depends on how you want to use it. Let's say you have length value and two possible units, cm and mm. If you want only to print the value later, you can always print it as value unit.
However, if you want to do some calculations with the value, for instance, calculate the area, you need to convert the values to the same units. So you have to define unit conversion table anyway.
I would convert the units to the same internal unit before I store them in the database, rather than converting them every time I use them.
I would add a model for units and physical quantities only if there are too many of them and conversion is really tricky. Such a model could work as a converter. But for simple cases, like mm⇒cm or inch⇒cm, a static conversion table would suffice.
By "field(enum)" do you mean you are using the choices option on a field?
A simple set of choices works out reasonably well for small lists of conversions. It allows you to make simplifying assumptions that helps your users (and you) get something that works.
Creating a formal model for units should only be done if you have (a) a LOT of units involved, (b) your need to extend it, AND (c) there's some rational expectation that the DB lookups will be of some value.
Units don't change all that often. There seems little reason to use the database for this. It seems a lot simpler to hard-code the list of choices.
Choices
You can, for example, use a something like this to keep track of conversions.
UNIT_CHOICES = ( ('m', 'meters'), ('f', 'feet' ), ('i', 'inches'), ('pt', 'points') )
unit_conversions = {
('m','f'): 3.xyz,
('m','i'): 39.xyz,
('m','pt'): 29.xyz*72,
('f','m'): 1/3.xyz,
('f','i'): 12.0,
('f','pt'): 12.0*72,
etc.
}
Given this mapping, you can get a conversion factor in your conversion method function, do the math, and return the converted unit.
class WithUnit( Model ):
...
def toUnit( self, someUnit ):
if someUnit == self.unit: return self.value
elif (someUnit,self.unit) in unit_conversions:
return self.value * unit_conversions[(someUnit,self.unit)]
else:
raise Exception( "Can't convert" )
Model.
If you want to create a formal model for units, you have to carry around the kind of dimension (length, volume, mass, weight/force, pressure, temperature, etc.) and the varous unit conversion factors. This works for everything but temperature, where you have a constant term in addition to a factor.
You have to pick a "baseline" set of units (e.g., MKS) and carry all the multipliers among the various units.
You also have to choose how many of the English units to load into your table (fluid ounces, teaspoons, tablespoons, cups, pints, quarts, etc.)
Use a field that indicates the type of measure (weight, length, etc.), and store the value in another field. That should be sufficient. The unit of measure should be implicit. I'm assuming you are using the same unit of measure for each measure type, for example always meters for length.
A concrete example: let's say you have two entities, "Car" and "CarMeasures". I'd write the model this way:
class Car(models.Model):
type=models.CharField(max_length=256);
class CarMeasures(models.Model):
carId=models.ForeignKey(Car);
measureValue=models.DecimalField(..., max_digits=10, decimal_places=2);
measureType=models.CharField(max_length=32);