On 31 déc, 05:40, schwim <gsch...@gmail.com> wrote:
> I'm trying to build a model that will store the counts of each of 10
> possible choices, e.g.:
>
>     v1 = models.IntegerField(default=0)
>     v2 = models.IntegerField(default=0)
>     v3 = models.IntegerField(default=0)
>     ...
>     v10 = models.IntegerField(default=0)
>
> I'd prefer to represent this as an array

Where ?

> rather than 10 separate
> fields.  I looked at the CommaSeparatedIntegerField as an alternative,
> but I want to explicitly state that there are 10 entries available per
> instance.

Note that at the Python level, a list (I suppose that's what you mean
by 'array') is not fixed-length.

At the relational (SQL) level, you could use a joined table storing
values (yourmodel_id, numchoice, value) with yourmodel_id + numchoice
as primary key (or, given Django's ORM limitation, using a unique
(yourmodel_id, numchoice) constraint), but you'll have to add your own
validation stuff (both at the database level and Django code level) to
make sure numchoice is between 1 and 10. Now weither this is the right
thing to do depends on the probabilities that you will want more than
10 "values" anytime soon. if this requirement is really stable, your
current solution is ok to me (purist DBAs would probably run away
screaming, but that's another problem).

If all you want is a way to access the values as a sequence (read-
only) from your python/templates code, it's just a matter of adding a
simple property:


class YourModel(models.Model):
    # you code here
    @property
    def values(self):
        return [getattr(self, "v%s" % i) for i in range(1,11)]


then:

m = YourModel.objects.get(...)
m.values
m.values[0]
m.values[9]


If you want a reliable read-write property, this becomes a bit more
involved. You have to write a custom descriptor returning a custom
sequence type that retains a reference on the model instance.

The following code should get you started - warning: it's Q&D, full of
magic numbers, not generic, not factorized, and not even tested.
IOW : it's by no mean production code.

class MySequence(object):
    def __init__(self, model):
        self._model = model

    def _as_fieldname(self, index):
        # sequences are zero-based
        # XXX : magic number
        if not 0 <= index <= 9:
            raise IndexError
        # your fields are 1-based
        # XXX duplicated in MySequenceDescriptor
        return "v%s" % (index+1)

    def __getitem__(self, index):
        fname = self._as_fieldname(index)
        return getattr(self._model, fname)

    def __setitem__(self, index, value):
        fname = self._as_fieldname(index)
        setattr(self._model, fname, value)

    # you may need some other sequence __magicmethods__ here
    # check the Python's manual about emulating sequence types


class MySequenceDescriptor(object):
    def __get__(self, instance, cls):
        if instance is None:
            # looked up in the class
            return self
        # looked up on a model instance:
        return MySequence(instance)

    def __set__(self, instance, value):
        # expects a sequence of len(10)
        # XXX : magic number
        if len(value) != 10:
            raise ValueError("yadda yadda")
        for index, val in enumerate(value):
            # XXX duplication of  MySequence._as_fieldname
            setattr(instance, "v%s" % (index+1), val)


class YourModel(models.Model):
    # your code here

    values = MySequenceDescriptor()

HTH

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to