1

I'm new to Django and trying to understand how to use querysets with models.

Model
class Channel(models.Model):
    name = models.CharField(max_length=200)
    accountid = models.CharField(max_length=34)

    def get_channel_list(self):
        return self.get_queryset().name()

What I want to do is return the entire name column as an array if account id matches. I'd like to use a function in the models.py but I haven't found an online sample that caters to what I'm looking for.

The above isn't returning any data even without a filter.

Any point in the right direction would be amazing.

Andrew
  • 4,443
  • 5
  • 33
  • 75

3 Answers3

4

Use objects.filter and classmethod:

class Channel(models.Model):
    name = models.CharField(max_length=200)
    accountid = models.CharField(max_length=34)

    @classmethod
    def get_channel_list(cls, acc):
        return cls.objects.filter(accountid=acc).values_list('name', flat=True)

There is another technique to do such things in django - define custom manager to model. (for example, you have several Channel models inherited from one base proxy model and you want to put same get_channel_list functions to some models - custom Manager is the way to go):

class ChannelManager(models.Manager):
    def get_channel_list(self, acc):
        return self.filter(accountid=acc).values_list('name', flat=True)

class Channel(models.Model):
    name = models.CharField(max_length=200)
    accountid = models.CharField(max_length=34)

    objects = ChannelManager()
ndpu
  • 22,225
  • 6
  • 54
  • 69
  • 1
    You could also use `self.objects.filter(accountid=self.accountid)`, since you're calling this as an instance method. If you don't do that, it might be purer design to declare the above as a class method. – Peter DeGlopper Dec 24 '13 at 20:22
  • How would I call this in a view? like I said, very new to Django. :\ – Andrew Dec 24 '13 at 20:24
  • Neither of these will work, as you can't access `objects`from an instance. – Daniel Roseman Dec 24 '13 at 20:25
  • I think that he is looking for a static method, but of course +1 for an exact answer and for flat=True – pkacprzak Dec 24 '13 at 20:26
  • I'm looking for it to be dynamic depending on whos logged in – Andrew Dec 24 '13 at 20:28
  • @AndrewWilson just call Channel.get_channel_list(ACCOUNTID_YOU_NEED) and list with names will returned – ndpu Dec 24 '13 at 20:30
  • You sir are the man, this works perfectly for what I need and I can expand off of this. – Andrew Dec 24 '13 at 20:33
  • @ndpu I'm having troubles sorting by asc i'm using `return cls.objects.filter(accountid=account).order_by('-name').values_list('name', 'channelid')` It's listing them in this order "TEST", "B TEST", "A TEST CHANNEL", "A TEST CHANNEL", "A TEST 2", "A B TEST", "TEST CHANNEL", "TEST 3", "TEST 3", "TEST 2 CHANNEL"... Any thoughts? – Andrew Dec 25 '13 at 00:07
  • figured out it's because it's case sensitive, hmmph. still stumped – Andrew Dec 25 '13 at 01:29
  • Since it's really a new question, I posted it's own question for it http://stackoverflow.com/questions/20768955/django-query-sort-case-insensitive-using-model-method-with-postgresql – Andrew Dec 25 '13 at 04:07
2

You have failed to understand the difference between managers and models. It's the manager that it's responsible for creating queries, and which has the get_queryset method. From a model, you need to access the manager, which is usually named objects. Note, you cannot do that from an instance, so this needs to be a classmethod.

@classmethod
def get_channel_list(cls, accountid):
    return cls.objects.filter(accountid=accountid).values_list('name')
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
0

I needed to access the queryset/manager for a different reason, since google brought me here - this ended up my solution:

class Channel(models.Model):
    name = models.CharField(max_length=200)
    accountid = models.CharField(max_length=34)

    def get_channel_list(cls, acc):
        return self.__class__.objects.filter(accountid=acc).values_list('name', flat=True)
S.D.
  • 2,486
  • 1
  • 16
  • 23