Alternatives to using __contains?

140 views
Skip to first unread message

megaman

unread,
Oct 9, 2018, 11:58:03 AM10/9/18
to Django users
I’m pretty new to Django. I have just learnt that could filter a query set this way:

Questions.objects.filter(question_text__contains=‘what’)

This kind of scares me a little because the filter “contains” is actually part of the field name. And I guess there are other operators appended to a field with the same __operation pattern.

Wouldn’t this make refactoring tricky? Even renaming the field name has to be done carefully. In my mind, this feels messy.

Is there an alternative to doing this? Something like:
Questions.objects.filter(question_text.contains=‘what’)
Or using “contains” as a function?

Basically, can I do the same thing without adding “magic strings” to field names?

Matthew Pava

unread,
Oct 9, 2018, 12:08:10 PM10/9/18
to django...@googlegroups.com
No.
Usually, you would try to keep all of your filtering in the managers module, and then you would be able to limit your refactoring of filters in that file.
You could try using *args and **kwargs syntax, but that would make it difficult to maintain.
I suppose you could functions in SQLAlchemy, and if you really wanted functions in Django, you could make them yourself.

I actually like the Django syntax. It's very easy to follow. You can also use the __ for related fields.
Questions.objects.filter(something__related_something__related_something_else__lower__contains="what")
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/3f7194e9-b600-4a14-be1e-83f0cb35dac6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Michal Petrucha

unread,
Oct 10, 2018, 4:49:52 AM10/10/18
to django...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Hi,

On Tue, Oct 09, 2018 at 08:03:27AM -0700, megaman wrote:
> I’m pretty new to Django. I have just learnt that could filter a
> query set this way:
>
> Questions.objects.filter(question_text__contains=‘what’)
>
> This kind of scares me a little because the filter “contains” is
> actually part of the field name. And I guess there are other
> operators appended to a field with the same __operation pattern.
>
> Wouldn’t this make refactoring tricky? Even renaming the field name
> has to be done carefully. In my mind, this feels messy.
>
> Is there an alternative to doing this? Something like:
> Questions.objects.filter(question_text.contains=‘what’)
> Or using “contains” as a function?

The syntax that you suggested here, unfortunately, is not valid
Python. In an argument list, you can use either positional arguments,
which are either Python expressions, or keyword arguments, but those
require a valid Python identifier to be on the left side, which
“question_text.contains” is not.

> Basically, can I do the same thing without adding “magic strings” to
> field names?

Not at the moment, sorry.

The idea of using a style more similar to SQLAlchemy has been floated
on the dev mailing list in the past (as in, years ago), but I cannot
even find the right thread at the moment, and I'm not aware of any
recent developments in this direction.

All in all, chaining relationships, expressions, and filters with __
in keyword arguments is how this is done in Django, and it's most
likely going to stay that way for the foreseeable future.

Michal
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBCgAGBQJbvb0CAAoJEHA7T/IPM/klndQP/Rd91q/4ANlPzkIzzJd3xRuX
xrJgvFnWNnv9tZdQK1kwaoQPRG2Msx9taahg2NPvVMQUNKbsMKW60dctmtUMpXVC
MXrWscLEwXecV94Zp10x9JFPJCMLjNvDELvWjkLIMz7/j/Ih4h5FnzfHTiwlg4DK
2XkGiuBaXVM+TKST8RI1w7YphvcjfdehQzy1wRx8wS5FoqgrBjxJ4FJJojDYeo5s
MO0kfPLzPHg4QIU6eYwg2euSmACUorkrXVj0q1Qr8b5AsAkVCPVIM7ryapGrorp4
6EZ+97FMwemoCAtkWzL6jSvnnp87Mm/587BzxRTOJ0ff2pkUv5wjizTmED5/Hur9
fmjz4CpuVx2wHsvt0ty4gNyQ693h2J1kRZxenP0iFAnzipRPy/Lll46uxB3MhX5P
uHjM+gqk6RvHfFh4H/jBe2mh2WSEKtpCPG5kRp3v/cw6qgV16CeQDk60u8Vlymqk
SXj0FGj9W/HGytVt11+tGKX0fPcnDyy4GF5CIRBVTfviq/yz+GZQcO1Dd2VoAaMc
fAwLpKsPNQrTnJBZXPSby/bgYTYljyIBl6YOe9heL4yCocQVEO6zQRmZ81hCzB4H
9DoMiW6Y7oILcm7L/DC8DY/if2aLyxSN4Rnl05yPZnAmiatIMxssW5rWrz4+7YiS
iH62Ro8wxl48vrSxC7Hu
=gsXH
-----END PGP SIGNATURE-----

megaman

unread,
Oct 10, 2018, 6:06:20 AM10/10/18
to Django users
You mentioned SQLAlchemy. Does SQLAlchemy use actual functions/methods over magic strings to perform the operations?

If so, are we even able to swap out the Django ORM and use SQLAlchemy?

megaman

unread,
Oct 10, 2018, 6:09:08 AM10/10/18
to Django users
That's interesting because I would have thought it's much better to chain through functions like in Javascript or in other functional paradigms. 
Chaining using the variable name feels "fragile" to me, like I may break things at any time without knowing.

Maybe I will just have to get used to how Python and Django work. I'm still very new to both of these. :P

Michal Petrucha

unread,
Oct 10, 2018, 10:19:34 AM10/10/18
to django...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

On Wed, Oct 10, 2018 at 03:06:20AM -0700, megaman wrote:
> You mentioned SQLAlchemy. Does SQLAlchemy use actual functions/methods over
> magic strings to perform the operations?

SQLAlchemy uses operator overloading and function calls in Python to
write SQL expressions, yes. If you're interested in details, you can
look at the docs:
https://docs.sqlalchemy.org/en/latest/orm/query.html#sqlalchemy.orm.query.Query.filter

> If so, are we even able to swap out the Django ORM and use SQLAlchemy?

Of course, you could decide to not use Django's ORM, and instead use
SQLAlchemy, but if you do that, you also lose Django's migrations,
model forms, almost all of django.contrib, all the neat test isolation
features in django.test, and that's just the things that I can name
off the top of my head. I don't think it's a trade-off worth doing if
your only reason is that you don't like the kwargs-based API of
relationships, expressions, and filters.

Michal
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBCgAGBQJbvgpYAAoJEHA7T/IPM/klaZkP+wTJ+l3p+DPN/KJPAabMKf95
llom243U4TJ1DhWjr/Ca6PrkseCU7ZKN6EY/oCXIy6fGLNHNsRm31HOA5MpHn0PP
2CwcylVr7Gkss7Pt1sz0ighzHSeB48rlKSoqA2YjYF6krP2UV/JtX1ubDmnw8L3q
HFEhE5tvl93uZPVUnGlsmIcfd2RWupTeZGiBdfvFNeQX04tUYbsfN9YpZy6OpnHC
Fq8yZRSiRnxRARNQjB3YqKCn5Vkcj4xx2fFhe82aeVzhXFblK76QxgPRCEV6fl5t
s0FORX3AggxApYmACTN4I3rC7XAHdayM9/BuMesP2eLQurAmXvx4UyPnpAbh8nRn
La0oZQcXjGzlb2qzxeBU575Zy869rvZmcVahXEyETYXkPSfjgoIMOVG+xNQoZ2oJ
XIhIQyxuCMUR/0UYwibNU+1XygmDLIGZl2dUEkau4yRTUJnr0PC8uXX/Kxmd7KBo
68YdqyOB9spYCyQOWMgUpPGXV33nTFqX2V/b2QsFMUc4QhK5AMNIPkDCYoMxd4vS
CJd6jaA++u4kpzurlclSqP4/anTGtF/YSJ1IMEcK+/JGL/GezkM8h3jFS5DnTzOz
BgpwHeAjFWteACZ8xuJmWpOJxEtbkrzJUE1HEp0jERE1WyJQfNN3M+KSodJwbIJk
QV+X8TdvkIvmUx6wkPFU
=GVrx
-----END PGP SIGNATURE-----
Reply all
Reply to author
Forward
0 new messages