0

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

2 Answers 2

1

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
Sign up to request clarification or add additional context in comments.

4 Comments

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. :)
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.
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(',') ?
You're right. I did run into this problem and decided to stick with your method. Thanks.
0

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')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.