|
1 |
+ |
# Generated by Django 2.2.11 on 2020-12-08 14:53 |
|
2 |
+ |
|
|
3 |
+ |
from django.db import migrations |
|
4 |
+ |
from django.contrib.admin.models import ADDITION |
|
5 |
+ |
from django.conf import settings |
|
6 |
+ |
|
|
7 |
+ |
|
|
8 |
+ |
def add_missing_footnotes(apps, schema_editor): |
|
9 |
+ |
''' |
|
10 |
+ |
Add footnotes to document source for events without footnotes. |
|
11 |
+ |
Events should be associated with one of two address books based on |
|
12 |
+ |
P36ADD and 36ADD tags in the event notes; all other events without |
|
13 |
+ |
footnotes are from the logbooks. |
|
14 |
+ |
''' |
|
15 |
+ |
Bibliography = apps.get_model('footnotes', 'Bibliography') |
|
16 |
+ |
Footnote = apps.get_model('footnotes', 'Footnote') |
|
17 |
+ |
Event = apps.get_model('accounts', 'Event') |
|
18 |
+ |
ContentType = apps.get_model('contenttypes', 'ContentType') |
|
19 |
+ |
User = apps.get_model('auth', 'User') |
|
20 |
+ |
LogEntry = apps.get_model('admin', 'LogEntry') |
|
21 |
+ |
|
|
22 |
+ |
event_content_type = ContentType.objects \ |
|
23 |
+ |
.get(model='event', app_label='accounts') |
|
24 |
+ |
footnote_content_type = ContentType.objects \ |
|
25 |
+ |
.get(model='footnote', app_label='footnotes') |
|
26 |
+ |
script_user = User.objects.get(username=settings.SCRIPT_USERNAME) |
|
27 |
+ |
|
|
28 |
+ |
# get bibliographic entries to be used as sources for footnotes |
|
29 |
+ |
# (but handle case where they don't exist, in a new db) |
|
30 |
+ |
addressbook_1936 = Bibliography.objects \ |
|
31 |
+ |
.filter(bibliographic_note__contains="Address Book 1919–1935", |
|
32 |
+ |
source_type__name='Address Book').first() |
|
33 |
+ |
addressbook_post1936 = Bibliography.objects \ |
|
34 |
+ |
.filter(bibliographic_note__contains="Address Book 1935–1937", |
|
35 |
+ |
source_type__name='Address Book').first() |
|
36 |
+ |
logbooks = Bibliography.objects \ |
|
37 |
+ |
.filter(bibliographic_note__contains="Logbooks 1919–1941", |
|
38 |
+ |
source_type__name='Logbook').first() |
|
39 |
+ |
|
|
40 |
+ |
# because footnote is a generic relation, it can't be used in a |
|
41 |
+ |
# queryset filter in a migration; instead, get a list event ids |
|
42 |
+ |
# with footnotes, so we can exclude them |
|
43 |
+ |
events_with_footnotes = Footnote.objects \ |
|
44 |
+ |
.filter(content_type=event_content_type) \ |
|
45 |
+ |
.values_list('object_id') |
|
46 |
+ |
|
|
47 |
+ |
if addressbook_post1936: |
|
48 |
+ |
# find all events with tag P36ADD and no footnote |
|
49 |
+ |
events_post36add = Event.objects.filter(notes__contains='P36ADD') \ |
|
50 |
+ |
.exclude(pk__in=events_with_footnotes) |
|
51 |
+ |
# for each event: create footnote, then create log entry for the footnote |
|
52 |
+ |
# NOTE: not using bulk create because the objects it returns don't have pks |
|
53 |
+ |
for event in events_post36add: |
|
54 |
+ |
footnote = Footnote.objects.create( |
|
55 |
+ |
bibliography=addressbook_post1936, |
|
56 |
+ |
content_type=event_content_type, |
|
57 |
+ |
object_id=event.pk) |
|
58 |
+ |
LogEntry.objects.create( |
|
59 |
+ |
user_id=script_user.id, |
|
60 |
+ |
content_type_id=footnote_content_type.pk, |
|
61 |
+ |
object_id=footnote.pk, |
|
62 |
+ |
object_repr='Footnote on event %s for %s' % |
|
63 |
+ |
(event.pk, addressbook_post1936.bibliographic_note), |
|
64 |
+ |
change_message='Address book footnote created based on P36ADD tag', |
|
65 |
+ |
action_flag=ADDITION) |
|
66 |
+ |
|
|
67 |
+ |
if addressbook_1936: |
|
68 |
+ |
# find events from the 1936 address book; exclude events from |
|
69 |
+ |
# post-1936 address book or tha talready have |
|
70 |
+ |
events_36add = Event.objects.filter(notes__contains='36ADD') \ |
|
71 |
+ |
.exclude(notes__contains='P36ADD') \ |
|
72 |
+ |
.exclude(pk__in=events_with_footnotes) |
|
73 |
+ |
# for each event: create footnote, then create log entry for the footnote |
|
74 |
+ |
for event in events_36add: |
|
75 |
+ |
footnote = Footnote.objects.create( |
|
76 |
+ |
bibliography=addressbook_1936, |
|
77 |
+ |
content_type=event_content_type, |
|
78 |
+ |
object_id=event.pk) |
|
79 |
+ |
LogEntry.objects.create( |
|
80 |
+ |
user_id=script_user.id, |
|
81 |
+ |
content_type_id=footnote_content_type.pk, |
|
82 |
+ |
object_id=footnote.pk, |
|
83 |
+ |
object_repr='Footnote on event %s for %s' % |
|
84 |
+ |
(event.pk, addressbook_1936.bibliographic_note), |
|
85 |
+ |
change_message='Address book footnote created based on 36ADD tag', |
|
86 |
+ |
action_flag=ADDITION) |
|
87 |
+ |
|
|
88 |
+ |
if logbooks: |
|
89 |
+ |
# find all remaining events without footnotes — from the logbooks |
|
90 |
+ |
logbooks_events = Event.objects.exclude(notes__contains='36ADD') \ |
|
91 |
+ |
.exclude(pk__in=events_with_footnotes) |
|
92 |
+ |
for event in logbooks_events: |
|
93 |
+ |
footnote = Footnote.objects.create( |
|
94 |
+ |
bibliography=logbooks, |
|
95 |
+ |
content_type=event_content_type, |
|
96 |
+ |
object_id=event.pk) |
|
97 |
+ |
LogEntry.objects.create( |
|
98 |
+ |
user_id=script_user.id, |
|
99 |
+ |
content_type_id=footnote_content_type.pk, |
|
100 |
+ |
object_id=footnote.pk, |
|
101 |
+ |
object_repr='Footnote on event %s for %s' % |
|
102 |
+ |
(event.pk, logbooks.bibliographic_note), |
|
103 |
+ |
change_message='Associated with logbooks', |
|
104 |
+ |
action_flag=ADDITION) |
|
105 |
+ |
|
|
106 |
+ |
|
|
107 |
+ |
class Migration(migrations.Migration): |
|
108 |
+ |
|
|
109 |
+ |
dependencies = [ |
|
110 |
+ |
('accounts', '0033_subscription_purchase_date_adjustments'), |
|
111 |
+ |
('footnotes', '0005_consolidate_event_footnotes'), |
|
112 |
+ |
('admin', '0003_logentry_add_action_flag_choices'), |
|
113 |
+ |
('common', '0005_create_script_user') |
|
114 |
+ |
] |
|
115 |
+ |
|
|
116 |
+ |
operations = [ |
|
117 |
+ |
migrations.RunPython(add_missing_footnotes, |
|
118 |
+ |
migrations.RunPython.noop) |
|
119 |
+ |
] |