1

I have this model

class Home(models.Model):
  ...
  number_female = models.IntegerField()
  number_male = models.IntegerField()
  def all_people(self):
     return self.number_female + self.number_male
  all_members = all_people(self)

i am getting: name 'self' is not defined.

how can I define a field which gets the result of models method? this Home scenario is just an example, i have more complex models, i just wanted to make question clearer.

doniyor
  • 36,596
  • 57
  • 175
  • 260
  • 2
    You want to save the field in table? If not make the method as property. – Rohan Jun 11 '14 at 06:35
  • @Rohan, i dont really want to save the field, i am doing this because i cannot filter by model method. if i make the method a property, then can i filter by this method too? – doniyor Jun 11 '14 at 06:36
  • Why not to do just return number_female + number_male ?? – juankysmith Jun 11 '14 at 06:46
  • @doniyor, I don't think you will be able filter with property. Moreover, I don't think you can filter on non saved field. – Rohan Jun 11 '14 at 06:49
  • @Rohan yeah thats why i want to save the field before i filter. – doniyor Jun 11 '14 at 07:12

3 Answers3

1

If you would like to add a calculated field like all_members as a part of your model, then you will have to override the save function:

class Home(models.Model):
    ...
    all_members = models.IntegerField()

    def save(self):
        all_members = self.all_people()
        super(Home, self).save()

Now you can filter by all_members. It would be better to use the @property decorator for all_members, in this case.

Another approach would be to use Django's extra method as mentioned in a different stackoverflow answer

Community
  • 1
  • 1
arocks
  • 2,862
  • 1
  • 12
  • 20
  • 1
    When you add a `Person` to a `Home`, it's not going to update your `all_members` field (unless explicitly told to via a signal) which doesn't feel like very robust design to me. – ptr Jun 11 '14 at 07:25
  • @PeteTinkler but what if i resave the home after new person came in? – doniyor Jun 11 '14 at 14:31
1

You still need to define all_members as a model field (not as an integer), and then populate it with the desired value when you save() the instance.

class Home(models.Model):
  ...
  number_female = models.IntegerField()
  number_male = models.IntegerField()
  all_members = models.IntegerField()


  def save(self):
     self.all_members = self.number_female + self.number_male
     super(Home, self).save()
desired login
  • 1,138
  • 8
  • 15
0

I think Django Managers can be a solution here. Example:

Custom Manager:

class CustomFilter(models.Manager):
      def all_people(self):
           return self.number_female + self.number_male

Model:

 class Home(models.Model):
     ....
     objects= CustomFilter()

Views:

allpeople= Home.objects.all_people(Home.objects.all())
ruddra
  • 50,746
  • 7
  • 78
  • 101
  • ``objects.all_people`` returns only number of all people, right? and this for each object of home, right? (i didnot dv, i uvoted) – doniyor Jun 11 '14 at 10:36
  • `objects.all()` returns a queryset which contains all objects of `Home`. :) – ruddra Jun 11 '14 at 10:53
  • I have suggested this way because in comments on the question, you said about filtering with model method. Using django managers, you can filter results using the method you design in Managers. – ruddra Jun 11 '14 at 11:01