0

I want to create a mixin that allows me to change the field of a get function as follows:

class MyMixin(self):

    myfield = 'field1' 

    def myfunct(self):

        i = MyModel.objects.get(self.myfield=myvar)

Such that the desired code runs MyModel.objects.get(field1=myvar).

However, this approach returns

SyntaxError: expression cannot contain assignment

How can I set field names like this dynamically?

alias51
  • 8,178
  • 22
  • 94
  • 166
  • Possible Duplicate [In Django, how does one filter a QuerySet with dynamic field lookups?](https://stackoverflow.com/questions/310732/in-django-how-does-one-filter-a-queryset-with-dynamic-field-lookups) – GiftZwergrapper Feb 12 '20 at 11:56

3 Answers3

4

You could do it like this:

kwargs = {self.myfield: myvar}
MyModel.objects.get(**kwargs)
wfehr
  • 2,185
  • 10
  • 21
1

You can pass a 2-tuple to a Q object [Django-doc] with a key and a value:

from django.db.models import Q

MyModel.objects.get(Q((self.myfield, myvar)))

For example, we can generate a query for the .filter(..):

>>> print(MyModel.objects.filter(Q(('id', 1))).query)
SELECT `test_mymodel`.`id` FROM `test_mymodel` WHERE `test_mymodel`.`id` = 1

In fact, if you take a look at how Django processes the positional and named parameters of the .get(..) and .filter(..), it makes a Q object [GitHub]:

        …
        clone = self._chain()
        if negate:
            clone.query.add_q(~Q(*args, **kwargs))
        else:
            clone.query.add_q(Q(*args, **kwargs))
        return clone

and the named parameters are converted to (sorted) 2-tuples:

class Q(tree.Node):
    # …

    def __init__(self, *args, _connector=None, _negated=False, **kwargs):
        super().__init__(children=[*args, *sorted(kwargs.items())], connector=_connector, negated=_negated)

so by using a 2-tuple in a Q object, we make a "shortcut" so to speak.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
0
lookup_kwargs = {'{0}'.format('id'): 1}
People.objects.get(**lookup_kwargs)

N.B: Your dynamic lookup field must exit in the following model. Otherwise, you will get an error, like (django.core.exceptions.FieldError......).

In the same way, you can filter single or multiple fields based on your expectations

lookup_kwargs = {'{0}'.format('id'): 1}
People.objects.filter(**lookup_kwargs)