bozdoz
bozdoz

Reputation: 12860

How to access Django method in a view

I have a model in Django with a method that I can't seem to access in the view. Here is the model:

class Realtor(models.Model):
    user = models.OneToOneField(User)
    team = models.ForeignKey(RealtorTeam, blank=True, null=True, default=None)
    is_showing_realtor = models.BooleanField(default=False)
    is_listing_realtor = models.BooleanField(default=False)

    def type(self):
        if self.is_showing_realtor and self.is_listing_realtor:
            return 'Showing and Listing'
        elif self.is_showing_realtor:
            return 'Showing'
        elif self.is_listing_realtor:
            return 'Listing'
        else:
            return ''

Now, in the view, I try to query the model, including the method, like this:

q = Realtor.objects.all()
q = q.filter(user__first_name__icontains=first)
q = q.filter(user__last_name__icontains=last)
q = q.filter(team__name__icontains=team)
q = q.filter(user__email__icontains=email)
q = q.filter(type__icontains=type)

The error I get is Cannot resolve keyword 'type' into field. Choices are.... I looked up a number of stackoverflow questions, and read through more of the Django docs, and I saw to add a field like this in the model:

type_display = (type,)

But that didn't work. Do I have to query the is_showing_realtor and is_listing_realtor? Is there no way to query the method?

More info

We are using Django_tables2 to display tables of models. We are able to access the type method with that, like this:

class RealtorTable(tables.Table):
    id = tables.Column()
    first_name = tables.Column(accessor='user.first_name', order_by='user.first_name')
    last_name = tables.Column(accessor='user.last_name', order_by='user.last_name')
    team = tables.Column()
    email = tables.Column(accessor='user.email', order_by='user.email')
    type = tables.Column(order_by='is_showing_realtor')

But still, can't pass it to the view.

Upvotes: 1

Views: 187

Answers (2)

reptilicus
reptilicus

Reputation: 10397

I'm no Django expert, but I'm pretty sure that you can't query on model attributes that aren't columns in the database, which is what you are trying to do. Perhaps try to decorate the method with @property to make it like an attribute.

You could just do a list comprehension if like

results = [m for m in query_set if m.type = "Showing and listing"]

Upvotes: 1

danodonovan
danodonovan

Reputation: 20341

type is the name of a built-in function python, and so also in django. I'd recommend renaming your function to something like listing_type to avoid any clashes.

In particular, this line

type_display = (type,)

probably isn't doing what you think it is.

reptilicus is correct, I'd not spotted the filter on a non-field attribute, that doesn't make sense. You could turn listing_type into a CharField with choices= set, and then some custom save() logic to set it when the model is changed - or you could use property

@def listing_type():
    doc = "The listing_type property."
    def fget(self):
        if self.is_showing_realtor and self.is_listing_realtor:
            return 'Showing and Listing'
        elif self.is_showing_realtor:
            return 'Showing'
        elif self.is_listing_realtor:
            return 'Listing'
        else:
            return ''
    def fset(self, value):
        self._listing_type = value
    def fdel(self):
        del self._listing_type
    return locals()
listing_type = property(**listing_type())

PS I still don't like type :-)

Upvotes: 2

Related Questions