Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
django-auto-prefetch
Advanced tools
.. image:: https://img.shields.io/github/actions/workflow/status/tolomea/django-auto-prefetch/main.yml.svg?branch=main&style=for-the-badge :target: https://github.com/tolomea/django-auto-prefetch/actions?workflow=CI
.. image:: https://img.shields.io/badge/Coverage-100%25-success?style=for-the-badge :target: https://github.com/tolomea/django-auto-prefetch/actions?workflow=CI
.. image:: https://img.shields.io/pypi/v/django-auto-prefetch.svg?style=for-the-badge :target: https://pypi.org/project/django-auto-prefetch/
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge :target: https://github.com/python/black
.. image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=for-the-badge :target: https://github.com/pre-commit/pre-commit :alt: pre-commit
Automatically prefetch foreign key values as needed.
When accessing a ForeignKey
or OneToOneField
(including in reverse) on
a model instance, if the field’s value has not yet been loaded then
auto-prefetch will prefetch the field for all model instances loaded by
the same QuerySet
as the current model instance. This is enabled at the
model level and totally automatic and transparent for users of the
model.
Python 3.9 to 3.13 supported.
Django 4.2 to 5.1 supported.
Install with python -m pip install django-auto-prefetch
.
Change all these imports from django.db.models
to auto_prefetch
:
ForeignKey
Manager
Model
- including inheriting Meta
from auto_prefetch.Model.Meta
OneToOneField
QuerySet
If you use custom subclasses of any of these classes, you should be able to swap for the auto_prefetch
versions in your subclasses’ bases.
For example, if you had:
.. code:: python
from django.db import models
class Book(models.Model): author = models.ForeignKey("Author", on_delete=models.CASCADE)
class Meta:
verbose_name = "Book"
…swap to:
.. code:: python
import auto_prefetch from django.db import models
class Book(auto_prefetch.Model): author = auto_prefetch.ForeignKey("Author", on_delete=models.CASCADE)
class Meta(auto_prefetch.Model.Meta):
verbose_name = "Book"
Run python manage.py makemigrations
to generate migrations for all the models you modified.
These migrations will set the |Meta.base_manager_name option|__ to prefetch_manager
for every model that you’ve converted.
This change ensures that auto-prefetching happens on related managers.
Such migrations do not change anything in the database.
.. |Meta.base_manager_name option| replace:: Meta.base_manager_name
option
__ https://docs.djangoproject.com/en/stable/ref/models/options/#base-manager-name
(If you instead set Meta.base_manager_name
on your models, make sure it inherits from auto_prefetch.Manager
.)
Currently when accessing an uncached foreign key field, Django will automatically fetch the missing value from the database. When this occurs in a loop it creates 1+N query problems. Consider the following snippet:
.. code:: python
for choice in Choice.objects.all(): print(choice.question.question_text, ":", choice.choice_text)
This will do one query for the choices and then one query per choice to get that choice’s question.
This behavior can be avoided with correct application of
prefetch_related()
like this:
.. code:: python
for choice in Choice.objects.prefetch_related("question"): print(choice.question.question_text, ":", choice.choice_text)
This has several usability issues, notably:
prefetch_related()
(e.g. the
template) may be quite removed from where the prefetch_related()
needs to
be applied (e.g. the view).prefetch_related()
/ select_related()
calls are missing is non-trivial and needs to be done on an ongoing
basis.prefetch_related()
calls are even harder
to find and result in unnecessary database queries.prefetch_related()
clauses.On the first iteration of the loop in the example above, when we first
access a choice’s question field, instead of fetching the question for
just that choice, auto-prefetch will speculatively fetch the questions
for all the choices returned by the QuerySet
. This change results in
the first snippet having the same database behavior as the second while
reducing or eliminating all of the noted usability issues.
Some important points:
ManyToManyField
\s are not changed at all.ForeignKey
and OneToOneField
\s, the
generated queries can’t have more result rows than the original query
and may have less. This eliminates any concern about a multiplicative
query size explosion.prefetch_related()
and/or select_related()
calls.choice.question.author
.
The conditions above still hold under such chaining.An example of that last point is:
.. code:: python
qs = Choice.objects.all() list(qs)[0].question
Such examples generally seem to be rarer and more likely to be visible
during code inspection (vs {{ choice.question }}
in a template). And
larger queries are usually a better failure mode than producing hundreds
of queries. For this to actually produce inferior behavior in practice
you need to:
If any of those aren’t true then automatic prefetching will still produce equivalent or better database behavior than without.
If you have concerns go look at the code, it’s all in
auto_prefetch/__init__.py <https://github.com/tolomea/django-auto-prefetch/blob/main/src/auto_prefetch/__init__.py>
__
and is fairly short.
FAQs
Automatically prefetch foreign key values as needed.
We found that django-auto-prefetch demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.