The motivation is for use with the QuerySet method
[https://docs.djangoproject.com/en/dev/ref/models/querysets/#only
`only()`], for example. (The `only()` method is used to prevent
unnecessary fields from being loaded from a database when querying.)
Consider the case of using `only()` to retrieve a list of many model
objects, and then subsequently displaying them. If one executes some
Django code after obtaining this list (e.g. by looping through the list of
objects), it would be bad if this later code accidentally accessed some
other field on each object. This could trigger the unintentional execution
of many individual database queries (e.g. on a production database), with
potentially bad consequences. I don't currently know an easy way to
prevent this.
It would be good to have such a way. For example, Django could provide
some sort of `noQuery()` context manager which would raise an exception if
the database were queried inside it. Code after the `only()` line could
be included in such a context manager. This could prevent accidentally
hammering a database.
Alternatively, the QuerySet API could expose a way to return objects with
some sort of `no_query` flag set. If attribute access on such a model
object required a database query, objects with such a flag set could
instead raise an exception. This would also suffice to prevent accidental
queries.
--
Ticket URL: <https://code.djangoproject.com/ticket/22492>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* cc: chris.jerdonek@… (added)
* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0
--
Ticket URL: <https://code.djangoproject.com/ticket/22492#comment:1>
* version: 1.6 => master
* stage: Unreviewed => Accepted
Comment:
Seems like an interesting idea to at least explore.
--
Ticket URL: <https://code.djangoproject.com/ticket/22492#comment:2>
* cc: raulcumplido@… (added)
* status: new => assigned
* owner: nobody => raulcd
--
Ticket URL: <https://code.djangoproject.com/ticket/22492#comment:3>
Comment (by raulcd):
Is something like this a possible solution. I am thinking on the API, or
do we prefer a solution where we have a context manager?
{{{
In [1]: from polls.models import Choice
In [2]: p = Choice.objects.defer('body_yes', 'id')
In [3]: choice = p[0]
In [4]: choice.no_query_deferred = True
In [5]: choice.body_yes
Traceback (most recent call last):
File "<....>", line xxx, in <module>
QueryException: no_query flag is set to True and a query has been
attempted.
In [6]: choice.no_query_deferred = False
In [7]: choice.body_yes
Out[7]: u'yes'
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/22492#comment:4>
Comment (by Simon Charette):
FWIW a third party application implements such queryset sealing
capabilities.
{{{#!python
In [1]: from polls.models import Choice
In [2]: p = Choice.objects.defer('body_yes').seal()
In [3]: choice = p[0]
In [4]: choice.body_yes
Traceback (most recent call last):
File "<....>", line xxx, in <module>
UnsealedAttributeAccess:: Attempt to fetch deferred field "body_yes" on
sealed <Choice instance>.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/22492#comment:5>
Comment (by Simon Charette):
#30874 was a duplicate.
--
Ticket URL: <https://code.djangoproject.com/ticket/22492#comment:6>
Comment (by Carlton Gibson):
#26481 was also a duplicate.
--
Ticket URL: <https://code.djangoproject.com/ticket/22492#comment:7>
* cc: Cesar Canassa (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/22492#comment:8>
* cc: Hannes Ljungberg (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/22492#comment:9>
Comment (by Andrea F):
I want a feature that is similar to what was original described but for a
different use case: I have a Celery task that needs a model object in the
state it was when the task was enqueued, ''not'' in a state reflecting the
corresponding database row(s) when the task is processed. I pass the
object to the Celery task by serializing the entity (using
`django.serializers`) and saving exactly the information I want to make
available to the task.
This object model has complex inner workings and multiple foreign keys. I
want to be able to use the object model functionality and custom logic we
have implemented in the model class, but I do _not_ want it reading (or
writing) anything from the database after deserialization in the Celery
task.
For this I want something less "smart" than a feature that knows about
`only` and `defer` and `QuerySet` objects. For this I want to be able to
set a flag on an object that would disable any further database
interactions originating from that object.
--
Ticket URL: <https://code.djangoproject.com/ticket/22492#comment:10>