3

The main purpose of a model is to contain business logic, so I want most of my code inside Django model in the form of methods. For example I want to write a method named get_tasks_by_user() inside task model. So that I can access it as

Tasks.get_tasks_by_user(user_id)

Following is my model code:

class Tasks(models.Model):
    slug=models.URLField()
    user=models.ForeignKey(User)
    title=models.CharField(max_length=100)
    objects=SearchManager()
    def __unicode__(self):
        return self.title
    days_passed = property(getDaysPassed)
    def get_tasks_by_user(self,userid):
        return self.filters(user_id=userid)

But this doesn't seems to work, I have used it in view as:

    tasks = Tasks.objects.get_tasks_by_user(user_id)

But it gives following error:

'SearchManager' object has no attribute 'get_tasks_by_user'

If I remove objects=SearchManager, then just name of manager in error will change so I think that is not issue. Seems like I am doing some very basic level mistake, how can I do what I am trying to do? I know I can do same thing via :Tasks.objects.filters(user_id=userid) but I want to keep all such logic in model. What is the correct way to do so?

2 Answers 2

5

An easy way to do this is by using classmethod decorator to make it a class method. Inside class Tasks:

@classmethod
def get_tasks_by_user(cls, userid):
    return cls.objects.filters(user_id=userid)

This way you can simply call:

tasks = Tasks.get_tasks_by_user(user_id)

Alternatively, you can use managers per Tom's answer.

To decided on which one to choose in your specific case, you can refer James Bennett's (the release manager of Django) blog post on when to use managers/classmethod.

Sign up to request clarification or add additional context in comments.

1 Comment

A classmethod is a class method and not a static method which is completely different in python
4

Any methods on a model class will only be available to instances of that model, i.e. individual objects.

For your get_tasks_by_user function to be available as you want it (on the collection), it needs to be implemented on the model manager.

class TaskManager(models.Manager):
    def get_tasks_by_user(self, user_id):
        return super(TaskManager, self).get_query_set().filter(user=user_id)

class Task(models.Model):
    # ...
    objects = TaskManager()

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.