0

I want to do a query on the django User table like this:

u = User.objects.filter(member__in = member_list)

where:

class Member(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    dob = models.DateField('Date of Birth', blank=True, null=True)

and member_list is a list of eligible members.

The query works fine but the problem is I do not actually know the model member is called member. It could be called anything.

I store the name of the model I want in a model called Category. I have a link to the name of the model through content_type.Category is defined as:

class Category(models.Model):
    name = models.CharField('Category', max_length=30)
    content_type = models.ForeignKey(ContentType)
    filter_condition = JSONField(default="{}", help_text=_(u"Django ORM compatible lookup kwargs which are used to get the list of objects."))
    user_link = models.CharField(_(u"Link to User table"), max_length=64, help_text=_(u"Name of the model field which links to the User table.  'No-link' means this is the User table."), default="No-link")

    def clean (self):
        if self.user_link == "No-link":
            if self.content_type.app_label == "auth" and self.content_type.model == "user":
                pass
            else:
                raise ValidationError(
                    _("Must specify the field that links to the user table.")
                    )
        else:
            if not hasattr(apps.get_model(self.content_type.app_label, self.content_type.model), self.user_link):
                raise ValidationError(
                    _("Must specify the field that links to the user table.")
                    )            

    def __unicode__(self):
        return self.name

    def _get_user_filter (self):
        return str(self.content_type.app_label)+'.'+str(self.content_type.model)+'.'+str(self.user_link)+'__in'

    def _get_filter(self):
        # simplejson likes to put unicode objects as dictionary keys
        # but keyword arguments must be str type
        fc = {}
        for k,v in self.filter_condition.iteritems():
            fc.update({str(k): v})
        return fc

    def object_list(self):
        return self.content_type.model_class()._default_manager.filter(**self._get_filter())

    def object_count(self):
        return self.object_list().count()

    class Meta:
        verbose_name = _("Category")
        verbose_name_plural = _("Categories")
        ordering = ('name',)

So I can retrieve the name of the model that links to User but I then need to convert it into a class which I can include in a query.

I can create an object x = category.content_type.model_class() which gives me <class 'cltc.models.Member'> but when I them perform a query s = User.objects.filter(x = c.category.object_list()) I get the error Cannot resolve keyword 'x' into field.

Any thoughts most welcome.

1 Answer 1

2

The left hand side of the filter argument is a keyword, not a python object, so x is treated as 'x', and Django expects a field called x.

To get around this, you can ensure that x is a string, and then use the python **kwarg syntax:

s = User.objects.filter(**{x: c.category.object_list()})

Thanks to https://stackoverflow.com/a/4720109/823020 for this.

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.