views:

35

answers:

2

I have Django model that looks like this:

class Categories(models.Model):
    """
    Model for storing the categories
    """
    name = models.CharField(max_length=8)
    keywords = models.TextField()
    spamwords = models.TextField()
    translations = models.TextField()

    def __unicode__(self):
        return self.name

    class Meta:
        verbose_name = _('Category')
        verbose_name_plural = _('Categories')

The fields keywords, spamwords and translations contain huge chunks of comma-separated text. Could someone tell how I could write a function inside the model which for a particular fieldname, returns the value a list so that I could access it something like this:

cat = Categories.objects.get(id=1)
print cat.keywords.to_array()

...it returns the field data, split into an array. (The splitting bit is very simple and i know how to do that - string.split(',')

Thanks

+1  A: 

You can easily add an instance method to your Categories class like this:

class Categories(models.Model):
   ... rest of your definition ...

   def get_spamwords_as_list(self):
       return self.spamwords.split(',')

You could use it like this:

cat = Categories.objects.get(id=1)
print cat.get_spamwords_as_list()

But I'm curious about your underlying data model -- why aren't you using a ManyToManyField to model your categories?

UPDATE: Adding an alternative generic version:

def get_word_list(self, name):
    if name in ['keywords', 'spamwords', 'translations']:
        return getattr(self, name).split(',')

# or even
def __getattr__(self, name):
    if name[-5:] == '_list' and name[:-5] in ['keywords', 'spamwords', 'translations']:
        return getattr(self, name[:-5]).split(',')
    else
        raise AttributeError

cat = Categories.get(pk=1)
cat.get_word_list('keywords')  # ['word 1', 'word 2', ...]
cat.keywords_list              # ['word 1', 'word 2', ...] with 2nd approach
cat.keywords                   # 'word 1, word 2' -- remains CSV
Benj
Your method was the first one that popped into my head but I was wondering if it was possible to create a generic function for the fields instead of three different functions for the fields. If you're asking me as to why I'm storing the data as CSV - it's because the site administrators often copy-paste CSV data from local text files. This method seemed much easier than having to enter word individually. :)
Mridang Agarwalla
Got it -- didn't understand that you were looking for a generic function; i think yours is elegant. Depending on your needs, you could still accept CSV input, and write custom form widgets that accept CSV and translate it into M2M relationships -- but I'll trust that you know what you need for your implementation.
Benj
With your approach (overloading __getattribute__), how do you get the *unsplit* values, for example when editing in the django admin or in any other place where you want the CSV text? I guess you could do `", ".join(cat.keywords)` but that seems ...What about a generic def get_word_list(self, name): if name in ['keywords', 'spamwords', 'translations']: return getattr(self, name).split(',')?
Benj
You're right. I did run into this problem and decided to stick with your method. Thanks.
Mridang Agarwalla
A: 

I did it this way:

class Categories(models.Model):
    """
    Model for storing the categories
    """
    name = models.CharField(max_length=8)
    keywords = models.TextField()
    spamwords = models.TextField()
    translations = models.TextField()

    def __unicode__(self):
        return self.name

    def __getattribute__(self, name):
        if name not in ['keywords', 'spamwords', 'translations']:
            return object.__getattribute__(self, name)
        else:
            return object.__getattribute__(self, name).split(',')

    class Meta:
        verbose_name = _('Category')
        verbose_name_plural = _('Categories')
Mridang Agarwalla