Search code examples
djangomodelsrelationshipcurvemanytomanyfield

Storing a curve in a django model as manytomany?


I have a list of products (say diodoes) which have a curve associated to them. For example,

  • Diode 1: curve 1: [(0,1),(1,3),(2,10), ...., (100,0.5)]
  • Diode 2: curve 2: [(0,2),(1,4),(2.1,19), ..., (100,0)]

So for each product there is a curve (with the same x-axis values range(1,100)) but different y-axis values.

My question is what is the best practice to store such data (using Django + PostgreSql) given that I want to calculate things with it later in the views (say the area under the curve, or that curve times another one, etc). I will also be charting it, so the view will have to pull the values.

My first attempts have had various limitations:

  • Naive attempt 1

     # model.py
     for i in range(101):
         name_sects = ["x", str(i+1)]
         attrs["".join(name_sects)] = models.DecimalField(_("".join([str(i+1),' A'])), max_digits=6)
    
    
     attrs['intensity'] = model.DecimalField(_('Diode Intensity'))
    
    
     Diode = type('Diode', (models.Model,), attrs)
    

Ok, that creates a field for each "x", x1, x2,... etc, and I can fill each "y" in the admin ... but it's not obvious how to manipulate it in the view or the template. (and a pain to fill in, obviously)

  • Naive attempt 2

    #model.py
    class Curve(models.Model)
        x_axis = models.PositiveIntegerField( ...)
        y_axis = models.DecimalField( ...)
    
    class Diode(models.Model)
        name = blah, blah
        intensity = model.DecimalField(_('Diode Intensity'), blah, blah)
        characteristic_curve = model.ManyToManyField(Curve)
    

Is ManyToMany the way forward? Even if to each diode corresponds one single curve? (but many points, possibly two diodes sharing a same point).

Any advice, tips or links to tools for it are very appreciated.


Solution

  • If you want to improve speed (because 100 entries for each product, it's really huge and it would be slow if you have to fetch 100 products and theirs points), I would use the pickle module and store your list of tuples in a TextField (or maybe CharField if the length of the string doesn't change).

    >>> a = [(1,2),(3,4),(5,6),(7,8)]
    >>> pickle.dumps(a)
    '(lp0\n(I1\nI2\ntp1\na(I3\nI4\ntp2\na(I5\nI6\ntp3\na(I7\nI8\ntp4\na.'
    >>> b = pickle.dumps(a)
    >>> pickle.loads(b)
    [(1, 2), (3, 4), (5, 6), (7, 8)]
    

    Just store b in your TextField and you can get back your list really easily.

    And even better, as Robert Smith says, use http://pypi.python.org/pypi/django-picklefield