1 | #!/usr/bin/env bash
|
---|
2 | set -eu
|
---|
3 | python -m venv nested_prefetch
|
---|
4 | cd nested_prefetch
|
---|
5 | . bin/activate
|
---|
6 | pip install Django==2.0.4
|
---|
7 | django-admin startproject nested_prefetch
|
---|
8 | cd nested_prefetch
|
---|
9 | ./manage.py startapp a1
|
---|
10 | cat <<END >> nested_prefetch/settings.py
|
---|
11 | INSTALLED_APPS.append('a1')
|
---|
12 | END
|
---|
13 | cat >> a1/models.py <<END
|
---|
14 | class M1(models.Model):
|
---|
15 | name = models.CharField(max_length=255)
|
---|
16 |
|
---|
17 | class M3(models.Model):
|
---|
18 | name = models.CharField(max_length=255)
|
---|
19 | m1s = models.ManyToManyField(M1, through='M2', related_name='m3s', related_query_name='m3')
|
---|
20 |
|
---|
21 | class M2(models.Model):
|
---|
22 | m1 = models.ForeignKey(M1, related_name='m2s', related_query_name='m2',
|
---|
23 | on_delete=models.CASCADE)
|
---|
24 | m3 = models.ForeignKey(M3, related_name='m2s', related_query_name='m2',
|
---|
25 | on_delete=models.CASCADE)
|
---|
26 | name = models.CharField(max_length=255)
|
---|
27 |
|
---|
28 | class M4(models.Model):
|
---|
29 | name = models.CharField(max_length=255)
|
---|
30 | m3 = models.ForeignKey(M3, related_name='m4s', related_query_name='m4',
|
---|
31 | on_delete=models.CASCADE)
|
---|
32 | END
|
---|
33 | ./manage.py makemigrations
|
---|
34 | ./manage.py migrate
|
---|
35 | cat > 1.py <<END
|
---|
36 | import os, django
|
---|
37 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "nested_prefetch.settings")
|
---|
38 | django.setup()
|
---|
39 |
|
---|
40 | from django.db.models import Prefetch
|
---|
41 | from a1.models import M1, M2, M3, M4
|
---|
42 |
|
---|
43 | m11 = M1.objects.create(name='m11')
|
---|
44 | m31 = M3.objects.create(name='m31')
|
---|
45 | m21_11 = M2.objects.create(m1=m11, m3=m31, name='m21_11')
|
---|
46 | m32 = M3.objects.create(name='m32')
|
---|
47 | m22_12 = M2.objects.create(m1=m11, m3=m32, name='m22_12')
|
---|
48 | m411 = M4.objects.create(name='m411', m3=m31)
|
---|
49 | m412 = M4.objects.create(name='m412', m3=m31)
|
---|
50 | m421 = M4.objects.create(name='m421', m3=m32)
|
---|
51 | m422 = M4.objects.create(name='m422', m3=m32)
|
---|
52 |
|
---|
53 | from django.conf import settings
|
---|
54 | from django.utils.module_loading import import_string
|
---|
55 | logging_config_func = import_string(settings.LOGGING_CONFIG)
|
---|
56 | logging_config_func({
|
---|
57 | 'version': 1,
|
---|
58 | 'disable_existing_loggers': False,
|
---|
59 | 'formatters': {
|
---|
60 | 'django.server': {
|
---|
61 | '()': 'django.utils.log.ServerFormatter',
|
---|
62 | 'format': '[%(server_time)s] %(message)s',
|
---|
63 | }
|
---|
64 | },
|
---|
65 | 'handlers': {
|
---|
66 | 'console': {
|
---|
67 | 'level': 'DEBUG',
|
---|
68 | 'class': 'logging.StreamHandler',
|
---|
69 | },
|
---|
70 | },
|
---|
71 | 'loggers': {
|
---|
72 | 'django.db.backends': {
|
---|
73 | 'handlers': ['console'],
|
---|
74 | 'level': 'DEBUG',
|
---|
75 | 'propagate': False,
|
---|
76 | },
|
---|
77 | }
|
---|
78 | })
|
---|
79 |
|
---|
80 | m1s = M1.objects.all() \
|
---|
81 | .prefetch_related(
|
---|
82 | Prefetch('m2s', queryset=M2.objects.prefetch_related('m3__m4s'))
|
---|
83 | )
|
---|
84 |
|
---|
85 | # m1s = M1.objects.all() \
|
---|
86 | # .prefetch_related('m2s', 'm2s__m3__m4s')
|
---|
87 |
|
---|
88 | indent = ' '
|
---|
89 | for m1 in m1s:
|
---|
90 | print(m1.name)
|
---|
91 | for m2 in m1.m2s.all():
|
---|
92 | print('{}{} (through {})'.format(indent * 2, m2.m3.name, m2.name))
|
---|
93 | for m4 in m2.m3.m4s.all():
|
---|
94 | print('{}{}'.format(indent * 3, m4.name))
|
---|
95 | END
|
---|
96 |
|
---|
97 | echo Now run:
|
---|
98 | echo cd nested_prefetch/nested_prefetch
|
---|
99 | echo . ../bin/activate
|
---|
100 | echo ./manage.py migrate a1 zero \&\& ./manage.py migrate a1 \&\& python 1.py
|
---|