From 1f949d758cbee0aa5cc78c3ef4deb5a9ff548fbb Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Mon, 27 May 2019 14:04:01 +0000 Subject: [PATCH 01/14] - Legacy-Id: 16226 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index fc1b23833..77d367a65 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ /.settings /.tmp /.factoryboy_random_state +/attic /bin /etc /ghostdriver.log From 815602351f36d9f93974d1f523c43d5eca05e873 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Mon, 10 Jun 2019 11:32:46 +0000 Subject: [PATCH 02/14] This is a series of 50 migrations that changes the Document and DocAlias primary keys from character strings to integers, and makes corresponding code changes. This was prompted by database limitations discovered when trying to make DocAlias use a m2m document field; with 255 long strings as primary keys for Document and DocAlias this violated the MySQL database limitations. Changing the primary keys to integers should also improve efficiency. Due to the data migrations which create the new integer primary keys and adds corresponding integer foreign keys matching the previous string foreign keys in all tables having foreign keys to Document and DocAlias, some of these migrations take a long time. The total set of migrations are expected to have a runtime on the order of 2 hours. - Legacy-Id: 16237 --- .../0003_add_communitylist_docs2_m2m.py | 43 + .../migrations/0004_set_document_m2m_keys.py | 55 + .../migrations/0005_1_del_docs_m2m_table.py | 31 + .../migrations/0005_2_add_docs_m2m_table.py | 33 + .../migrations/0006_copy_docs_m2m_table.py | 56 + .../migrations/0007_remove_docs2_m2m.py | 45 + ietf/community/tests.py | 4 +- ietf/community/utils.py | 2 +- ietf/community/views.py | 8 +- ietf/doc/fields.py | 21 +- .../0013_add_document_docalias_id.py | 25 + .../0014_set_document_docalias_id.py | 35 + .../0015_1_add_fk_to_document_id.py | 121 + .../0015_2_add_doc_document_m2m_fields.py | 93 + .../0016_set_document_docalias_fk.py | 112 + .../0017_make_document_id_primary_key.py | 25 + .../0018_remove_old_document_field.py | 124 + .../migrations/0019_rename_field_document2.py | 83 + .../migrations/0020_copy_docs_m2m_table.py | 33 + ietf/doc/migrations/0021_remove_docs2_m2m.py | 62 + .../0022_document_primary_key_cleanup.py | 67 + ietf/doc/models.py | 8 +- ietf/doc/utils.py | 4 +- ietf/doc/utils_search.py | 8 +- ietf/doc/views_doc.py | 6 +- ietf/doc/views_search.py | 2 +- ietf/group/feeds.py | 2 +- ietf/group/forms.py | 2 +- .../0013_add_groupmilestone_docs2_m2m.py | 52 + .../migrations/0014_set_document_m2m_keys.py | 56 + .../migrations/0015_1_del_docs_m2m_table.py | 40 + .../migrations/0015_2_add_docs_m2m_table.py | 40 + .../migrations/0016_copy_docs_m2m_table.py | 57 + .../group/migrations/0017_remove_docs2_m2m.py | 45 + .../0018_remove_old_document_field.py | 19 + .../migrations/0019_rename_field_document2.py | 21 + ietf/group/tests_review.py | 6 +- ietf/group/views.py | 8 +- ietf/idindex/index.py | 26 +- ietf/iesg/agenda.py | 2 +- ietf/iesg/tests.py | 2 +- ietf/ietfauth/tests.py | 2 +- .../0003_add_ipdocrel_document2_fk.py | 28 + .../0004_remove_iprdocrel_document.py | 19 + .../migrations/0005_rename_field_document2.py | 21 + .../0006_document_primary_key_cleanup.py | 22 + ietf/ipr/tests.py | 18 +- .../migrations/0003_liaison_document2_fk.py | 28 + ...ove_liaisonstatementattachment_document.py | 19 + .../migrations/0005_rename_field_document2.py | 21 + .../0006_document_primary_key_cleanup.py | 22 + .../0015_sessionpresentation_document2_fk.py | 28 + ...016_remove_sessionpresentation_document.py | 33 + .../migrations/0017_rename_field_document2.py | 25 + .../0018_document_primary_key_cleanup.py | 22 + ietf/meeting/models.py | 1 + .../migrations/0002_add_message_docs2_m2m.py | 30 + .../migrations/0003_set_document_m2m_keys.py | 46 + .../migrations/0004_1_del_docs_m2m_table.py | 31 + .../migrations/0004_2_add_docs_m2m_table.py | 31 + .../migrations/0005_copy_docs_m2m_table.py | 27 + .../migrations/0006_remove_docs2_m2m.py | 30 + ietf/name/fixtures/names.json | 2436 ++++++++++++++++- .../migrations/0011_review_document2_fk.py | 58 + .../0012_remove_old_document_field.py | 47 + .../migrations/0013_rename_field_document2.py | 31 + .../0014_document_primary_key_cleanup.py | 27 + ietf/review/models.py | 8 - ietf/review/utils.py | 30 +- ietf/secr/proceedings/proc_utils.py | 8 +- ietf/settings.py | 1 + .../0002_submission_document2_fk.py | 28 + .../0003_remove_old_document_field.py | 19 + .../migrations/0004_rename_field_document2.py | 21 + ietf/submit/tests.py | 12 +- ietf/sync/tests.py | 2 +- .../community/notification_email.txt | 2 +- ietf/templates/doc/document_review.html | 2 +- .../doc/review_assignment_summary.html | 6 +- .../group/manage_review_requests.html | 6 +- ietf/templates/iesg/agenda_doc.txt | 2 +- ietf/templates/ietfauth/review_overview.html | 2 +- ietf/templates/review/reviewer_reminder.txt | 2 +- ietf/templates/review/secretary_reminder.txt | 2 +- ietf/templates/sync/rfceditor_undo.html | 2 +- ietf/utils/history.py | 5 + ietf/utils/test_runner.py | 27 +- ietf/utils/tests.py | 10 - 88 files changed, 4657 insertions(+), 127 deletions(-) create mode 100644 ietf/community/migrations/0003_add_communitylist_docs2_m2m.py create mode 100644 ietf/community/migrations/0004_set_document_m2m_keys.py create mode 100644 ietf/community/migrations/0005_1_del_docs_m2m_table.py create mode 100644 ietf/community/migrations/0005_2_add_docs_m2m_table.py create mode 100644 ietf/community/migrations/0006_copy_docs_m2m_table.py create mode 100644 ietf/community/migrations/0007_remove_docs2_m2m.py create mode 100644 ietf/doc/migrations/0013_add_document_docalias_id.py create mode 100644 ietf/doc/migrations/0014_set_document_docalias_id.py create mode 100644 ietf/doc/migrations/0015_1_add_fk_to_document_id.py create mode 100644 ietf/doc/migrations/0015_2_add_doc_document_m2m_fields.py create mode 100644 ietf/doc/migrations/0016_set_document_docalias_fk.py create mode 100644 ietf/doc/migrations/0017_make_document_id_primary_key.py create mode 100644 ietf/doc/migrations/0018_remove_old_document_field.py create mode 100644 ietf/doc/migrations/0019_rename_field_document2.py create mode 100644 ietf/doc/migrations/0020_copy_docs_m2m_table.py create mode 100644 ietf/doc/migrations/0021_remove_docs2_m2m.py create mode 100644 ietf/doc/migrations/0022_document_primary_key_cleanup.py create mode 100644 ietf/group/migrations/0013_add_groupmilestone_docs2_m2m.py create mode 100644 ietf/group/migrations/0014_set_document_m2m_keys.py create mode 100644 ietf/group/migrations/0015_1_del_docs_m2m_table.py create mode 100644 ietf/group/migrations/0015_2_add_docs_m2m_table.py create mode 100644 ietf/group/migrations/0016_copy_docs_m2m_table.py create mode 100644 ietf/group/migrations/0017_remove_docs2_m2m.py create mode 100644 ietf/group/migrations/0018_remove_old_document_field.py create mode 100644 ietf/group/migrations/0019_rename_field_document2.py create mode 100644 ietf/ipr/migrations/0003_add_ipdocrel_document2_fk.py create mode 100644 ietf/ipr/migrations/0004_remove_iprdocrel_document.py create mode 100644 ietf/ipr/migrations/0005_rename_field_document2.py create mode 100644 ietf/ipr/migrations/0006_document_primary_key_cleanup.py create mode 100644 ietf/liaisons/migrations/0003_liaison_document2_fk.py create mode 100644 ietf/liaisons/migrations/0004_remove_liaisonstatementattachment_document.py create mode 100644 ietf/liaisons/migrations/0005_rename_field_document2.py create mode 100644 ietf/liaisons/migrations/0006_document_primary_key_cleanup.py create mode 100644 ietf/meeting/migrations/0015_sessionpresentation_document2_fk.py create mode 100644 ietf/meeting/migrations/0016_remove_sessionpresentation_document.py create mode 100644 ietf/meeting/migrations/0017_rename_field_document2.py create mode 100644 ietf/meeting/migrations/0018_document_primary_key_cleanup.py create mode 100644 ietf/message/migrations/0002_add_message_docs2_m2m.py create mode 100644 ietf/message/migrations/0003_set_document_m2m_keys.py create mode 100644 ietf/message/migrations/0004_1_del_docs_m2m_table.py create mode 100644 ietf/message/migrations/0004_2_add_docs_m2m_table.py create mode 100644 ietf/message/migrations/0005_copy_docs_m2m_table.py create mode 100644 ietf/message/migrations/0006_remove_docs2_m2m.py create mode 100644 ietf/review/migrations/0011_review_document2_fk.py create mode 100644 ietf/review/migrations/0012_remove_old_document_field.py create mode 100644 ietf/review/migrations/0013_rename_field_document2.py create mode 100644 ietf/review/migrations/0014_document_primary_key_cleanup.py create mode 100644 ietf/submit/migrations/0002_submission_document2_fk.py create mode 100644 ietf/submit/migrations/0003_remove_old_document_field.py create mode 100644 ietf/submit/migrations/0004_rename_field_document2.py diff --git a/ietf/community/migrations/0003_add_communitylist_docs2_m2m.py b/ietf/community/migrations/0003_add_communitylist_docs2_m2m.py new file mode 100644 index 000000000..9b74833eb --- /dev/null +++ b/ietf/community/migrations/0003_add_communitylist_docs2_m2m.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 14:23 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0002_auto_20180220_1052'), + ] + + operations = [ + migrations.CreateModel( + name='CommunityListDocs', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('communitylist', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='community.CommunityList')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id')), + ], + ), + migrations.AddField( + model_name='communitylist', + name='added_docs2', + field=models.ManyToManyField(related_name='communitylists', through='community.CommunityListDocs', to='doc.Document'), + ), + migrations.CreateModel( + name='SearchRuleDocs', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id')), + ('searchrule', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='community.SearchRule')), + ], + ), + migrations.AddField( + model_name='searchrule', + name='name_contains_index2', + field=models.ManyToManyField(related_name='searchrules', through='community.SearchRuleDocs', to='doc.Document'), + ), + ] diff --git a/ietf/community/migrations/0004_set_document_m2m_keys.py b/ietf/community/migrations/0004_set_document_m2m_keys.py new file mode 100644 index 000000000..ab4f81b20 --- /dev/null +++ b/ietf/community/migrations/0004_set_document_m2m_keys.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 14:27 +from __future__ import unicode_literals + +import sys + +from tqdm import tqdm + +from django.db import migrations + + +def forward(apps, schema_editor): + + Document = apps.get_model('doc','Document') + CommunityList = apps.get_model('community', 'CommunityList') + CommunityListDocs = apps.get_model('community', 'CommunityListDocs') + SearchRule = apps.get_model('community', 'SearchRule') + SearchRuleDocs = apps.get_model('community', 'SearchRuleDocs') + + # Document id fixup ------------------------------------------------------------ + + objs = Document.objects.in_bulk() + nameid = { o.name: o.id for id, o in objs.iteritems() } + + sys.stderr.write('\n') + + sys.stderr.write(' %s.%s:\n' % (CommunityList.__name__, 'added_docs')) + count = 0 + for l in tqdm(CommunityList.objects.all()): + for d in l.added_docs.all(): + count += 1 + CommunityListDocs.objects.get_or_create(communitylist=l, document_id=nameid[d.name]) + sys.stderr.write(' %s CommunityListDocs objects created\n' % (count, )) + + sys.stderr.write(' %s.%s:\n' % (SearchRule.__name__, 'name_contains_index')) + count = 0 + for r in tqdm(SearchRule.objects.all()): + for d in r.name_contains_index.all(): + count += 1 + SearchRuleDocs.objects.get_or_create(searchrule=r, document_id=nameid[d.name]) + sys.stderr.write(' %s SearchRuleDocs objects created\n' % (count, )) + +def reverse(apps, schema_editor): + pass + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0003_add_communitylist_docs2_m2m'), + ('doc', '0014_set_document_docalias_id'), + ] + + operations = [ + migrations.RunPython(forward, reverse), + ] diff --git a/ietf/community/migrations/0005_1_del_docs_m2m_table.py b/ietf/community/migrations/0005_1_del_docs_m2m_table.py new file mode 100644 index 000000000..1675631be --- /dev/null +++ b/ietf/community/migrations/0005_1_del_docs_m2m_table.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-22 08:15 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0004_set_document_m2m_keys'), + ] + + # The implementation of AlterField in Django 1.11 applies + # 'ALTER TABLE MODIFY ...;' in order to fix foregn keys + # to the altered field, but as it seems does _not_ fix up m2m + # intermediary tables in an equivalent manner, so here we remove and + # then recreate the m2m tables so they will have the appropriate field + # types. + + operations = [ + # Remove fields + migrations.RemoveField( + model_name='communitylist', + name='added_docs', + ), + migrations.RemoveField( + model_name='searchrule', + name='name_contains_index', + ), + ] diff --git a/ietf/community/migrations/0005_2_add_docs_m2m_table.py b/ietf/community/migrations/0005_2_add_docs_m2m_table.py new file mode 100644 index 000000000..1d34b2a9b --- /dev/null +++ b/ietf/community/migrations/0005_2_add_docs_m2m_table.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-22 08:15 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0005_1_del_docs_m2m_table'), + ] + + # The implementation of AlterField in Django 1.11 applies + # 'ALTER TABLE
MODIFY ...;' in order to fix foregn keys + # to the altered field, but as it seems does _not_ fix up m2m + # intermediary tables in an equivalent manner, so here we remove and + # then recreate the m2m tables so they will have the appropriate field + # types. + + operations = [ + # Add fields back (will create the m2m tables with the right field types) + migrations.AddField( + model_name='communitylist', + name='added_docs', + field=models.ManyToManyField(to='doc.Document'), + ), + migrations.AddField( + model_name='searchrule', + name='name_contains_index', + field=models.ManyToManyField(to='doc.Document'), + ), + ] diff --git a/ietf/community/migrations/0006_copy_docs_m2m_table.py b/ietf/community/migrations/0006_copy_docs_m2m_table.py new file mode 100644 index 000000000..9968a7355 --- /dev/null +++ b/ietf/community/migrations/0006_copy_docs_m2m_table.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-27 05:56 +from __future__ import unicode_literals + +from django.db import migrations + +import sys, time + +from tqdm import tqdm + + +def forward(apps, schema_editor): + + CommunityList = apps.get_model('community', 'CommunityList') + CommunityListDocs = apps.get_model('community', 'CommunityListDocs') + SearchRule = apps.get_model('community', 'SearchRule') + SearchRuleDocs = apps.get_model('community', 'SearchRuleDocs') + + # Document id fixup ------------------------------------------------------------ + + + sys.stderr.write('\n') + + sys.stderr.write(' %s.%s:\n' % (CommunityList.__name__, 'added_docs')) + for l in tqdm(CommunityList.objects.all()): + l.added_docs.set([ d.document for d in CommunityListDocs.objects.filter(communitylist=l) ]) + + sys.stderr.write(' %s.%s:\n' % (SearchRule.__name__, 'name_contains_index')) + for r in tqdm(SearchRule.objects.all()): + r.name_contains_index.set([ d.document for d in SearchRuleDocs.objects.filter(searchrule=r) ]) + +def reverse(apps, schema_editor): + pass + +def timestamp(apps, schema_editor): + sys.stderr.write('\n %s' % time.strftime('%Y-%m-%d %H:%M:%S')) + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0005_2_add_docs_m2m_table'), + ] + + operations = [ + #migrations.RunPython(forward, reverse), + # Alternative: + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO community_communitylist_added_docs SELECT * FROM community_communitylistdocs;", + ""), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO community_searchrule_name_contains_index SELECT * FROM community_searchruledocs;", + ""), + migrations.RunPython(timestamp, timestamp), + ] diff --git a/ietf/community/migrations/0007_remove_docs2_m2m.py b/ietf/community/migrations/0007_remove_docs2_m2m.py new file mode 100644 index 000000000..28364e645 --- /dev/null +++ b/ietf/community/migrations/0007_remove_docs2_m2m.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-30 03:06 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0006_copy_docs_m2m_table'), + ] + + operations = [ + migrations.RemoveField( + model_name='communitylistdocs', + name='communitylist', + ), + migrations.RemoveField( + model_name='communitylistdocs', + name='document', + ), + migrations.RemoveField( + model_name='searchruledocs', + name='document', + ), + migrations.RemoveField( + model_name='searchruledocs', + name='searchrule', + ), + migrations.RemoveField( + model_name='communitylist', + name='added_docs2', + ), + migrations.RemoveField( + model_name='searchrule', + name='name_contains_index2', + ), + migrations.DeleteModel( + name='CommunityListDocs', + ), + migrations.DeleteModel( + name='SearchRuleDocs', + ), + ] diff --git a/ietf/community/tests.py b/ietf/community/tests.py index 759cce65b..6b8c1bec0 100644 --- a/ietf/community/tests.py +++ b/ietf/community/tests.py @@ -107,7 +107,7 @@ class CommunityListTests(TestCase): self.assertEqual(r.status_code, 200) # add document - r = self.client.post(url, { "action": "add_documents", "documents": draft.pk }) + r = self.client.post(url, { "action": "add_documents", "documents": draft.name }) self.assertEqual(r.status_code, 302) clist = CommunityList.objects.get(user__username="plain") self.assertTrue(clist.added_docs.filter(pk=draft.pk)) @@ -118,7 +118,7 @@ class CommunityListTests(TestCase): self.assertTrue(draft.name in unicontent(r)) # remove document - r = self.client.post(url, { "action": "remove_document", "document": draft.pk }) + r = self.client.post(url, { "action": "remove_document", "document": draft.name }) self.assertEqual(r.status_code, 302) clist = CommunityList.objects.get(user__username="plain") self.assertTrue(not clist.added_docs.filter(pk=draft.pk)) diff --git a/ietf/community/utils.py b/ietf/community/utils.py index de1064645..e4fcd6f35 100644 --- a/ietf/community/utils.py +++ b/ietf/community/utils.py @@ -61,7 +61,7 @@ def augment_docs_with_tracking_info(docs, user): if user and user.is_authenticated: clist = CommunityList.objects.filter(user=user).first() if clist: - tracked.update(docs_tracked_by_community_list(clist).filter(pk__in=docs).values_list("pk", flat=True)) + tracked.update(docs_tracked_by_community_list(clist).filter(pk__in=[ d.pk for d in docs ]).values_list("pk", flat=True)) for d in docs: d.tracked_in_personal_community_list = d.pk in tracked diff --git a/ietf/community/views.py b/ietf/community/views.py index 472665e4e..60eb3de66 100644 --- a/ietf/community/views.py +++ b/ietf/community/views.py @@ -57,9 +57,9 @@ def manage_list(request, username=None, acronym=None, group_type=None): add_doc_form = AddDocumentsForm() if request.method == 'POST' and action == 'remove_document': - document_pk = request.POST.get('document') - if clist.pk is not None and document_pk: - document = get_object_or_404(clist.added_docs, pk=document_pk) + document_name = request.POST.get('document') + if clist.pk is not None and document_name: + document = get_object_or_404(clist.added_docs, name=document_name) clist.added_docs.remove(document) return HttpResponseRedirect("") @@ -209,7 +209,7 @@ def feed(request, username=None, acronym=None, group_type=None): since = datetime.datetime.now() - datetime.timedelta(days=14) events = DocEvent.objects.filter( - doc__in=documents, + doc__id__in=documents, time__gte=since, ).distinct().order_by('-time', '-id').select_related("doc") diff --git a/ietf/doc/fields.py b/ietf/doc/fields.py index 1d19a128e..3285e1416 100644 --- a/ietf/doc/fields.py +++ b/ietf/doc/fields.py @@ -2,6 +2,7 @@ import json from django.utils.html import escape from django import forms +from django.db.models import Q from django.urls import reverse as urlreverse import debug # pyflakes:ignore @@ -52,8 +53,10 @@ class SearchableDocumentsField(forms.CharField): if isinstance(value, (int, long)): value = str(value) if isinstance(value, basestring): - pks = self.parse_select2_value(value) - value = self.model.objects.filter(pk__in=pks) + items = self.parse_select2_value(value) + names = [ i for i in items if not i.isdigit() ] + ids = [ i for i in items if i.isdigit() ] + value = self.model.objects.filter(Q(name__in=names)|Q(id__in=ids)) filter_args = {} if self.model == DocAlias: filter_args["document__type"] = self.doc_type @@ -76,17 +79,17 @@ class SearchableDocumentsField(forms.CharField): def clean(self, value): value = super(SearchableDocumentsField, self).clean(value) - pks = self.parse_select2_value(value) + names = self.parse_select2_value(value) - objs = self.model.objects.filter(pk__in=pks) + objs = self.model.objects.filter(name__in=names) - found_pks = [str(o.pk) for o in objs] - failed_pks = [x for x in pks if x not in found_pks] - if failed_pks: - raise forms.ValidationError(u"Could not recognize the following documents: {pks}. You can only input documents already registered in the Datatracker.".format(pks=", ".join(failed_pks))) + found_names = [str(o.name) for o in objs] + failed_names = [x for x in names if x not in found_names] + if failed_names: + raise forms.ValidationError(u"Could not recognize the following documents: {names}. You can only input documents already registered in the Datatracker.".format(names=", ".join(failed_names))) if self.max_entries != None and len(objs) > self.max_entries: - raise forms.ValidationError(u"You can select at most %s entries only." % self.max_entries) + raise forms.ValidationError(u"You can select at most %s entries." % self.max_entries) return objs diff --git a/ietf/doc/migrations/0013_add_document_docalias_id.py b/ietf/doc/migrations/0013_add_document_docalias_id.py new file mode 100644 index 000000000..23e147f5a --- /dev/null +++ b/ietf/doc/migrations/0013_add_document_docalias_id.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 08:41 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0012_add_event_type_closed_review_assignment'), + ] + + operations = [ + migrations.AddField( + model_name='docalias', + name='id', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='document', + name='id', + field=models.IntegerField(default=0), + ), + ] diff --git a/ietf/doc/migrations/0014_set_document_docalias_id.py b/ietf/doc/migrations/0014_set_document_docalias_id.py new file mode 100644 index 000000000..dcade10dd --- /dev/null +++ b/ietf/doc/migrations/0014_set_document_docalias_id.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 08:42 +from __future__ import unicode_literals + +import sys + +from tqdm import tqdm + +from django.db import migrations + + +def forward(apps, schema_editor): + Document = apps.get_model('doc','Document') + sys.stderr.write('\n') + for i, d in enumerate(tqdm(Document.objects.all()), start=1): + d.id = i + d.save() + + DocAlias = apps.get_model('doc','DocAlias') + for i, d in enumerate(tqdm(DocAlias.objects.all()), start=1): + d.id = i + d.save() + +def reverse(apps, schema_editor): + pass + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0013_add_document_docalias_id'), + ] + + operations = [ + migrations.RunPython(forward, reverse), + ] diff --git a/ietf/doc/migrations/0015_1_add_fk_to_document_id.py b/ietf/doc/migrations/0015_1_add_fk_to_document_id.py new file mode 100644 index 000000000..023709c4f --- /dev/null +++ b/ietf/doc/migrations/0015_1_add_fk_to_document_id.py @@ -0,0 +1,121 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 10:29 +from __future__ import unicode_literals + +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0014_set_document_docalias_id'), + ] + + operations = [ + # Fix name and id fields first + migrations.AlterField( + model_name='docalias', + name='name', + field=models.CharField(max_length=255, unique=True), + ), + migrations.AlterField( + model_name='docalias', + name='id', + field=models.IntegerField(primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='document', + name='name', + field=models.CharField(max_length=255, unique=True, validators=[django.core.validators.RegexValidator(b'^[-a-z0-9]+$', b'Provide a valid document name consisting of lowercase letters, numbers and hyphens.', b'invalid')]), + ), + migrations.AlterField( + model_name='document', + name='id', + field=models.IntegerField(primary_key=True, serialize=False), + ), + + # Then remaining fields + migrations.AddField( + model_name='docalias', + name='document2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='dochistory', + name='doc2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='history_set', to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='documentauthor', + name='document2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='documenturl', + name='doc2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='relateddochistory', + name='target2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reversely_related_document_history_set', to='doc.DocAlias', to_field=b'id'), + ), + migrations.AddField( + model_name='relateddocument', + name='source2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='relateddocument', + name='target2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.DocAlias', to_field=b'id'), + ), + migrations.AddField( + model_name='docevent', + name='doc2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='id'), + ), + migrations.AlterField( + model_name='docalias', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_docalias', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='dochistory', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_hist', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='documentauthor', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_doc_auth', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='documenturl', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_doc_url', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='relateddochistory', + name='target', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_hist_target', to='doc.DocAlias', to_field=b'name'), + ), + migrations.AlterField( + model_name='relateddocument', + name='source', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_rel_source', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='relateddocument', + name='target', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_rel_target', to='doc.DocAlias', to_field=b'name'), + ), + migrations.AlterField( + model_name='docevent', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_docevent', to='doc.Document', to_field=b'name'), + ), + ] diff --git a/ietf/doc/migrations/0015_2_add_doc_document_m2m_fields.py b/ietf/doc/migrations/0015_2_add_doc_document_m2m_fields.py new file mode 100644 index 000000000..10c874892 --- /dev/null +++ b/ietf/doc/migrations/0015_2_add_doc_document_m2m_fields.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-28 12:42 +from __future__ import unicode_literals + +import sys, time + +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + + +def timestamp(apps, schema_editor): + sys.stderr.write('\n %s' % time.strftime('%Y-%m-%d %H:%M:%S')) + +class Migration(migrations.Migration): + + dependencies = [ + ('name', '0006_adjust_statenames'), + ('doc', '0015_1_add_fk_to_document_id'), + ] + + operations = [ + migrations.CreateModel( + name='DocumentLanguages', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='name', related_name='doclanguages')), + ('formallanguagename', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='name.FormalLanguageName')), + ], + ), + migrations.CreateModel( + name='DocumentStates', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='name', related_name='docstates')), + ('state', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.State')), + ], + ), + migrations.CreateModel( + name='DocumentTags', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='name', related_name='doctags')), + ('doctagname', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='name.DocTagName')), + ], + ), + migrations.AddField( + model_name='document', + name='formal_languages2', + field=models.ManyToManyField(blank=True, related_name='languagedocs', through='doc.DocumentLanguages', to='name.FormalLanguageName'), + ), + migrations.AddField( + model_name='document', + name='states2', + field=models.ManyToManyField(blank=True, related_name='statedocs', through='doc.DocumentStates', to='doc.State'), + ), + migrations.AddField( + model_name='document', + name='tags2', + field=models.ManyToManyField(blank=True, related_name='tagdocs', through='doc.DocumentTags', to='name.DocTagName'), + ), + # Here we copy the content of the existing implicit m2m tables for + # the Document m2m fields into the explicit through tabeles, in order + # to be able to later set the correct id from name + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO doc_documentlanguages SELECT * FROM doc_document_formal_languages;", + ""), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO doc_documentstates SELECT * FROM doc_document_states;", + ""), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO doc_documenttags SELECT * FROM doc_document_tags;", + ""), + migrations.RunPython(timestamp, timestamp), + migrations.AddField( + model_name='documentlanguages', + name='document2', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='id', null=True, default=None), + ), + migrations.AddField( + model_name='documentstates', + name='document2', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='id', null=True, default=None), ), + migrations.AddField( + model_name='documenttags', + name='document2', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='id', null=True, default=None), + + ), + ] diff --git a/ietf/doc/migrations/0016_set_document_docalias_fk.py b/ietf/doc/migrations/0016_set_document_docalias_fk.py new file mode 100644 index 000000000..5bcc9872a --- /dev/null +++ b/ietf/doc/migrations/0016_set_document_docalias_fk.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 14:04 +from __future__ import unicode_literals + +import sys + +from tqdm import tqdm + +from django.db import migrations + +def forward(apps, schema_editor): + + def add_id_fk(o, a, nameid): + n = getattr(o, a+'_id') + if n: + i = nameid[n] + if not isinstance(i, (int, long)): + raise ValueError("Inappropriate value: %s: nameid[%s]: %s" % (o.__class__.__name__, n, i)) + if getattr(o, a+'2_id') != i: + setattr(o, a+'2_id', i) + o.save() + + DocAlias = apps.get_model('doc','DocAlias') + DocEvent = apps.get_model('doc', 'DocEvent') + DocHistory = apps.get_model('doc', 'DocHistory') + Document = apps.get_model('doc', 'Document') + DocumentAuthor = apps.get_model('doc', 'DocumentAuthor') + DocumentLanguages = apps.get_model('doc', 'DocumentLanguages') + DocumentStates = apps.get_model('doc', 'DocumentStates') + DocumentTags = apps.get_model('doc', 'DocumentTags') + DocumentURL = apps.get_model('doc', 'DocumentURL') + Group = apps.get_model('group', 'Group') + IprDocRel = apps.get_model('ipr', 'IprDocRel') + LiaisonStatementAttachment = apps.get_model('liaisons', 'LiaisonStatementAttachment') + RelatedDocHistory = apps.get_model('doc', 'RelatedDocHistory') + RelatedDocument = apps.get_model('doc', 'RelatedDocument') + ReviewAssignment = apps.get_model('review', 'ReviewAssignment') + ReviewRequest = apps.get_model('review', 'ReviewRequest') + ReviewWish = apps.get_model('review', 'ReviewWish') + SessionPresentation = apps.get_model('meeting', 'SessionPresentation') + Submission = apps.get_model('submit', 'Submission') + + # Document id fixup ------------------------------------------------------------ + + objs = Document.objects.in_bulk() + nameid = { o.name: o.id for id, o in objs.iteritems() } + + sys.stderr.write('\n') + + sys.stderr.write('Setting Document FKs:\n') + + for C, a in [ + ( DocAlias , 'document'), + ( DocEvent , 'doc'), + ( DocHistory , 'doc'), + ( DocumentAuthor , 'document'), + ( DocumentLanguages , 'document'), + ( DocumentStates , 'document'), + ( DocumentTags , 'document'), + ( DocumentURL , 'doc'), + ( Group , 'charter'), + ( LiaisonStatementAttachment , 'document'), + ( RelatedDocument , 'source'), + ( ReviewAssignment , 'review'), + ( ReviewRequest , 'doc'), + ( ReviewRequest , 'unused_review'), + ( ReviewWish , 'doc'), + ( SessionPresentation , 'document'), + ( Submission , 'draft'), + ]: + sys.stderr.write(' %s.%s:\n' % (C.__name__, a)) + for o in tqdm(C.objects.all()): + add_id_fk(o, a, nameid) + + # DocAlias id fixup ------------------------------------------------------------ + + sys.stderr.write('\n') + + objs = DocAlias.objects.in_bulk() + nameid = { o.name: o.id for id, o in objs.iteritems() } + + sys.stderr.write('Setting DocAlias FKs:\n') + + for C, a in [ + ( IprDocRel , 'document'), + ( RelatedDocument , 'target'), + ( RelatedDocHistory , 'target'), + ]: + sys.stderr.write(' %s.%s:\n' % (C.__name__, a)) + for o in tqdm(C.objects.all()): + add_id_fk(o, a, nameid) + +def reverse(apps, schema_editor): + pass + +class Migration(migrations.Migration): + + dependencies = [ + ('community', '0004_set_document_m2m_keys'), + ('doc', '0015_2_add_doc_document_m2m_fields'), + ('group', '0014_set_document_m2m_keys'), + ('ipr', '0003_add_ipdocrel_document2_fk'), + ('liaisons', '0003_liaison_document2_fk'), + ('meeting', '0015_sessionpresentation_document2_fk'), + ('message', '0003_set_document_m2m_keys'), + ('review', '0011_review_document2_fk'), + ('submit', '0002_submission_document2_fk'), + ] + + operations = [ + migrations.RunPython(forward, reverse), + ] diff --git a/ietf/doc/migrations/0017_make_document_id_primary_key.py b/ietf/doc/migrations/0017_make_document_id_primary_key.py new file mode 100644 index 000000000..48e7cf308 --- /dev/null +++ b/ietf/doc/migrations/0017_make_document_id_primary_key.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-09 05:46 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0016_set_document_docalias_fk'), + ] + + operations = [ + migrations.AlterField( + model_name='docalias', + name='id', + field=models.AutoField(primary_key=True, serialize=False), + ), + migrations.AlterField( + model_name='document', + name='id', + field=models.AutoField(primary_key=True, serialize=False), + ), + ] diff --git a/ietf/doc/migrations/0018_remove_old_document_field.py b/ietf/doc/migrations/0018_remove_old_document_field.py new file mode 100644 index 000000000..08401f3cc --- /dev/null +++ b/ietf/doc/migrations/0018_remove_old_document_field.py @@ -0,0 +1,124 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-20 09:53 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0017_make_document_id_primary_key'), + ] + + operations = [ + migrations.AlterModelOptions( + name='documentauthor', + options={'ordering': ['document2', 'order']}, + ), + migrations.RemoveIndex( + model_name='docevent', + name='doc_doceven_type_43e53e_idx', + ), + migrations.RemoveField( + model_name='docalias', + name='document', + ), + migrations.RemoveField( + model_name='docevent', + name='doc', + ), + migrations.RemoveField( + model_name='dochistory', + name='doc', + ), + migrations.RemoveField( + model_name='documentauthor', + name='document', + ), + migrations.RemoveField( + model_name='documenturl', + name='doc', + ), + migrations.RemoveField( + model_name='relateddochistory', + name='target', + ), + migrations.RemoveField( + model_name='relateddocument', + name='source', + ), + migrations.RemoveField( + model_name='relateddocument', + name='target', + ), + migrations.AddIndex( + model_name='docevent', + index=models.Index(fields=[b'type', b'doc2'], name='doc_doceven_type_ac7748_idx'), + ), + # The following 9 migrations are related to the m2m fields on Document + # Remove the intermediary model field pointing to Document.name + migrations.RemoveField( + model_name='documentlanguages', + name='document', + ), + migrations.RemoveField( + model_name='documentstates', + name='document', + ), + migrations.RemoveField( + model_name='documenttags', + name='document', + ), + # Rename the intermediary model field pointing to Document.id, to + # match the implicit m2m table + migrations.RenameField( + model_name='documentlanguages', + old_name='document2', + new_name='document', + ), + migrations.RenameField( + model_name='documentstates', + old_name='document2', + new_name='document', + ), + migrations.RenameField( + model_name='documenttags', + old_name='document2', + new_name='document', + ), + # Alter the fields to point to Document.pk instead of Document.name + migrations.AlterField( + model_name='documentlanguages', + name='document', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='documentstates', + name='document', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='documenttags', + name='document', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + # Remove the implicit m2m tables which point to Document.name + migrations.RemoveField( + model_name='document', + name='formal_languages', + ), + migrations.RemoveField( + model_name='document', + name='states', + ), + migrations.RemoveField( + model_name='document', + name='tags', + ), + # Next (in a separate migration, in order to commit the above before + # we proceed) we'll create the implicit m2m tables again, this time + # pointing to Document.id since that's now the primary key. + ] diff --git a/ietf/doc/migrations/0019_rename_field_document2.py b/ietf/doc/migrations/0019_rename_field_document2.py new file mode 100644 index 000000000..4a41ab83e --- /dev/null +++ b/ietf/doc/migrations/0019_rename_field_document2.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 05:31 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0018_remove_old_document_field'), + ] + + operations = [ + migrations.AlterModelOptions( + name='documentauthor', + options={'ordering': ['document', 'order']}, + ), + migrations.RemoveIndex( + model_name='docevent', + name='doc_doceven_type_ac7748_idx', + ), + migrations.RenameField( + model_name='docalias', + old_name='document2', + new_name='document', + ), + migrations.RenameField( + model_name='docevent', + old_name='doc2', + new_name='doc', + ), + migrations.RenameField( + model_name='dochistory', + old_name='doc2', + new_name='doc', + ), + migrations.RenameField( + model_name='documentauthor', + old_name='document2', + new_name='document', + ), + migrations.RenameField( + model_name='documenturl', + old_name='doc2', + new_name='doc', + ), + migrations.RenameField( + model_name='relateddochistory', + old_name='target2', + new_name='target', + ), + migrations.RenameField( + model_name='relateddocument', + old_name='source2', + new_name='source', + ), + migrations.RenameField( + model_name='relateddocument', + old_name='target2', + new_name='target', + ), + migrations.AddIndex( + model_name='docevent', + index=models.Index(fields=[b'type', b'doc'], name='doc_doceven_type_43e53e_idx'), + ), + # Add back the m2m field we removed in 0018_... + migrations.AddField( + model_name='document', + name='formal_languages', + field=models.ManyToManyField(blank=True, help_text=b'Formal languages used in document', to='name.FormalLanguageName'), + ), + migrations.AddField( + model_name='document', + name='states', + field=models.ManyToManyField(blank=True, to='doc.State'), + ), + migrations.AddField( + model_name='document', + name='tags', + field=models.ManyToManyField(blank=True, to='name.DocTagName'), + ), + ] diff --git a/ietf/doc/migrations/0020_copy_docs_m2m_table.py b/ietf/doc/migrations/0020_copy_docs_m2m_table.py new file mode 100644 index 000000000..5cfae63bf --- /dev/null +++ b/ietf/doc/migrations/0020_copy_docs_m2m_table.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 05:31 +from __future__ import unicode_literals + +import sys, time + +from django.db import migrations + +def timestamp(apps, schema_editor): + sys.stderr.write('\n %s' % time.strftime('%Y-%m-%d %H:%M:%S')) + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ] + + operations = [ + # Copy the doc IDs from the explicit m2m table to the implicit table + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO doc_document_formal_languages SELECT id,document_id,formallanguagename_id FROM doc_documentlanguages;", + ""), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO doc_document_states SELECT id,document_id,state_id FROM doc_documentstates;", + ""), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO doc_document_tags SELECT id,document_id,doctagname_id FROM doc_documenttags;", + ""), + migrations.RunPython(timestamp, timestamp), + ] diff --git a/ietf/doc/migrations/0021_remove_docs2_m2m.py b/ietf/doc/migrations/0021_remove_docs2_m2m.py new file mode 100644 index 000000000..e2bb27c77 --- /dev/null +++ b/ietf/doc/migrations/0021_remove_docs2_m2m.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-30 03:36 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0020_copy_docs_m2m_table'), + ] + + operations = [ + # Get rid of the explicit m2m tables which we needed only to be + # able to convert from Document.name to Document.id + migrations.RemoveField( + model_name='documentlanguages', + name='document', + ), + migrations.RemoveField( + model_name='documentlanguages', + name='formallanguagename', + ), + migrations.RemoveField( + model_name='documentstates', + name='document', + ), + migrations.RemoveField( + model_name='documentstates', + name='state', + ), + migrations.RemoveField( + model_name='documenttags', + name='doctagname', + ), + migrations.RemoveField( + model_name='documenttags', + name='document', + ), + migrations.RemoveField( + model_name='document', + name='formal_languages2', + ), + migrations.RemoveField( + model_name='document', + name='states2', + ), + migrations.RemoveField( + model_name='document', + name='tags2', + ), + migrations.DeleteModel( + name='DocumentLanguages', + ), + migrations.DeleteModel( + name='DocumentStates', + ), + migrations.DeleteModel( + name='DocumentTags', + ), + ] diff --git a/ietf/doc/migrations/0022_document_primary_key_cleanup.py b/ietf/doc/migrations/0022_document_primary_key_cleanup.py new file mode 100644 index 000000000..dba56d2dc --- /dev/null +++ b/ietf/doc/migrations/0022_document_primary_key_cleanup.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-10 03:47 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0021_remove_docs2_m2m'), + ] + + operations = [ + migrations.AlterField( + model_name='docalias', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='docalias', + name='id', + field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='docevent', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='dochistory', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='history_set', to='doc.Document'), + ), + migrations.AlterField( + model_name='document', + name='id', + field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='documentauthor', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='documenturl', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='relateddochistory', + name='target', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reversely_related_document_history_set', to='doc.DocAlias'), + ), + migrations.AlterField( + model_name='relateddocument', + name='source', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + migrations.AlterField( + model_name='relateddocument', + name='target', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.DocAlias'), + ), + ] diff --git a/ietf/doc/models.py b/ietf/doc/models.py index 0c8509837..87ada27cc 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -609,7 +609,7 @@ validate_docname = RegexValidator( ) class Document(DocumentInfo): - name = models.CharField(max_length=255, primary_key=True, validators=[validate_docname,]) # immutable + name = models.CharField(max_length=255, validators=[validate_docname,], unique=True) # immutable def __unicode__(self): return self.name @@ -908,8 +908,10 @@ class DocAlias(models.Model): same immutable Document.name, in the tables, but will be referred to by RFC number, primarily, after achieving RFC status. """ - name = models.CharField(max_length=255, primary_key=True) + name = models.CharField(max_length=255, unique=True) document = ForeignKey(Document) +# docs = models.ManyToManyField(Document, related_name='aliases') + def __unicode__(self): return "%s-->%s" % (self.name, self.document.name) document_link = admin_link("document") @@ -1005,7 +1007,7 @@ class DocEvent(models.Model): time = models.DateTimeField(default=datetime.datetime.now, help_text="When the event happened", db_index=True) type = models.CharField(max_length=50, choices=EVENT_TYPES) by = ForeignKey(Person) - doc = ForeignKey('doc.Document') + doc = ForeignKey(Document) rev = models.CharField(verbose_name="revision", max_length=16, null=True, blank=True) desc = models.TextField() diff --git a/ietf/doc/utils.py b/ietf/doc/utils.py index 69fee36f9..c5a05ad1e 100644 --- a/ietf/doc/utils.py +++ b/ietf/doc/utils.py @@ -685,8 +685,8 @@ def extract_complete_replaces_ancestor_mapping_for_docs(names): break relations = RelatedDocument.objects.filter( - source__in=front, relationship="replaces" - ).select_related("target").values_list("source", "target__document") + source__name__in=front, relationship="replaces" + ).select_related("target").values_list("source__name", "target__document__name") if not relations: break diff --git a/ietf/doc/utils_search.py b/ietf/doc/utils_search.py index 31b365e27..d042616d1 100644 --- a/ietf/doc/utils_search.py +++ b/ietf/doc/utils_search.py @@ -20,7 +20,7 @@ def fill_in_telechat_date(docs, doc_dict=None, doc_ids=None): doc_ids = doc_dict.keys() seen = set() - for e in TelechatDocEvent.objects.filter(doc__in=doc_ids, type="scheduled_for_telechat").order_by('-time'): + for e in TelechatDocEvent.objects.filter(doc__id__in=doc_ids, type="scheduled_for_telechat").order_by('-time'): if e.doc_id not in seen: d = doc_dict[e.doc_id] d.telechat_date = wrap_value(d.telechat_date(e)) @@ -49,7 +49,7 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False): doc_dict = dict((d.pk, d) for d in docs) doc_ids = doc_dict.keys() - rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", document__in=doc_ids).values_list("document", "name")) + rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", document__id__in=doc_ids).values_list("document__id", "name")) # latest event cache event_types = ("published_rfc", @@ -61,11 +61,11 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False): for e in event_types: d.latest_event_cache[e] = None - for e in DocEvent.objects.filter(doc__in=doc_ids, type__in=event_types).order_by('time'): + for e in DocEvent.objects.filter(doc__id__in=doc_ids, type__in=event_types).order_by('time'): doc_dict[e.doc_id].latest_event_cache[e.type] = e seen = set() - for e in BallotDocEvent.objects.filter(doc__in=doc_ids, type__in=('created_ballot', 'closed_ballot')).order_by('-time','-id'): + for e in BallotDocEvent.objects.filter(doc__id__in=doc_ids, type__in=('created_ballot', 'closed_ballot')).order_by('-time','-id'): if not e.doc_id in seen: doc_dict[e.doc_id].ballot = e if e.type == 'created_ballot' else None seen.add(e.doc_id) diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py index e9597a506..cd2ee59a9 100644 --- a/ietf/doc/views_doc.py +++ b/ietf/doc/views_doc.py @@ -382,7 +382,7 @@ def document_main(request, name, rev=None): published = doc.latest_event(type="published_rfc") started_iesg_process = doc.latest_event(type="started_iesg_process") - review_assignments = review_assignments_to_list_for_docs([doc]).get(doc.pk, []) + review_assignments = review_assignments_to_list_for_docs([doc]).get(doc.name, []) no_review_from_teams = no_review_from_teams_on_doc(doc, rev or doc.rev) return render(request, "doc/document_draft.html", @@ -598,11 +598,11 @@ def document_main(request, name, rev=None): # If we want to go back to using markup_txt.markup_unicode, call it explicitly here like this: # content = markup_txt.markup_unicode(content, split=False, width=80) - review_assignment = ReviewAssignment.objects.filter(review=doc.name).first() + review_assignment = ReviewAssignment.objects.filter(review__name=doc.name).first() other_reviews = [] if review_assignment: - other_reviews = [r for r in review_assignments_to_list_for_docs([review_assignment.review_request.doc]).get(doc.pk, []) if r != review_assignment] + other_reviews = [r for r in review_assignments_to_list_for_docs([review_assignment.review_request.doc]).get(doc.name, []) if r != review_assignment] return render(request, "doc/document_review.html", dict(doc=doc, diff --git a/ietf/doc/views_search.py b/ietf/doc/views_search.py index 8bd40ed4f..f91a20254 100644 --- a/ietf/doc/views_search.py +++ b/ietf/doc/views_search.py @@ -478,7 +478,7 @@ def index_all_drafts(request): else: heading = "%s Internet-Drafts" % state.name - draft_names = DocAlias.objects.filter(document__states=state).values_list("name", "document") + draft_names = DocAlias.objects.filter(document__states=state).values_list("name", "document__name") names = [] names_to_skip = set() diff --git a/ietf/group/feeds.py b/ietf/group/feeds.py index 3b36b0608..a911bbf81 100644 --- a/ietf/group/feeds.py +++ b/ietf/group/feeds.py @@ -38,7 +38,7 @@ class GroupChangesFeed(Feed): def item_link(self, obj): if isinstance(obj, DocEvent): - return urlreverse("ietf.doc.views_doc.document_main", kwargs={'name': obj.doc_id }) + return urlreverse("ietf.doc.views_doc.document_main", kwargs={'name': obj.doc.name }) elif isinstance(obj, GroupEvent): return obj.group.about_url() diff --git a/ietf/group/forms.py b/ietf/group/forms.py index 635312263..73ee69328 100644 --- a/ietf/group/forms.py +++ b/ietf/group/forms.py @@ -227,7 +227,7 @@ class ManageReviewRequestForm(forms.Form): def __init__(self, review_req, *args, **kwargs): if not "prefix" in kwargs: if review_req.pk is None: - kwargs["prefix"] = "r{}-{}".format(review_req.type_id, review_req.doc_id) + kwargs["prefix"] = "r{}-{}".format(review_req.type_id, review_req.doc.name) else: kwargs["prefix"] = "r{}".format(review_req.pk) diff --git a/ietf/group/migrations/0013_add_groupmilestone_docs2_m2m.py b/ietf/group/migrations/0013_add_groupmilestone_docs2_m2m.py new file mode 100644 index 000000000..2857df1b3 --- /dev/null +++ b/ietf/group/migrations/0013_add_groupmilestone_docs2_m2m.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-02-25 13:02 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0012_add_old_nomcom_announcements'), + ] + + operations = [ + migrations.CreateModel( + name='GroupMilestoneDocs', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id')), + ('groupmilestone', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='group.GroupMilestone')), + ], + ), + migrations.CreateModel( + name='GroupMilestoneHistoryDocs', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id')), + ('groupmilestonehistory', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='group.GroupMilestoneHistory')), + ], + ), + migrations.AddField( + model_name='group', + name='charter2', + field=ietf.utils.models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chartered_group', to='doc.Document', to_field=b'id'), + ), + migrations.AlterField( + model_name='group', + name='charter', + field=ietf.utils.models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='old_group', to='doc.Document', to_field=b'name'), + ), + migrations.AddField( + model_name='groupmilestone', + name='docs2', + field=models.ManyToManyField(blank=True, related_name='groupmilestones', through='group.GroupMilestoneDocs', to='doc.Document'), + ), + migrations.AddField( + model_name='groupmilestonehistory', + name='docs2', + field=models.ManyToManyField(blank=True, related_name='groupmilestoneshistory', through='group.GroupMilestoneHistoryDocs', to='doc.Document'), + ), + ] diff --git a/ietf/group/migrations/0014_set_document_m2m_keys.py b/ietf/group/migrations/0014_set_document_m2m_keys.py new file mode 100644 index 000000000..73dd5be43 --- /dev/null +++ b/ietf/group/migrations/0014_set_document_m2m_keys.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-10 06:48 +from __future__ import unicode_literals + +import sys + +from tqdm import tqdm + +from django.db import migrations + + +def forward(apps, schema_editor): + + Document = apps.get_model('doc','Document') + GroupMilestone = apps.get_model('group', 'GroupMilestone') + GroupMilestoneDocs = apps.get_model('group', 'GroupMilestoneDocs') + GroupMilestoneHistory = apps.get_model('group', 'GroupMilestoneHistory') + GroupMilestoneHistoryDocs = apps.get_model('group', 'GroupMilestoneHistoryDocs') + + # Document id fixup ------------------------------------------------------------ + + objs = Document.objects.in_bulk() + nameid = { o.name: o.id for id, o in objs.iteritems() } + + sys.stderr.write('\n') + + sys.stderr.write(' %s.%s:\n' % (GroupMilestone.__name__, 'docs')) + count = 0 + for m in tqdm(GroupMilestone.objects.all()): + for d in m.docs.all(): + count += 1 + GroupMilestoneDocs.objects.get_or_create(groupmilestone=m, document_id=nameid[d.name]) + sys.stderr.write(' %s GroupMilestoneDocs objects created\n' % (count, )) + + sys.stderr.write(' %s.%s:\n' % (GroupMilestoneHistory.__name__, 'docs')) + count = 0 + for m in tqdm(GroupMilestoneHistory.objects.all()): + for d in m.docs.all(): + count += 1 + GroupMilestoneHistoryDocs.objects.get_or_create(GroupMilestoneHistory=m, document_id=nameid[d.name]) + sys.stderr.write(' %s GroupMilestoneHistoryDocs objects created\n' % (count, )) + + +def reverse(apps, schema_editor): + pass + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0013_add_groupmilestone_docs2_m2m'), + ('doc', '0014_set_document_docalias_id'), + ] + + operations = [ + migrations.RunPython(forward, reverse), + ] diff --git a/ietf/group/migrations/0015_1_del_docs_m2m_table.py b/ietf/group/migrations/0015_1_del_docs_m2m_table.py new file mode 100644 index 000000000..b2a570b8b --- /dev/null +++ b/ietf/group/migrations/0015_1_del_docs_m2m_table.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-22 08:00 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0014_set_document_m2m_keys'), + ] + + # The implementation of AlterField in Django 1.11 applies + # 'ALTER TABLE
MODIFY ...;' in order to fix foregn keys + # to the altered field, but as it seems does _not_ fix up m2m + # intermediary tables in an equivalent manner, so here we remove and + # then recreate the m2m tables so they will have the appropriate field + # types. + + operations = [ + migrations.RemoveField( + model_name='groupmilestone', + name='docs', + ), + migrations.RemoveField( + model_name='groupmilestonehistory', + name='docs', + ), + migrations.AddField( + model_name='groupmilestone', + name='docs', + field=models.ManyToManyField(to='doc.Document'), + ), + migrations.AddField( + model_name='groupmilestonehistory', + name='docs', + field=models.ManyToManyField(to='doc.Document'), + ), + ] diff --git a/ietf/group/migrations/0015_2_add_docs_m2m_table.py b/ietf/group/migrations/0015_2_add_docs_m2m_table.py new file mode 100644 index 000000000..7528014ed --- /dev/null +++ b/ietf/group/migrations/0015_2_add_docs_m2m_table.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-22 08:00 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0015_1_del_docs_m2m_table'), + ] + + # The implementation of AlterField in Django 1.11 applies + # 'ALTER TABLE
MODIFY ...;' in order to fix foregn keys + # to the altered field, but as it seems does _not_ fix up m2m + # intermediary tables in an equivalent manner, so here we remove and + # then recreate the m2m tables so they will have the appropriate field + # types. + + operations = [ + migrations.RemoveField( + model_name='groupmilestone', + name='docs', + ), + migrations.RemoveField( + model_name='groupmilestonehistory', + name='docs', + ), + migrations.AddField( + model_name='groupmilestone', + name='docs', + field=models.ManyToManyField(blank=True, to='doc.Document'), + ), + migrations.AddField( + model_name='groupmilestonehistory', + name='docs', + field=models.ManyToManyField(blank=True, to='doc.Document'), + ), + ] diff --git a/ietf/group/migrations/0016_copy_docs_m2m_table.py b/ietf/group/migrations/0016_copy_docs_m2m_table.py new file mode 100644 index 000000000..d606fceb0 --- /dev/null +++ b/ietf/group/migrations/0016_copy_docs_m2m_table.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-27 05:57 +from __future__ import unicode_literals + +import sys, time + +from tqdm import tqdm + +from django.db import migrations + + +def forward(apps, schema_editor): + + GroupMilestone = apps.get_model('group', 'GroupMilestone') + GroupMilestoneDocs = apps.get_model('group', 'GroupMilestoneDocs') + GroupMilestoneHistory = apps.get_model('group', 'GroupMilestoneHistory') + GroupMilestoneHistoryDocs = apps.get_model('group', 'GroupMilestoneHistoryDocs') + + # Document id fixup ------------------------------------------------------------ + + sys.stderr.write('\n') + + sys.stderr.write(' %s.%s:\n' % (GroupMilestone.__name__, 'docs')) + for m in tqdm(GroupMilestone.objects.all()): + m.docs.set([ d.document for d in GroupMilestoneDocs.objects.filter(groupmilestone=m) ]) + + sys.stderr.write(' %s.%s:\n' % (GroupMilestoneHistory.__name__, 'docs')) + for m in tqdm(GroupMilestoneHistory.objects.all()): + m.docs.set([ d.document for d in GroupMilestoneHistoryDocs.objects.filter(groupmilestonehistory=m) ]) + + +def reverse(apps, schema_editor): + pass + +def timestamp(apps, schema_editor): + sys.stderr.write('\n %s' % time.strftime('%Y-%m-%d %H:%M:%S')) + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0015_2_add_docs_m2m_table'), + ] + + operations = [ + #migrations.RunPython(forward, reverse), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO group_groupmilestone_docs SELECT * FROM group_groupmilestonedocs;", + "" + ), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO group_groupmilestonehistory_docs SELECT * FROM group_groupmilestonehistorydocs;", + "" + ), + migrations.RunPython(timestamp, timestamp), + ] diff --git a/ietf/group/migrations/0017_remove_docs2_m2m.py b/ietf/group/migrations/0017_remove_docs2_m2m.py new file mode 100644 index 000000000..df5d4cf56 --- /dev/null +++ b/ietf/group/migrations/0017_remove_docs2_m2m.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-30 03:23 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0016_copy_docs_m2m_table'), + ] + + operations = [ + migrations.RemoveField( + model_name='groupmilestonedocs', + name='document', + ), + migrations.RemoveField( + model_name='groupmilestonedocs', + name='groupmilestone', + ), + migrations.RemoveField( + model_name='groupmilestonehistorydocs', + name='document', + ), + migrations.RemoveField( + model_name='groupmilestonehistorydocs', + name='groupmilestonehistory', + ), + migrations.RemoveField( + model_name='groupmilestone', + name='docs2', + ), + migrations.RemoveField( + model_name='groupmilestonehistory', + name='docs2', + ), + migrations.DeleteModel( + name='GroupMilestoneDocs', + ), + migrations.DeleteModel( + name='GroupMilestoneHistoryDocs', + ), + ] diff --git a/ietf/group/migrations/0018_remove_old_document_field.py b/ietf/group/migrations/0018_remove_old_document_field.py new file mode 100644 index 000000000..1b978a215 --- /dev/null +++ b/ietf/group/migrations/0018_remove_old_document_field.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-25 06:51 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('group', '0017_remove_docs2_m2m'), + ] + + operations = [ + migrations.RemoveField( + model_name='group', + name='charter', + ), + ] diff --git a/ietf/group/migrations/0019_rename_field_document2.py b/ietf/group/migrations/0019_rename_field_document2.py new file mode 100644 index 000000000..761d7d7ce --- /dev/null +++ b/ietf/group/migrations/0019_rename_field_document2.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-25 06:52 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ('group', '0018_remove_old_document_field'), + ] + + operations = [ + migrations.RenameField( + model_name='group', + old_name='charter2', + new_name='charter', + ), + ] diff --git a/ietf/group/tests_review.py b/ietf/group/tests_review.py index 021172a98..e6b781712 100644 --- a/ietf/group/tests_review.py +++ b/ietf/group/tests_review.py @@ -237,7 +237,7 @@ class ReviewTests(TestCase): content = """ {% autoescape off %} Reviewer Deadline Draft - {% for r in review_assignments %}{{ r.reviewer.person.plain_name|ljust:"22" }} {{ r.review_request.deadline|date:"Y-m-d" }} {{ r.review_request.doc_id }}-{% if r.review_request.requested_rev %}{{ r.review_request.requested_rev }}{% else %}{{ r.review_request.doc.rev }}{% endif %} + {% for r in review_assignments %}{{ r.reviewer.person.plain_name|ljust:"22" }} {{ r.review_request.deadline|date:"Y-m-d" }} {{ r.review_request.doc.name }}-{% if r.review_request.requested_rev %}{{ r.review_request.requested_rev }}{% else %}{{ r.review_request.doc.rev }}{% endif %} {% endfor %} {% if rotation_list %}Next in the reviewer rotation: @@ -480,13 +480,13 @@ class ReviewTests(TestCase): empty_outbox() email_reviewer_reminder(review_req) self.assertEqual(len(outbox), 1) - self.assertTrue(review_req.doc_id in outbox[0].get_payload(decode=True).decode("utf-8")) + self.assertTrue(review_req.doc.name in outbox[0].get_payload(decode=True).decode("utf-8")) # email secretary empty_outbox() email_secretary_reminder(review_req, secretary_role) self.assertEqual(len(outbox), 1) - self.assertTrue(review_req.doc_id in outbox[0].get_payload(decode=True).decode("utf-8")) + self.assertTrue(review_req.doc.name in outbox[0].get_payload(decode=True).decode("utf-8")) diff --git a/ietf/group/views.py b/ietf/group/views.py index bdfd95d8a..18c407de4 100644 --- a/ietf/group/views.py +++ b/ietf/group/views.py @@ -1372,7 +1372,7 @@ def reviewer_overview(request, acronym, group_type=None): latest_reqs = [] for d in req_data: if d.state in ["assigned", "accepted"] or len(latest_reqs) < MAX_CLOSED_REQS + open_reqs: - latest_reqs.append((d.assignment_pk, d.doc, d.reviewed_rev, d.assigned_time, d.deadline, + latest_reqs.append((d.assignment_pk, d.doc_name, d.reviewed_rev, d.assigned_time, d.deadline, assignment_state_by_slug.get(d.state), int(math.ceil(d.assignment_to_closure_days)) if d.assignment_to_closure_days is not None else None)) if d.state in ["completed", "completed_in_time", "completed_late"]: @@ -1405,7 +1405,7 @@ def manage_review_requests(request, acronym, group_type=None, assignment_status= document_requests = extract_revision_ordered_review_requests_for_documents_and_replaced( ReviewRequest.objects.filter(state__in=("part-completed", "completed"), team=group).prefetch_related("result"), - set(r.doc_id for r in review_requests), + set(r.doc.name for r in review_requests), ) # we need a mutable query dict for resetting upon saving with @@ -1417,7 +1417,7 @@ def manage_review_requests(request, acronym, group_type=None, assignment_status= # add previous requests l = [] - for r in document_requests.get(req.doc_id, []): + for r in document_requests.get(req.doc.name, []): # take all on the latest reviewed rev if l and l[0].reviewed_rev: if r.doc_id == l[0].doc_id and r.reviewed_rev: @@ -1703,7 +1703,7 @@ def change_reviewer_settings(request, acronym, reviewer_email, group_type=None): msg += "{} is currently assigned to review:".format(reviewer_role.person) for r in review_assignments: msg += "\n\n" - msg += "{} (deadline: {})".format(r.review_request.doc_id, r.review_request.deadline.isoformat()) + msg += "{} (deadline: {})".format(r.review_request.doc.name, r.review_request.deadline.isoformat()) else: msg += "{} does not have any assignments currently.".format(reviewer_role.person) diff --git a/ietf/idindex/index.py b/ietf/idindex/index.py index 2846fc17e..d97f9b544 100644 --- a/ietf/idindex/index.py +++ b/ietf/idindex/index.py @@ -22,17 +22,17 @@ def all_id_txt(): # this returns a lot of data so try to be efficient # precalculations - revision_time = dict(NewRevisionDocEvent.objects.filter(type="new_revision", doc__name__startswith="draft-").order_by('time').values_list("doc_id", "time")) + revision_time = dict(NewRevisionDocEvent.objects.filter(type="new_revision", doc__name__startswith="draft-").order_by('time').values_list("doc__name", "time")) def formatted_rev_date(name): t = revision_time.get(name) return t.strftime("%Y-%m-%d") if t else "" rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", - document__states=State.objects.get(type="draft", slug="rfc")).values_list("document_id", "name")) + document__states=State.objects.get(type="draft", slug="rfc")).values_list("document__name", "name")) replacements = dict(RelatedDocument.objects.filter(target__document__states=State.objects.get(type="draft", slug="repl"), - relationship="replaces").values_list("target__document_id", "source")) + relationship="replaces").values_list("target__name", "source__name")) # we need a distinct to prevent the queries below from multiplying the result @@ -66,7 +66,7 @@ def all_id_txt(): # handle the rest - not_in_process = all_ids.exclude(pk__in=[d.name for d in in_iesg_process]) + not_in_process = all_ids.exclude(pk__in=[d.pk for d in in_iesg_process]) for s in State.objects.filter(type="draft").order_by("order"): for name, rev in not_in_process.filter(states=s).values_list("name", "rev"): @@ -110,21 +110,21 @@ def all_id2_txt(): drafts = drafts.prefetch_related("states") rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", - document__states=State.objects.get(type="draft", slug="rfc")).values_list("document_id", "name")) + document__states=State.objects.get(type="draft", slug="rfc")).values_list("document__name", "name")) replacements = dict(RelatedDocument.objects.filter(target__document__states=State.objects.get(type="draft", slug="repl"), - relationship="replaces").values_list("target__document_id", "source")) + relationship="replaces").values_list("target__name", "source__name")) - revision_time = dict(DocEvent.objects.filter(type="new_revision", doc__name__startswith="draft-").order_by('time').values_list("doc_id", "time")) + revision_time = dict(DocEvent.objects.filter(type="new_revision", doc__name__startswith="draft-").order_by('time').values_list("doc__name", "time")) file_types = file_types_for_drafts() authors = {} for a in DocumentAuthor.objects.filter(document__name__startswith="draft-").order_by("order").select_related("email", "person").iterator(): - if a.document_id not in authors: - l = authors[a.document_id] = [] + if a.document.name not in authors: + l = authors[a.document.name] = [] else: - l = authors[a.document_id] + l = authors[a.document.name] if a.email: l.append(u'%s <%s>' % (a.person.plain_name().replace("@", ""), a.email.address.replace(",", ""))) else: @@ -239,8 +239,8 @@ def active_drafts_index_by_group(extra_values=()): docs_dict[d.name]['group_id'] = individual.id # add initial and latest revision time - for time, doc_id in NewRevisionDocEvent.objects.filter(type="new_revision", doc__states=active_state).order_by('-time').values_list("time", "doc_id"): - d = docs_dict.get(doc_id) + for time, doc_name in NewRevisionDocEvent.objects.filter(type="new_revision", doc__states=active_state).order_by('-time').values_list("time", "doc__name"): + d = docs_dict.get(doc_name) if d: if "rev_time" not in d: d["rev_time"] = time @@ -248,7 +248,7 @@ def active_drafts_index_by_group(extra_values=()): # add authors for a in DocumentAuthor.objects.filter(document__states=active_state).order_by("order").select_related("person"): - d = docs_dict.get(a.document_id) + d = docs_dict.get(a.document.name) if d: if "authors" not in d: d["authors"] = [] diff --git a/ietf/iesg/agenda.py b/ietf/iesg/agenda.py index 46a22adf3..78437de81 100644 --- a/ietf/iesg/agenda.py +++ b/ietf/iesg/agenda.py @@ -182,7 +182,7 @@ def fill_in_agenda_docs(date, sections, docs=None): if e and (e.consensus != None): doc.consensus = "Yes" if e.consensus else "No" - doc.review_assignments = review_assignments_for_docs.get(doc.pk, []) + doc.review_assignments = review_assignments_for_docs.get(doc.name, []) elif doc.type_id == "conflrev": doc.conflictdoc = doc.relateddocument_set.get(relationship__slug='conflrev').target.document elif doc.type_id == "charter": diff --git a/ietf/iesg/tests.py b/ietf/iesg/tests.py index 5f80a74ca..16a738512 100644 --- a/ietf/iesg/tests.py +++ b/ietf/iesg/tests.py @@ -493,7 +493,7 @@ class RescheduleOnAgendaTests(TestCase): e.returning_item = True e.save() - form_id = draft.pk + form_id = draft.name url = urlreverse('ietf.iesg.views.agenda_documents') diff --git a/ietf/ietfauth/tests.py b/ietf/ietfauth/tests.py index e1ff2ed50..d8aa71f4c 100644 --- a/ietf/ietfauth/tests.py +++ b/ietf/ietfauth/tests.py @@ -384,7 +384,7 @@ class IetfAuthTests(TestCase): # wish to review r = self.client.post(url, { "action": "add_wish", - 'doc': doc.pk, + 'doc': doc.name, "team": review_req.team_id, }) self.assertEqual(r.status_code, 302) diff --git a/ietf/ipr/migrations/0003_add_ipdocrel_document2_fk.py b/ietf/ipr/migrations/0003_add_ipdocrel_document2_fk.py new file mode 100644 index 000000000..31fd31bcc --- /dev/null +++ b/ietf/ipr/migrations/0003_add_ipdocrel_document2_fk.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 11:58 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0015_1_add_fk_to_document_id'), + ('ipr', '0002_auto_20180225_1207'), + ] + + operations = [ + migrations.AddField( + model_name='iprdocrel', + name='document2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.DocAlias', to_field=b'id'), + ), + migrations.AlterField( + model_name='iprdocrel', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_ipr', to='doc.DocAlias', to_field=b'name'), + ), + ] diff --git a/ietf/ipr/migrations/0004_remove_iprdocrel_document.py b/ietf/ipr/migrations/0004_remove_iprdocrel_document.py new file mode 100644 index 000000000..e75eb43a1 --- /dev/null +++ b/ietf/ipr/migrations/0004_remove_iprdocrel_document.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-20 09:53 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipr', '0003_add_ipdocrel_document2_fk'), + ] + + operations = [ + migrations.RemoveField( + model_name='iprdocrel', + name='document', + ), + ] diff --git a/ietf/ipr/migrations/0005_rename_field_document2.py b/ietf/ipr/migrations/0005_rename_field_document2.py new file mode 100644 index 000000000..2f793cb21 --- /dev/null +++ b/ietf/ipr/migrations/0005_rename_field_document2.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 05:31 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ('ipr', '0004_remove_iprdocrel_document'), + ] + + operations = [ + migrations.RenameField( + model_name='iprdocrel', + old_name='document2', + new_name='document', + ), + ] diff --git a/ietf/ipr/migrations/0006_document_primary_key_cleanup.py b/ietf/ipr/migrations/0006_document_primary_key_cleanup.py new file mode 100644 index 000000000..a691399f0 --- /dev/null +++ b/ietf/ipr/migrations/0006_document_primary_key_cleanup.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-10 03:42 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ipr', '0005_rename_field_document2'), + ] + + operations = [ + migrations.AlterField( + model_name='iprdocrel', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.DocAlias'), + ), + ] diff --git a/ietf/ipr/tests.py b/ietf/ipr/tests.py index 24a4f3fae..fe03a3c28 100644 --- a/ietf/ipr/tests.py +++ b/ietf/ipr/tests.py @@ -260,9 +260,9 @@ class IprTests(TestCase): "ietfer_contact_info": "555-555-0101", "iprdocrel_set-TOTAL_FORMS": 2, "iprdocrel_set-INITIAL_FORMS": 0, - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk, + "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().name, "iprdocrel_set-0-revisions": '00', - "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().pk, + "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().name, "patent_number": "SE12345678901", "patent_inventor": "A. Nonymous", "patent_title": "A method of transfering bits", @@ -303,9 +303,9 @@ class IprTests(TestCase): "ietfer_contact_info": "555-555-0101", "iprdocrel_set-TOTAL_FORMS": 2, "iprdocrel_set-INITIAL_FORMS": 0, - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk, + "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().name, "iprdocrel_set-0-revisions": '00', - "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().pk, + "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().name, "patent_number": "SE12345678901", "patent_inventor": "A. Nonymous", "patent_title": "A method of transfering bits", @@ -351,7 +351,7 @@ class IprTests(TestCase): "holder_legal_name": "Test Legal", "ietfer_contact_info": "555-555-0101", "ietfer_name": "Test Participant", - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk, + "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().name, "iprdocrel_set-0-revisions": '00', "iprdocrel_set-INITIAL_FORMS": 0, "iprdocrel_set-TOTAL_FORMS": 1, @@ -400,9 +400,9 @@ class IprTests(TestCase): "ietfer_contact_info": "555-555-0101", "iprdocrel_set-TOTAL_FORMS": 2, "iprdocrel_set-INITIAL_FORMS": 0, - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk, + "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().name, "iprdocrel_set-0-revisions": '00', - "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().pk, + "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().name, "patent_number": "SE12345678901", "patent_inventor": "A. Nonymous", "patent_title": "A method of transfering bits", @@ -438,7 +438,7 @@ class IprTests(TestCase): "holder_contact_email": "test@holder.com", "iprdocrel_set-TOTAL_FORMS": 1, "iprdocrel_set-INITIAL_FORMS": 0, - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().pk, + "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().name, "iprdocrel_set-0-revisions": '00', "patent_number": "SE12345678901", "patent_inventor": "A. Nonymous", @@ -627,7 +627,7 @@ Subject: test 'iprdocrel_set-TOTAL_FORMS' : 1, 'iprdocrel_set-INITIAL_FORMS' : 1, 'iprdocrel_set-0-id': disclosure.pk, - "iprdocrel_set-0-document": disclosure.docs.first().pk, + "iprdocrel_set-0-document": disclosure.docs.first().name, "iprdocrel_set-0-revisions": disclosure.docs.first().document.rev, 'holder_legal_name': disclosure.holder_legal_name, 'patent_number': patent_dict['Number'], diff --git a/ietf/liaisons/migrations/0003_liaison_document2_fk.py b/ietf/liaisons/migrations/0003_liaison_document2_fk.py new file mode 100644 index 000000000..335389423 --- /dev/null +++ b/ietf/liaisons/migrations/0003_liaison_document2_fk.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 11:58 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0015_1_add_fk_to_document_id'), + ('liaisons', '0002_auto_20180225_1207'), + ] + + operations = [ + migrations.AddField( + model_name='liaisonstatementattachment', + name='document2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AlterField( + model_name='liaisonstatementattachment', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_liaison', to='doc.Document', to_field=b'name'), + ), + ] diff --git a/ietf/liaisons/migrations/0004_remove_liaisonstatementattachment_document.py b/ietf/liaisons/migrations/0004_remove_liaisonstatementattachment_document.py new file mode 100644 index 000000000..c687f0f00 --- /dev/null +++ b/ietf/liaisons/migrations/0004_remove_liaisonstatementattachment_document.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-20 09:53 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('liaisons', '0003_liaison_document2_fk'), + ] + + operations = [ + migrations.RemoveField( + model_name='liaisonstatementattachment', + name='document', + ), + ] diff --git a/ietf/liaisons/migrations/0005_rename_field_document2.py b/ietf/liaisons/migrations/0005_rename_field_document2.py new file mode 100644 index 000000000..df1f7f2b5 --- /dev/null +++ b/ietf/liaisons/migrations/0005_rename_field_document2.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 05:31 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ('liaisons', '0004_remove_liaisonstatementattachment_document'), + ] + + operations = [ + migrations.RenameField( + model_name='liaisonstatementattachment', + old_name='document2', + new_name='document', + ), + ] diff --git a/ietf/liaisons/migrations/0006_document_primary_key_cleanup.py b/ietf/liaisons/migrations/0006_document_primary_key_cleanup.py new file mode 100644 index 000000000..78bcc13a7 --- /dev/null +++ b/ietf/liaisons/migrations/0006_document_primary_key_cleanup.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-10 03:47 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('liaisons', '0005_rename_field_document2'), + ] + + operations = [ + migrations.AlterField( + model_name='liaisonstatementattachment', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + ] diff --git a/ietf/meeting/migrations/0015_sessionpresentation_document2_fk.py b/ietf/meeting/migrations/0015_sessionpresentation_document2_fk.py new file mode 100644 index 000000000..51dca6299 --- /dev/null +++ b/ietf/meeting/migrations/0015_sessionpresentation_document2_fk.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 11:58 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0015_1_add_fk_to_document_id'), + ('meeting', '0014_auto_20190426_0305'), + ] + + operations = [ + migrations.AddField( + model_name='sessionpresentation', + name='document2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AlterField( + model_name='sessionpresentation', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_sesspres', to='doc.Document', to_field=b'name'), + ), + ] diff --git a/ietf/meeting/migrations/0016_remove_sessionpresentation_document.py b/ietf/meeting/migrations/0016_remove_sessionpresentation_document.py new file mode 100644 index 000000000..e0d656bc1 --- /dev/null +++ b/ietf/meeting/migrations/0016_remove_sessionpresentation_document.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 03:57 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0018_remove_old_document_field'), + ('meeting', '0015_sessionpresentation_document2_fk'), + ] + + operations = [ + + # We need to get rid of the current through table uniqueness + # constraint before we can remove the document column: The table + # has "UNIQUE KEY `session_id` (`session_id`,`document_id`)" + migrations.RunSQL( + "ALTER TABLE `meeting_session_materials` DROP INDEX `session_id`;", + "CREATE UNIQUE INDEX `session_id` ON `meeting_session_materials` (`session_id`, `document_id`);" + ), + ## This doesn't work: + # migrations.RemoveIndex( + # model_name='sessionpresentation', + # name='session_id' + # ), + migrations.RemoveField( + model_name='sessionpresentation', + name='document', + ), + ] diff --git a/ietf/meeting/migrations/0017_rename_field_document2.py b/ietf/meeting/migrations/0017_rename_field_document2.py new file mode 100644 index 000000000..9be7d25ea --- /dev/null +++ b/ietf/meeting/migrations/0017_rename_field_document2.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 05:31 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ('meeting', '0016_remove_sessionpresentation_document'), + ] + + operations = [ + migrations.RenameField( + model_name='sessionpresentation', + old_name='document2', + new_name='document', + ), + migrations.AlterUniqueTogether( + name='sessionpresentation', + unique_together=set([('session', 'document')]), + ), + ] diff --git a/ietf/meeting/migrations/0018_document_primary_key_cleanup.py b/ietf/meeting/migrations/0018_document_primary_key_cleanup.py new file mode 100644 index 000000000..0e5275ed9 --- /dev/null +++ b/ietf/meeting/migrations/0018_document_primary_key_cleanup.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-10 03:47 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('meeting', '0017_rename_field_document2'), + ] + + operations = [ + migrations.AlterField( + model_name='sessionpresentation', + name='document', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + ] diff --git a/ietf/meeting/models.py b/ietf/meeting/models.py index ce8b65b86..ec3d8f39e 100644 --- a/ietf/meeting/models.py +++ b/ietf/meeting/models.py @@ -863,6 +863,7 @@ class SessionPresentation(models.Model): class Meta: db_table = 'meeting_session_materials' ordering = ('order',) + unique_together = (('session', 'document'),) def __unicode__(self): return u"%s -> %s-%s" % (self.session, self.document.name, self.rev) diff --git a/ietf/message/migrations/0002_add_message_docs2_m2m.py b/ietf/message/migrations/0002_add_message_docs2_m2m.py new file mode 100644 index 000000000..f5daf17c4 --- /dev/null +++ b/ietf/message/migrations/0002_add_message_docs2_m2m.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 14:23 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('message', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='MessageDocs', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('message', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='message.Message')), + ('document', ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id')), + ], + ), + migrations.AddField( + model_name='message', + name='related_docs2', + field=models.ManyToManyField(blank=True, related_name='messages', through='message.MessageDocs', to='doc.Document'), + ), + ] diff --git a/ietf/message/migrations/0003_set_document_m2m_keys.py b/ietf/message/migrations/0003_set_document_m2m_keys.py new file mode 100644 index 000000000..ffdb5adf7 --- /dev/null +++ b/ietf/message/migrations/0003_set_document_m2m_keys.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 14:27 +from __future__ import unicode_literals + +import sys + +from tqdm import tqdm + +from django.db import migrations + + +def forward(apps, schema_editor): + + Document = apps.get_model('doc','Document') + Message = apps.get_model('message', 'Message') + MessageDocs = apps.get_model('message', 'MessageDocs') + + + # Document id fixup ------------------------------------------------------------ + + objs = Document.objects.in_bulk() + nameid = { o.name: o.id for id, o in objs.iteritems() } + + sys.stderr.write('\n') + + sys.stderr.write(' %s.%s:\n' % (Message.__name__, 'related_docs')) + count = 0 + for m in tqdm(Message.objects.all()): + for d in m.related_docs.all(): + count += 1; + MessageDocs.objects.get_or_create(message=m, document_id=nameid[d.name]) + sys.stderr.write(' %s MessageDocs objects created\n' % (count, )) + +def reverse(apps, schema_editor): + pass + +class Migration(migrations.Migration): + + dependencies = [ + ('message', '0002_add_message_docs2_m2m'), + ('doc', '0014_set_document_docalias_id'), + ] + + operations = [ + migrations.RunPython(forward, reverse), + ] diff --git a/ietf/message/migrations/0004_1_del_docs_m2m_table.py b/ietf/message/migrations/0004_1_del_docs_m2m_table.py new file mode 100644 index 000000000..6bf2fcc5f --- /dev/null +++ b/ietf/message/migrations/0004_1_del_docs_m2m_table.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-22 08:01 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('message', '0003_set_document_m2m_keys'), + ] + + # The implementation of AlterField in Django 1.11 applies + # 'ALTER TABLE
MODIFY ...;' in order to fix foregn keys + # to the altered field, but as it seems does _not_ fix up m2m + # intermediary tables in an equivalent manner, so here we remove and + # then recreate the m2m tables so they will have the appropriate field + # types. + + operations = [ + migrations.RemoveField( + model_name='message', + name='related_docs', + ), + migrations.AddField( + model_name='message', + name='related_docs', + field=models.ManyToManyField(to='doc.Document'), + ), + ] diff --git a/ietf/message/migrations/0004_2_add_docs_m2m_table.py b/ietf/message/migrations/0004_2_add_docs_m2m_table.py new file mode 100644 index 000000000..314cc5d76 --- /dev/null +++ b/ietf/message/migrations/0004_2_add_docs_m2m_table.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-22 08:01 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('message', '0004_1_del_docs_m2m_table'), + ] + + # The implementation of AlterField in Django 1.11 applies + # 'ALTER TABLE
MODIFY ...;' in order to fix foregn keys + # to the altered field, but as it seems does _not_ fix up m2m + # intermediary tables in an equivalent manner, so here we remove and + # then recreate the m2m tables so they will have the appropriate field + # types. + + operations = [ + migrations.RemoveField( + model_name='message', + name='related_docs', + ), + migrations.AddField( + model_name='message', + name='related_docs', + field=models.ManyToManyField(blank=True, to='doc.Document'), + ), + ] diff --git a/ietf/message/migrations/0005_copy_docs_m2m_table.py b/ietf/message/migrations/0005_copy_docs_m2m_table.py new file mode 100644 index 000000000..ac4afcdf3 --- /dev/null +++ b/ietf/message/migrations/0005_copy_docs_m2m_table.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-27 05:56 +from __future__ import unicode_literals + +import sys, time + +from django.db import migrations + + +def timestamp(apps, schema_editor): + sys.stderr.write('\n %s' % time.strftime('%Y-%m-%d %H:%M:%S')) + +class Migration(migrations.Migration): + + dependencies = [ + ('message', '0004_2_add_docs_m2m_table'), + ] + + operations = [ + #migrations.RunPython(forward, reverse), + migrations.RunPython(timestamp, timestamp), + migrations.RunSQL( + "INSERT INTO message_message_related_docs SELECT * FROM message_messagedocs;", + "" + ), + migrations.RunPython(timestamp, timestamp), + ] diff --git a/ietf/message/migrations/0006_remove_docs2_m2m.py b/ietf/message/migrations/0006_remove_docs2_m2m.py new file mode 100644 index 000000000..48ea5f4e6 --- /dev/null +++ b/ietf/message/migrations/0006_remove_docs2_m2m.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-30 03:32 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('message', '0005_copy_docs_m2m_table'), + ] + + operations = [ + migrations.RemoveField( + model_name='messagedocs', + name='document', + ), + migrations.RemoveField( + model_name='messagedocs', + name='message', + ), + migrations.RemoveField( + model_name='message', + name='related_docs2', + ), + migrations.DeleteModel( + name='MessageDocs', + ), + ] diff --git a/ietf/name/fixtures/names.json b/ietf/name/fixtures/names.json index 8af101227..fde50cdd2 100644 --- a/ietf/name/fixtures/names.json +++ b/ietf/name/fixtures/names.json @@ -2678,13 +2678,13 @@ "fields": { "about_page": "ietf.group.views.group_about", "acts_like_wg": false, - "admin_roles": "[\"chair\"]", + "admin_roles": "[\"chair\",\"advisor\"]", "agenda_type": "side", "create_wiki": true, "custom_group_roles": true, "customize_workflow": false, "default_tab": "ietf.group.views.group_about", - "docman_roles": "[]", + "docman_roles": "[\"chair\"]", "groupman_roles": "[\"chair\",\"advisor\"]", "has_chartering_process": false, "has_default_jabber": false, @@ -10934,11 +10934,2435 @@ "model": "name.topicaudiencename", "pk": "nominees" }, + { + "fields": { + "alias": "AD", + "country": "AD" + }, + "model": "stats.countryalias", + "pk": 1 + }, + { + "fields": { + "alias": "AE", + "country": "AE" + }, + "model": "stats.countryalias", + "pk": 2 + }, + { + "fields": { + "alias": "AF", + "country": "AF" + }, + "model": "stats.countryalias", + "pk": 3 + }, + { + "fields": { + "alias": "AG", + "country": "AG" + }, + "model": "stats.countryalias", + "pk": 4 + }, + { + "fields": { + "alias": "AI", + "country": "AI" + }, + "model": "stats.countryalias", + "pk": 5 + }, + { + "fields": { + "alias": "AL", + "country": "AL" + }, + "model": "stats.countryalias", + "pk": 6 + }, + { + "fields": { + "alias": "AM", + "country": "AM" + }, + "model": "stats.countryalias", + "pk": 7 + }, + { + "fields": { + "alias": "AO", + "country": "AO" + }, + "model": "stats.countryalias", + "pk": 8 + }, + { + "fields": { + "alias": "AQ", + "country": "AQ" + }, + "model": "stats.countryalias", + "pk": 9 + }, + { + "fields": { + "alias": "AR", + "country": "AR" + }, + "model": "stats.countryalias", + "pk": 10 + }, + { + "fields": { + "alias": "AS", + "country": "AS" + }, + "model": "stats.countryalias", + "pk": 11 + }, + { + "fields": { + "alias": "AT", + "country": "AT" + }, + "model": "stats.countryalias", + "pk": 12 + }, + { + "fields": { + "alias": "AU", + "country": "AU" + }, + "model": "stats.countryalias", + "pk": 13 + }, + { + "fields": { + "alias": "AW", + "country": "AW" + }, + "model": "stats.countryalias", + "pk": 14 + }, + { + "fields": { + "alias": "AX", + "country": "AX" + }, + "model": "stats.countryalias", + "pk": 15 + }, + { + "fields": { + "alias": "AZ", + "country": "AZ" + }, + "model": "stats.countryalias", + "pk": 16 + }, + { + "fields": { + "alias": "BA", + "country": "BA" + }, + "model": "stats.countryalias", + "pk": 17 + }, + { + "fields": { + "alias": "BB", + "country": "BB" + }, + "model": "stats.countryalias", + "pk": 18 + }, + { + "fields": { + "alias": "BD", + "country": "BD" + }, + "model": "stats.countryalias", + "pk": 19 + }, + { + "fields": { + "alias": "BE", + "country": "BE" + }, + "model": "stats.countryalias", + "pk": 20 + }, + { + "fields": { + "alias": "BF", + "country": "BF" + }, + "model": "stats.countryalias", + "pk": 21 + }, + { + "fields": { + "alias": "BG", + "country": "BG" + }, + "model": "stats.countryalias", + "pk": 22 + }, + { + "fields": { + "alias": "BH", + "country": "BH" + }, + "model": "stats.countryalias", + "pk": 23 + }, + { + "fields": { + "alias": "BI", + "country": "BI" + }, + "model": "stats.countryalias", + "pk": 24 + }, + { + "fields": { + "alias": "BJ", + "country": "BJ" + }, + "model": "stats.countryalias", + "pk": 25 + }, + { + "fields": { + "alias": "BL", + "country": "BL" + }, + "model": "stats.countryalias", + "pk": 26 + }, + { + "fields": { + "alias": "BM", + "country": "BM" + }, + "model": "stats.countryalias", + "pk": 27 + }, + { + "fields": { + "alias": "BN", + "country": "BN" + }, + "model": "stats.countryalias", + "pk": 28 + }, + { + "fields": { + "alias": "BO", + "country": "BO" + }, + "model": "stats.countryalias", + "pk": 29 + }, + { + "fields": { + "alias": "BQ", + "country": "BQ" + }, + "model": "stats.countryalias", + "pk": 30 + }, + { + "fields": { + "alias": "BR", + "country": "BR" + }, + "model": "stats.countryalias", + "pk": 31 + }, + { + "fields": { + "alias": "BS", + "country": "BS" + }, + "model": "stats.countryalias", + "pk": 32 + }, + { + "fields": { + "alias": "BT", + "country": "BT" + }, + "model": "stats.countryalias", + "pk": 33 + }, + { + "fields": { + "alias": "BV", + "country": "BV" + }, + "model": "stats.countryalias", + "pk": 34 + }, + { + "fields": { + "alias": "BW", + "country": "BW" + }, + "model": "stats.countryalias", + "pk": 35 + }, + { + "fields": { + "alias": "BY", + "country": "BY" + }, + "model": "stats.countryalias", + "pk": 36 + }, + { + "fields": { + "alias": "BZ", + "country": "BZ" + }, + "model": "stats.countryalias", + "pk": 37 + }, + { + "fields": { + "alias": "CA", + "country": "CA" + }, + "model": "stats.countryalias", + "pk": 38 + }, + { + "fields": { + "alias": "CC", + "country": "CC" + }, + "model": "stats.countryalias", + "pk": 39 + }, + { + "fields": { + "alias": "CD", + "country": "CD" + }, + "model": "stats.countryalias", + "pk": 40 + }, + { + "fields": { + "alias": "CF", + "country": "CF" + }, + "model": "stats.countryalias", + "pk": 41 + }, + { + "fields": { + "alias": "CG", + "country": "CG" + }, + "model": "stats.countryalias", + "pk": 42 + }, + { + "fields": { + "alias": "CH", + "country": "CH" + }, + "model": "stats.countryalias", + "pk": 43 + }, + { + "fields": { + "alias": "CI", + "country": "CI" + }, + "model": "stats.countryalias", + "pk": 44 + }, + { + "fields": { + "alias": "CK", + "country": "CK" + }, + "model": "stats.countryalias", + "pk": 45 + }, + { + "fields": { + "alias": "CL", + "country": "CL" + }, + "model": "stats.countryalias", + "pk": 46 + }, + { + "fields": { + "alias": "CM", + "country": "CM" + }, + "model": "stats.countryalias", + "pk": 47 + }, + { + "fields": { + "alias": "CN", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 48 + }, + { + "fields": { + "alias": "CO", + "country": "CO" + }, + "model": "stats.countryalias", + "pk": 49 + }, + { + "fields": { + "alias": "CR", + "country": "CR" + }, + "model": "stats.countryalias", + "pk": 50 + }, + { + "fields": { + "alias": "CU", + "country": "CU" + }, + "model": "stats.countryalias", + "pk": 51 + }, + { + "fields": { + "alias": "CV", + "country": "CV" + }, + "model": "stats.countryalias", + "pk": 52 + }, + { + "fields": { + "alias": "CW", + "country": "CW" + }, + "model": "stats.countryalias", + "pk": 53 + }, + { + "fields": { + "alias": "CX", + "country": "CX" + }, + "model": "stats.countryalias", + "pk": 54 + }, + { + "fields": { + "alias": "CY", + "country": "CY" + }, + "model": "stats.countryalias", + "pk": 55 + }, + { + "fields": { + "alias": "CZ", + "country": "CZ" + }, + "model": "stats.countryalias", + "pk": 56 + }, + { + "fields": { + "alias": "DE", + "country": "DE" + }, + "model": "stats.countryalias", + "pk": 57 + }, + { + "fields": { + "alias": "DJ", + "country": "DJ" + }, + "model": "stats.countryalias", + "pk": 58 + }, + { + "fields": { + "alias": "DK", + "country": "DK" + }, + "model": "stats.countryalias", + "pk": 59 + }, + { + "fields": { + "alias": "DM", + "country": "DM" + }, + "model": "stats.countryalias", + "pk": 60 + }, + { + "fields": { + "alias": "DO", + "country": "DO" + }, + "model": "stats.countryalias", + "pk": 61 + }, + { + "fields": { + "alias": "DZ", + "country": "DZ" + }, + "model": "stats.countryalias", + "pk": 62 + }, + { + "fields": { + "alias": "EC", + "country": "EC" + }, + "model": "stats.countryalias", + "pk": 63 + }, + { + "fields": { + "alias": "EE", + "country": "EE" + }, + "model": "stats.countryalias", + "pk": 64 + }, + { + "fields": { + "alias": "EG", + "country": "EG" + }, + "model": "stats.countryalias", + "pk": 65 + }, + { + "fields": { + "alias": "EH", + "country": "EH" + }, + "model": "stats.countryalias", + "pk": 66 + }, + { + "fields": { + "alias": "ER", + "country": "ER" + }, + "model": "stats.countryalias", + "pk": 67 + }, + { + "fields": { + "alias": "ES", + "country": "ES" + }, + "model": "stats.countryalias", + "pk": 68 + }, + { + "fields": { + "alias": "ET", + "country": "ET" + }, + "model": "stats.countryalias", + "pk": 69 + }, + { + "fields": { + "alias": "FI", + "country": "FI" + }, + "model": "stats.countryalias", + "pk": 70 + }, + { + "fields": { + "alias": "FJ", + "country": "FJ" + }, + "model": "stats.countryalias", + "pk": 71 + }, + { + "fields": { + "alias": "FK", + "country": "FK" + }, + "model": "stats.countryalias", + "pk": 72 + }, + { + "fields": { + "alias": "FM", + "country": "FM" + }, + "model": "stats.countryalias", + "pk": 73 + }, + { + "fields": { + "alias": "FO", + "country": "FO" + }, + "model": "stats.countryalias", + "pk": 74 + }, + { + "fields": { + "alias": "FR", + "country": "FR" + }, + "model": "stats.countryalias", + "pk": 75 + }, + { + "fields": { + "alias": "GA", + "country": "GA" + }, + "model": "stats.countryalias", + "pk": 76 + }, + { + "fields": { + "alias": "GB", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 77 + }, + { + "fields": { + "alias": "GD", + "country": "GD" + }, + "model": "stats.countryalias", + "pk": 78 + }, + { + "fields": { + "alias": "GE", + "country": "GE" + }, + "model": "stats.countryalias", + "pk": 79 + }, + { + "fields": { + "alias": "GF", + "country": "GF" + }, + "model": "stats.countryalias", + "pk": 80 + }, + { + "fields": { + "alias": "GG", + "country": "GG" + }, + "model": "stats.countryalias", + "pk": 81 + }, + { + "fields": { + "alias": "GH", + "country": "GH" + }, + "model": "stats.countryalias", + "pk": 82 + }, + { + "fields": { + "alias": "GI", + "country": "GI" + }, + "model": "stats.countryalias", + "pk": 83 + }, + { + "fields": { + "alias": "GL", + "country": "GL" + }, + "model": "stats.countryalias", + "pk": 84 + }, + { + "fields": { + "alias": "GM", + "country": "GM" + }, + "model": "stats.countryalias", + "pk": 85 + }, + { + "fields": { + "alias": "GN", + "country": "GN" + }, + "model": "stats.countryalias", + "pk": 86 + }, + { + "fields": { + "alias": "GP", + "country": "GP" + }, + "model": "stats.countryalias", + "pk": 87 + }, + { + "fields": { + "alias": "GQ", + "country": "GQ" + }, + "model": "stats.countryalias", + "pk": 88 + }, + { + "fields": { + "alias": "GR", + "country": "GR" + }, + "model": "stats.countryalias", + "pk": 89 + }, + { + "fields": { + "alias": "GS", + "country": "GS" + }, + "model": "stats.countryalias", + "pk": 90 + }, + { + "fields": { + "alias": "GT", + "country": "GT" + }, + "model": "stats.countryalias", + "pk": 91 + }, + { + "fields": { + "alias": "GU", + "country": "GU" + }, + "model": "stats.countryalias", + "pk": 92 + }, + { + "fields": { + "alias": "GW", + "country": "GW" + }, + "model": "stats.countryalias", + "pk": 93 + }, + { + "fields": { + "alias": "GY", + "country": "GY" + }, + "model": "stats.countryalias", + "pk": 94 + }, + { + "fields": { + "alias": "HK", + "country": "HK" + }, + "model": "stats.countryalias", + "pk": 95 + }, + { + "fields": { + "alias": "HM", + "country": "HM" + }, + "model": "stats.countryalias", + "pk": 96 + }, + { + "fields": { + "alias": "HN", + "country": "HN" + }, + "model": "stats.countryalias", + "pk": 97 + }, + { + "fields": { + "alias": "HR", + "country": "HR" + }, + "model": "stats.countryalias", + "pk": 98 + }, + { + "fields": { + "alias": "HT", + "country": "HT" + }, + "model": "stats.countryalias", + "pk": 99 + }, + { + "fields": { + "alias": "HU", + "country": "HU" + }, + "model": "stats.countryalias", + "pk": 100 + }, + { + "fields": { + "alias": "ID", + "country": "ID" + }, + "model": "stats.countryalias", + "pk": 101 + }, + { + "fields": { + "alias": "IE", + "country": "IE" + }, + "model": "stats.countryalias", + "pk": 102 + }, + { + "fields": { + "alias": "IL", + "country": "IL" + }, + "model": "stats.countryalias", + "pk": 103 + }, + { + "fields": { + "alias": "IM", + "country": "IM" + }, + "model": "stats.countryalias", + "pk": 104 + }, + { + "fields": { + "alias": "IN", + "country": "IN" + }, + "model": "stats.countryalias", + "pk": 105 + }, + { + "fields": { + "alias": "IO", + "country": "IO" + }, + "model": "stats.countryalias", + "pk": 106 + }, + { + "fields": { + "alias": "IQ", + "country": "IQ" + }, + "model": "stats.countryalias", + "pk": 107 + }, + { + "fields": { + "alias": "IR", + "country": "IR" + }, + "model": "stats.countryalias", + "pk": 108 + }, + { + "fields": { + "alias": "IS", + "country": "IS" + }, + "model": "stats.countryalias", + "pk": 109 + }, + { + "fields": { + "alias": "IT", + "country": "IT" + }, + "model": "stats.countryalias", + "pk": 110 + }, + { + "fields": { + "alias": "JE", + "country": "JE" + }, + "model": "stats.countryalias", + "pk": 111 + }, + { + "fields": { + "alias": "JM", + "country": "JM" + }, + "model": "stats.countryalias", + "pk": 112 + }, + { + "fields": { + "alias": "JO", + "country": "JO" + }, + "model": "stats.countryalias", + "pk": 113 + }, + { + "fields": { + "alias": "JP", + "country": "JP" + }, + "model": "stats.countryalias", + "pk": 114 + }, + { + "fields": { + "alias": "KE", + "country": "KE" + }, + "model": "stats.countryalias", + "pk": 115 + }, + { + "fields": { + "alias": "KG", + "country": "KG" + }, + "model": "stats.countryalias", + "pk": 116 + }, + { + "fields": { + "alias": "KH", + "country": "KH" + }, + "model": "stats.countryalias", + "pk": 117 + }, + { + "fields": { + "alias": "KI", + "country": "KI" + }, + "model": "stats.countryalias", + "pk": 118 + }, + { + "fields": { + "alias": "KM", + "country": "KM" + }, + "model": "stats.countryalias", + "pk": 119 + }, + { + "fields": { + "alias": "KN", + "country": "KN" + }, + "model": "stats.countryalias", + "pk": 120 + }, + { + "fields": { + "alias": "KP", + "country": "KP" + }, + "model": "stats.countryalias", + "pk": 121 + }, + { + "fields": { + "alias": "KR", + "country": "KR" + }, + "model": "stats.countryalias", + "pk": 122 + }, + { + "fields": { + "alias": "KW", + "country": "KW" + }, + "model": "stats.countryalias", + "pk": 123 + }, + { + "fields": { + "alias": "KY", + "country": "KY" + }, + "model": "stats.countryalias", + "pk": 124 + }, + { + "fields": { + "alias": "KZ", + "country": "KZ" + }, + "model": "stats.countryalias", + "pk": 125 + }, + { + "fields": { + "alias": "LA", + "country": "LA" + }, + "model": "stats.countryalias", + "pk": 126 + }, + { + "fields": { + "alias": "LB", + "country": "LB" + }, + "model": "stats.countryalias", + "pk": 127 + }, + { + "fields": { + "alias": "LC", + "country": "LC" + }, + "model": "stats.countryalias", + "pk": 128 + }, + { + "fields": { + "alias": "LI", + "country": "LI" + }, + "model": "stats.countryalias", + "pk": 129 + }, + { + "fields": { + "alias": "LK", + "country": "LK" + }, + "model": "stats.countryalias", + "pk": 130 + }, + { + "fields": { + "alias": "LR", + "country": "LR" + }, + "model": "stats.countryalias", + "pk": 131 + }, + { + "fields": { + "alias": "LS", + "country": "LS" + }, + "model": "stats.countryalias", + "pk": 132 + }, + { + "fields": { + "alias": "LT", + "country": "LT" + }, + "model": "stats.countryalias", + "pk": 133 + }, + { + "fields": { + "alias": "LU", + "country": "LU" + }, + "model": "stats.countryalias", + "pk": 134 + }, + { + "fields": { + "alias": "LV", + "country": "LV" + }, + "model": "stats.countryalias", + "pk": 135 + }, + { + "fields": { + "alias": "LY", + "country": "LY" + }, + "model": "stats.countryalias", + "pk": 136 + }, + { + "fields": { + "alias": "MA", + "country": "MA" + }, + "model": "stats.countryalias", + "pk": 137 + }, + { + "fields": { + "alias": "MC", + "country": "MC" + }, + "model": "stats.countryalias", + "pk": 138 + }, + { + "fields": { + "alias": "MD", + "country": "MD" + }, + "model": "stats.countryalias", + "pk": 139 + }, + { + "fields": { + "alias": "ME", + "country": "ME" + }, + "model": "stats.countryalias", + "pk": 140 + }, + { + "fields": { + "alias": "MF", + "country": "MF" + }, + "model": "stats.countryalias", + "pk": 141 + }, + { + "fields": { + "alias": "MG", + "country": "MG" + }, + "model": "stats.countryalias", + "pk": 142 + }, + { + "fields": { + "alias": "MH", + "country": "MH" + }, + "model": "stats.countryalias", + "pk": 143 + }, + { + "fields": { + "alias": "MK", + "country": "MK" + }, + "model": "stats.countryalias", + "pk": 144 + }, + { + "fields": { + "alias": "ML", + "country": "ML" + }, + "model": "stats.countryalias", + "pk": 145 + }, + { + "fields": { + "alias": "MM", + "country": "MM" + }, + "model": "stats.countryalias", + "pk": 146 + }, + { + "fields": { + "alias": "MN", + "country": "MN" + }, + "model": "stats.countryalias", + "pk": 147 + }, + { + "fields": { + "alias": "MO", + "country": "MO" + }, + "model": "stats.countryalias", + "pk": 148 + }, + { + "fields": { + "alias": "MP", + "country": "MP" + }, + "model": "stats.countryalias", + "pk": 149 + }, + { + "fields": { + "alias": "MQ", + "country": "MQ" + }, + "model": "stats.countryalias", + "pk": 150 + }, + { + "fields": { + "alias": "MR", + "country": "MR" + }, + "model": "stats.countryalias", + "pk": 151 + }, + { + "fields": { + "alias": "MS", + "country": "MS" + }, + "model": "stats.countryalias", + "pk": 152 + }, + { + "fields": { + "alias": "MT", + "country": "MT" + }, + "model": "stats.countryalias", + "pk": 153 + }, + { + "fields": { + "alias": "MU", + "country": "MU" + }, + "model": "stats.countryalias", + "pk": 154 + }, + { + "fields": { + "alias": "MV", + "country": "MV" + }, + "model": "stats.countryalias", + "pk": 155 + }, + { + "fields": { + "alias": "MW", + "country": "MW" + }, + "model": "stats.countryalias", + "pk": 156 + }, + { + "fields": { + "alias": "MX", + "country": "MX" + }, + "model": "stats.countryalias", + "pk": 157 + }, + { + "fields": { + "alias": "MY", + "country": "MY" + }, + "model": "stats.countryalias", + "pk": 158 + }, + { + "fields": { + "alias": "MZ", + "country": "MZ" + }, + "model": "stats.countryalias", + "pk": 159 + }, + { + "fields": { + "alias": "NA", + "country": "NA" + }, + "model": "stats.countryalias", + "pk": 160 + }, + { + "fields": { + "alias": "NC", + "country": "NC" + }, + "model": "stats.countryalias", + "pk": 161 + }, + { + "fields": { + "alias": "NE", + "country": "NE" + }, + "model": "stats.countryalias", + "pk": 162 + }, + { + "fields": { + "alias": "NF", + "country": "NF" + }, + "model": "stats.countryalias", + "pk": 163 + }, + { + "fields": { + "alias": "NG", + "country": "NG" + }, + "model": "stats.countryalias", + "pk": 164 + }, + { + "fields": { + "alias": "NI", + "country": "NI" + }, + "model": "stats.countryalias", + "pk": 165 + }, + { + "fields": { + "alias": "NL", + "country": "NL" + }, + "model": "stats.countryalias", + "pk": 166 + }, + { + "fields": { + "alias": "NO", + "country": "NO" + }, + "model": "stats.countryalias", + "pk": 167 + }, + { + "fields": { + "alias": "NP", + "country": "NP" + }, + "model": "stats.countryalias", + "pk": 168 + }, + { + "fields": { + "alias": "NR", + "country": "NR" + }, + "model": "stats.countryalias", + "pk": 169 + }, + { + "fields": { + "alias": "NU", + "country": "NU" + }, + "model": "stats.countryalias", + "pk": 170 + }, + { + "fields": { + "alias": "NZ", + "country": "NZ" + }, + "model": "stats.countryalias", + "pk": 171 + }, + { + "fields": { + "alias": "OM", + "country": "OM" + }, + "model": "stats.countryalias", + "pk": 172 + }, + { + "fields": { + "alias": "PA", + "country": "PA" + }, + "model": "stats.countryalias", + "pk": 173 + }, + { + "fields": { + "alias": "PE", + "country": "PE" + }, + "model": "stats.countryalias", + "pk": 174 + }, + { + "fields": { + "alias": "PF", + "country": "PF" + }, + "model": "stats.countryalias", + "pk": 175 + }, + { + "fields": { + "alias": "PG", + "country": "PG" + }, + "model": "stats.countryalias", + "pk": 176 + }, + { + "fields": { + "alias": "PH", + "country": "PH" + }, + "model": "stats.countryalias", + "pk": 177 + }, + { + "fields": { + "alias": "PK", + "country": "PK" + }, + "model": "stats.countryalias", + "pk": 178 + }, + { + "fields": { + "alias": "PL", + "country": "PL" + }, + "model": "stats.countryalias", + "pk": 179 + }, + { + "fields": { + "alias": "PM", + "country": "PM" + }, + "model": "stats.countryalias", + "pk": 180 + }, + { + "fields": { + "alias": "PN", + "country": "PN" + }, + "model": "stats.countryalias", + "pk": 181 + }, + { + "fields": { + "alias": "PR", + "country": "PR" + }, + "model": "stats.countryalias", + "pk": 182 + }, + { + "fields": { + "alias": "PS", + "country": "PS" + }, + "model": "stats.countryalias", + "pk": 183 + }, + { + "fields": { + "alias": "PT", + "country": "PT" + }, + "model": "stats.countryalias", + "pk": 184 + }, + { + "fields": { + "alias": "PW", + "country": "PW" + }, + "model": "stats.countryalias", + "pk": 185 + }, + { + "fields": { + "alias": "PY", + "country": "PY" + }, + "model": "stats.countryalias", + "pk": 186 + }, + { + "fields": { + "alias": "QA", + "country": "QA" + }, + "model": "stats.countryalias", + "pk": 187 + }, + { + "fields": { + "alias": "RE", + "country": "RE" + }, + "model": "stats.countryalias", + "pk": 188 + }, + { + "fields": { + "alias": "RO", + "country": "RO" + }, + "model": "stats.countryalias", + "pk": 189 + }, + { + "fields": { + "alias": "RS", + "country": "RS" + }, + "model": "stats.countryalias", + "pk": 190 + }, + { + "fields": { + "alias": "RU", + "country": "RU" + }, + "model": "stats.countryalias", + "pk": 191 + }, + { + "fields": { + "alias": "RW", + "country": "RW" + }, + "model": "stats.countryalias", + "pk": 192 + }, + { + "fields": { + "alias": "SA", + "country": "SA" + }, + "model": "stats.countryalias", + "pk": 193 + }, + { + "fields": { + "alias": "SB", + "country": "SB" + }, + "model": "stats.countryalias", + "pk": 194 + }, + { + "fields": { + "alias": "SC", + "country": "SC" + }, + "model": "stats.countryalias", + "pk": 195 + }, + { + "fields": { + "alias": "SD", + "country": "SD" + }, + "model": "stats.countryalias", + "pk": 196 + }, + { + "fields": { + "alias": "SE", + "country": "SE" + }, + "model": "stats.countryalias", + "pk": 197 + }, + { + "fields": { + "alias": "SG", + "country": "SG" + }, + "model": "stats.countryalias", + "pk": 198 + }, + { + "fields": { + "alias": "SH", + "country": "SH" + }, + "model": "stats.countryalias", + "pk": 199 + }, + { + "fields": { + "alias": "SI", + "country": "SI" + }, + "model": "stats.countryalias", + "pk": 200 + }, + { + "fields": { + "alias": "SJ", + "country": "SJ" + }, + "model": "stats.countryalias", + "pk": 201 + }, + { + "fields": { + "alias": "SK", + "country": "SK" + }, + "model": "stats.countryalias", + "pk": 202 + }, + { + "fields": { + "alias": "SL", + "country": "SL" + }, + "model": "stats.countryalias", + "pk": 203 + }, + { + "fields": { + "alias": "SM", + "country": "SM" + }, + "model": "stats.countryalias", + "pk": 204 + }, + { + "fields": { + "alias": "SN", + "country": "SN" + }, + "model": "stats.countryalias", + "pk": 205 + }, + { + "fields": { + "alias": "SO", + "country": "SO" + }, + "model": "stats.countryalias", + "pk": 206 + }, + { + "fields": { + "alias": "SR", + "country": "SR" + }, + "model": "stats.countryalias", + "pk": 207 + }, + { + "fields": { + "alias": "SS", + "country": "SS" + }, + "model": "stats.countryalias", + "pk": 208 + }, + { + "fields": { + "alias": "ST", + "country": "ST" + }, + "model": "stats.countryalias", + "pk": 209 + }, + { + "fields": { + "alias": "SV", + "country": "SV" + }, + "model": "stats.countryalias", + "pk": 210 + }, + { + "fields": { + "alias": "SX", + "country": "SX" + }, + "model": "stats.countryalias", + "pk": 211 + }, + { + "fields": { + "alias": "SY", + "country": "SY" + }, + "model": "stats.countryalias", + "pk": 212 + }, + { + "fields": { + "alias": "SZ", + "country": "SZ" + }, + "model": "stats.countryalias", + "pk": 213 + }, + { + "fields": { + "alias": "TC", + "country": "TC" + }, + "model": "stats.countryalias", + "pk": 214 + }, + { + "fields": { + "alias": "TD", + "country": "TD" + }, + "model": "stats.countryalias", + "pk": 215 + }, + { + "fields": { + "alias": "TF", + "country": "TF" + }, + "model": "stats.countryalias", + "pk": 216 + }, + { + "fields": { + "alias": "TG", + "country": "TG" + }, + "model": "stats.countryalias", + "pk": 217 + }, + { + "fields": { + "alias": "TH", + "country": "TH" + }, + "model": "stats.countryalias", + "pk": 218 + }, + { + "fields": { + "alias": "TJ", + "country": "TJ" + }, + "model": "stats.countryalias", + "pk": 219 + }, + { + "fields": { + "alias": "TK", + "country": "TK" + }, + "model": "stats.countryalias", + "pk": 220 + }, + { + "fields": { + "alias": "TL", + "country": "TL" + }, + "model": "stats.countryalias", + "pk": 221 + }, + { + "fields": { + "alias": "TM", + "country": "TM" + }, + "model": "stats.countryalias", + "pk": 222 + }, + { + "fields": { + "alias": "TN", + "country": "TN" + }, + "model": "stats.countryalias", + "pk": 223 + }, + { + "fields": { + "alias": "TO", + "country": "TO" + }, + "model": "stats.countryalias", + "pk": 224 + }, + { + "fields": { + "alias": "TR", + "country": "TR" + }, + "model": "stats.countryalias", + "pk": 225 + }, + { + "fields": { + "alias": "TT", + "country": "TT" + }, + "model": "stats.countryalias", + "pk": 226 + }, + { + "fields": { + "alias": "TV", + "country": "TV" + }, + "model": "stats.countryalias", + "pk": 227 + }, + { + "fields": { + "alias": "TW", + "country": "TW" + }, + "model": "stats.countryalias", + "pk": 228 + }, + { + "fields": { + "alias": "TZ", + "country": "TZ" + }, + "model": "stats.countryalias", + "pk": 229 + }, + { + "fields": { + "alias": "UA", + "country": "UA" + }, + "model": "stats.countryalias", + "pk": 230 + }, + { + "fields": { + "alias": "UG", + "country": "UG" + }, + "model": "stats.countryalias", + "pk": 231 + }, + { + "fields": { + "alias": "UM", + "country": "UM" + }, + "model": "stats.countryalias", + "pk": 232 + }, + { + "fields": { + "alias": "US", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 233 + }, + { + "fields": { + "alias": "UY", + "country": "UY" + }, + "model": "stats.countryalias", + "pk": 234 + }, + { + "fields": { + "alias": "UZ", + "country": "UZ" + }, + "model": "stats.countryalias", + "pk": 235 + }, + { + "fields": { + "alias": "VA", + "country": "VA" + }, + "model": "stats.countryalias", + "pk": 236 + }, + { + "fields": { + "alias": "VC", + "country": "VC" + }, + "model": "stats.countryalias", + "pk": 237 + }, + { + "fields": { + "alias": "VE", + "country": "VE" + }, + "model": "stats.countryalias", + "pk": 238 + }, + { + "fields": { + "alias": "VG", + "country": "VG" + }, + "model": "stats.countryalias", + "pk": 239 + }, + { + "fields": { + "alias": "VI", + "country": "VI" + }, + "model": "stats.countryalias", + "pk": 240 + }, + { + "fields": { + "alias": "VN", + "country": "VN" + }, + "model": "stats.countryalias", + "pk": 241 + }, + { + "fields": { + "alias": "VU", + "country": "VU" + }, + "model": "stats.countryalias", + "pk": 242 + }, + { + "fields": { + "alias": "WF", + "country": "WF" + }, + "model": "stats.countryalias", + "pk": 243 + }, + { + "fields": { + "alias": "WS", + "country": "WS" + }, + "model": "stats.countryalias", + "pk": 244 + }, + { + "fields": { + "alias": "YE", + "country": "YE" + }, + "model": "stats.countryalias", + "pk": 245 + }, + { + "fields": { + "alias": "YT", + "country": "YT" + }, + "model": "stats.countryalias", + "pk": 246 + }, + { + "fields": { + "alias": "ZA", + "country": "ZA" + }, + "model": "stats.countryalias", + "pk": 247 + }, + { + "fields": { + "alias": "ZM", + "country": "ZM" + }, + "model": "stats.countryalias", + "pk": 248 + }, + { + "fields": { + "alias": "ZW", + "country": "ZW" + }, + "model": "stats.countryalias", + "pk": 249 + }, + { + "fields": { + "alias": "russian federation", + "country": "RU" + }, + "model": "stats.countryalias", + "pk": 250 + }, + { + "fields": { + "alias": "p. r. china", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 251 + }, + { + "fields": { + "alias": "p.r. china", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 252 + }, + { + "fields": { + "alias": "p.r.china", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 253 + }, + { + "fields": { + "alias": "p.r china", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 254 + }, + { + "fields": { + "alias": "p.r. of china", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 255 + }, + { + "fields": { + "alias": "PRC", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 256 + }, + { + "fields": { + "alias": "P.R.C", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 257 + }, + { + "fields": { + "alias": "P.R.C.", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 258 + }, + { + "fields": { + "alias": "beijing", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 259 + }, + { + "fields": { + "alias": "shenzhen", + "country": "CN" + }, + "model": "stats.countryalias", + "pk": 260 + }, + { + "fields": { + "alias": "R.O.C.", + "country": "TW" + }, + "model": "stats.countryalias", + "pk": 261 + }, + { + "fields": { + "alias": "usa", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 262 + }, + { + "fields": { + "alias": "UAS", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 263 + }, + { + "fields": { + "alias": "USA.", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 264 + }, + { + "fields": { + "alias": "u.s.a.", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 265 + }, + { + "fields": { + "alias": "u. s. a.", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 266 + }, + { + "fields": { + "alias": "u.s.a", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 267 + }, + { + "fields": { + "alias": "u.s.", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 268 + }, + { + "fields": { + "alias": "U.S", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 269 + }, + { + "fields": { + "alias": "US of A", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 270 + }, + { + "fields": { + "alias": "united sates", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 271 + }, + { + "fields": { + "alias": "united state", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 272 + }, + { + "fields": { + "alias": "united states", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 273 + }, + { + "fields": { + "alias": "unites states", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 274 + }, + { + "fields": { + "alias": "texas", + "country": "US" + }, + "model": "stats.countryalias", + "pk": 275 + }, + { + "fields": { + "alias": "UK", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 276 + }, + { + "fields": { + "alias": "united kingcom", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 277 + }, + { + "fields": { + "alias": "great britain", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 278 + }, + { + "fields": { + "alias": "england", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 279 + }, + { + "fields": { + "alias": "U.K.", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 280 + }, + { + "fields": { + "alias": "U.K", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 281 + }, + { + "fields": { + "alias": "scotland", + "country": "GB" + }, + "model": "stats.countryalias", + "pk": 282 + }, + { + "fields": { + "alias": "republic of korea", + "country": "KR" + }, + "model": "stats.countryalias", + "pk": 283 + }, + { + "fields": { + "alias": "korea", + "country": "KR" + }, + "model": "stats.countryalias", + "pk": 284 + }, + { + "fields": { + "alias": "korea rep", + "country": "KR" + }, + "model": "stats.countryalias", + "pk": 285 + }, + { + "fields": { + "alias": "korea (the republic of)", + "country": "KR" + }, + "model": "stats.countryalias", + "pk": 286 + }, + { + "fields": { + "alias": "the netherlands", + "country": "NL" + }, + "model": "stats.countryalias", + "pk": 287 + }, + { + "fields": { + "alias": "netherland", + "country": "NL" + }, + "model": "stats.countryalias", + "pk": 288 + }, + { + "fields": { + "alias": "danmark", + "country": "DK" + }, + "model": "stats.countryalias", + "pk": 289 + }, + { + "fields": { + "alias": "sweeden", + "country": "SE" + }, + "model": "stats.countryalias", + "pk": 290 + }, + { + "fields": { + "alias": "swede", + "country": "SE" + }, + "model": "stats.countryalias", + "pk": 291 + }, + { + "fields": { + "alias": "belgique", + "country": "BE" + }, + "model": "stats.countryalias", + "pk": 292 + }, + { + "fields": { + "alias": "madrid", + "country": "ES" + }, + "model": "stats.countryalias", + "pk": 293 + }, + { + "fields": { + "alias": "espana", + "country": "ES" + }, + "model": "stats.countryalias", + "pk": 294 + }, + { + "fields": { + "alias": "hellas", + "country": "GR" + }, + "model": "stats.countryalias", + "pk": 295 + }, + { + "fields": { + "alias": "gemany", + "country": "DE" + }, + "model": "stats.countryalias", + "pk": 296 + }, + { + "fields": { + "alias": "deutschland", + "country": "DE" + }, + "model": "stats.countryalias", + "pk": 297 + }, + { + "fields": { + "alias": "italia", + "country": "IT" + }, + "model": "stats.countryalias", + "pk": 298 + }, + { + "fields": { + "alias": "isreal", + "country": "IL" + }, + "model": "stats.countryalias", + "pk": 299 + }, + { + "fields": { + "alias": "tel aviv", + "country": "IL" + }, + "model": "stats.countryalias", + "pk": 300 + }, + { + "fields": { + "alias": "UAE", + "country": "AE" + }, + "model": "stats.countryalias", + "pk": 301 + }, + { + "fields": { + "alias": "grand-duchy of luxembourg", + "country": "LU" + }, + "model": "stats.countryalias", + "pk": 302 + }, + { + "fields": { + "alias": "brasil", + "country": "BR" + }, + "model": "stats.countryalias", + "pk": 303 + }, { "fields": { "command": "xym", "switch": "--version", - "time": "2019-04-28T00:08:08.288", + "time": "2019-06-05T00:08:14.315", "used": true, "version": "xym 0.4" }, @@ -10949,7 +13373,7 @@ "fields": { "command": "pyang", "switch": "--version", - "time": "2019-04-28T00:08:09.335", + "time": "2019-06-05T00:08:15.692", "used": true, "version": "pyang 1.7.8" }, @@ -10960,7 +13384,7 @@ "fields": { "command": "yanglint", "switch": "--version", - "time": "2019-04-28T00:08:09.623", + "time": "2019-06-05T00:08:15.932", "used": true, "version": "yanglint 0.14.80" }, @@ -10971,7 +13395,7 @@ "fields": { "command": "xml2rfc", "switch": "--version", - "time": "2019-04-28T00:08:11.596", + "time": "2019-06-05T00:08:18.757", "used": true, "version": "xml2rfc 2.22.3" }, diff --git a/ietf/review/migrations/0011_review_document2_fk.py b/ietf/review/migrations/0011_review_document2_fk.py new file mode 100644 index 000000000..7e6a9d4f2 --- /dev/null +++ b/ietf/review/migrations/0011_review_document2_fk.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 11:58 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0015_1_add_fk_to_document_id'), + ('review', '0010_populate_review_assignments'), + ] + + operations = [ + migrations.AddField( + model_name='reviewrequest', + name='doc2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reviewrequest_set', to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='reviewwish', + name='doc2', + field=ietf.utils.models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AddField( + model_name='reviewrequest', + name='unused_review2', + field=ietf.utils.models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='id'), + ), + migrations.AddField( + model_name='reviewassignment', + name='review2', + field=ietf.utils.models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field='id'), + ), + migrations.AlterField( + model_name='reviewrequest', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_revreq', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='reviewwish', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='old_revwish', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='reviewrequest', + name='unused_review', + field=ietf.utils.models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='old_unused_review', to='doc.Document', to_field=b'name'), + ), + migrations.AlterField( + model_name='reviewassignment', + name='review', + field=ietf.utils.models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='old_reviewassignment', to='doc.Document', to_field=b'name'), + ), + ] diff --git a/ietf/review/migrations/0012_remove_old_document_field.py b/ietf/review/migrations/0012_remove_old_document_field.py new file mode 100644 index 000000000..eea4899dd --- /dev/null +++ b/ietf/review/migrations/0012_remove_old_document_field.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-20 09:53 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('review', '0011_review_document2_fk'), + ] + + operations = [ + migrations.RemoveField( + model_name='reviewrequest', + name='doc', + ), + migrations.RemoveField( + model_name='reviewrequest', + name='unused_reviewer', + ), + migrations.RemoveField( + model_name='reviewrequest', + name='unused_review', + ), + migrations.RemoveField( + model_name='reviewrequest', + name='unused_review2', + ), + migrations.RemoveField( + model_name='reviewrequest', + name='unused_reviewed_rev', + ), + migrations.RemoveField( + model_name='reviewrequest', + name='unused_result', + ), + migrations.RemoveField( + model_name='reviewwish', + name='doc', + ), + migrations.RemoveField( + model_name='reviewassignment', + name='review', + ), + ] diff --git a/ietf/review/migrations/0013_rename_field_document2.py b/ietf/review/migrations/0013_rename_field_document2.py new file mode 100644 index 000000000..b40b82fd1 --- /dev/null +++ b/ietf/review/migrations/0013_rename_field_document2.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-21 05:31 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ('review', '0012_remove_old_document_field'), + ] + + operations = [ + migrations.RenameField( + model_name='reviewrequest', + old_name='doc2', + new_name='doc', + ), + migrations.RenameField( + model_name='reviewwish', + old_name='doc2', + new_name='doc', + ), + migrations.RenameField( + model_name='reviewassignment', + old_name='review2', + new_name='review', + ), + ] diff --git a/ietf/review/migrations/0014_document_primary_key_cleanup.py b/ietf/review/migrations/0014_document_primary_key_cleanup.py new file mode 100644 index 000000000..8ef0b334e --- /dev/null +++ b/ietf/review/migrations/0014_document_primary_key_cleanup.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-06-10 03:47 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('review', '0013_rename_field_document2'), + ] + + operations = [ + migrations.AlterField( + model_name='reviewrequest', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reviewrequest_set', to='doc.Document'), + ), + migrations.AlterField( + model_name='reviewwish', + name='doc', + field=ietf.utils.models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='doc.Document'), + ), + ] diff --git a/ietf/review/models.py b/ietf/review/models.py index dab758d50..3780e7667 100644 --- a/ietf/review/models.py +++ b/ietf/review/models.py @@ -119,14 +119,6 @@ class ReviewRequest(models.Model): requested_rev = models.CharField(verbose_name="requested revision", max_length=16, blank=True, help_text="Fill in if a specific revision is to be reviewed, e.g. 02") comment = models.TextField(verbose_name="Requester's comments and instructions", max_length=2048, blank=True, help_text="Provide any additional information to show to the review team secretary and reviewer", default='') - # Moved to class ReviewAssignment: - # These exist only to facilitate data migrations. They will be removed in the next release. - unused_reviewer = ForeignKey(Email, blank=True, null=True) - - unused_review = OneToOneField(Document, blank=True, null=True) - unused_reviewed_rev = models.CharField(verbose_name="reviewed revision", max_length=16, blank=True) - unused_result = ForeignKey(ReviewResultName, blank=True, null=True) - def __unicode__(self): return u"%s review on %s by %s %s" % (self.type, self.doc, self.team, self.state) diff --git a/ietf/review/utils.py b/ietf/review/utils.py index 5cef81fbe..5b8ce5bc5 100644 --- a/ietf/review/utils.py +++ b/ietf/review/utils.py @@ -167,7 +167,7 @@ def days_needed_to_fulfill_min_interval_for_reviewers(team): return res ReviewAssignmentData = namedtuple("ReviewAssignmentData", [ - "assignment_pk", "doc", "doc_pages", "req_time", "state", "assigned_time", "deadline", "reviewed_rev", "result", "team", "reviewer", + "assignment_pk", "doc_name", "doc_pages", "req_time", "state", "assigned_time", "deadline", "reviewed_rev", "result", "team", "reviewer", "late_days", "request_to_assignment_days", "assignment_to_closure_days", "request_to_closure_days"]) @@ -194,7 +194,7 @@ def extract_review_assignment_data(teams=None, reviewers=None, time_from=None, t event_qs = ReviewAssignment.objects.filter(filters) event_qs = event_qs.values_list( - "pk", "review_request__doc", "review_request__doc__pages", "review_request__time", "state", "review_request__deadline", "reviewed_rev", "result", "review_request__team", + "pk", "review_request__doc__name", "review_request__doc__pages", "review_request__time", "state", "review_request__deadline", "reviewed_rev", "result", "review_request__team", "reviewer__person", "assigned_on", "completed_on" ) @@ -215,7 +215,7 @@ def extract_review_assignment_data(teams=None, reviewers=None, time_from=None, t for assignment in event_qs: - assignment_pk, doc, doc_pages, req_time, state, deadline, reviewed_rev, result, team, reviewer, assigned_on, completed_on = assignment + assignment_pk, doc_name, doc_pages, req_time, state, deadline, reviewed_rev, result, team, reviewer, assigned_on, completed_on = assignment requested_time = req_time assigned_time = assigned_on @@ -226,7 +226,7 @@ def extract_review_assignment_data(teams=None, reviewers=None, time_from=None, t assignment_to_closure_days = positive_days(assigned_time, closed_time) request_to_closure_days = positive_days(requested_time, closed_time) - d = ReviewAssignmentData(assignment_pk, doc, doc_pages, req_time, state, assigned_time, deadline, reviewed_rev, result, team, reviewer, + d = ReviewAssignmentData(assignment_pk, doc_name, doc_pages, req_time, state, assigned_time, deadline, reviewed_rev, result, team, reviewer, late_days, request_to_assignment_days, assignment_to_closure_days, request_to_closure_days) @@ -659,7 +659,7 @@ def suggested_review_requests_for_team(team): # cancelled/moved telechat_events = TelechatDocEvent.objects.filter( # turn into list so we don't get a complex and slow join sent down to the DB - doc__in=list(telechat_docs.values_list("pk", flat=True)), + doc__id__in=list(telechat_docs.values_list("pk", flat=True)), ).values_list( "doc", "pk", "time", "telechat_date" ).order_by("doc", "-time", "-id").distinct() @@ -688,7 +688,7 @@ def suggested_review_requests_for_team(team): # filter those with existing explicit requests existing_requests = defaultdict(list) - for r in ReviewRequest.objects.filter(doc__in=requests.iterkeys(), team=team): + for r in ReviewRequest.objects.filter(doc__id__in=requests.iterkeys(), team=team): existing_requests[r.doc_id].append(r) def blocks(existing, request): @@ -719,8 +719,10 @@ def extract_revision_ordered_review_assignments_for_documents_and_replaced(revie replaces = extract_complete_replaces_ancestor_mapping_for_docs(names) assignments_for_each_doc = defaultdict(list) - for r in review_assignment_queryset.filter(review_request__doc__in=set(e for l in replaces.itervalues() for e in l) | names).order_by("-reviewed_rev","-assigned_on", "-id").iterator(): - assignments_for_each_doc[r.review_request.doc_id].append(r) + replacement_name_set = set(e for l in replaces.itervalues() for e in l) | names + for r in ( review_assignment_queryset.filter(review_request__doc__name__in=replacement_name_set) + .order_by("-reviewed_rev","-assigned_on", "-id").iterator()): + assignments_for_each_doc[r.review_request.doc.name].append(r) # now collect in breadth-first order to keep the revision order intact res = defaultdict(list) @@ -765,8 +767,8 @@ def extract_revision_ordered_review_requests_for_documents_and_replaced(review_r replaces = extract_complete_replaces_ancestor_mapping_for_docs(names) requests_for_each_doc = defaultdict(list) - for r in review_request_queryset.filter(doc__in=set(e for l in replaces.itervalues() for e in l) | names).order_by("-time", "-id").iterator(): - requests_for_each_doc[r.doc_id].append(r) + for r in review_request_queryset.filter(doc__name__in=set(e for l in replaces.itervalues() for e in l) | names).order_by("-time", "-id").iterator(): + requests_for_each_doc[r.doc.name].append(r) # now collect in breadth-first order to keep the revision order intact res = defaultdict(list) @@ -990,12 +992,12 @@ def email_reviewer_reminder(review_request): deadline_days = (review_request.deadline - datetime.date.today()).days - subject = "Reminder: deadline for review of {} in {} is {}".format(review_request.doc_id, team.acronym, review_request.deadline.isoformat()) + subject = "Reminder: deadline for review of {} in {} is {}".format(review_request.doc.name, team.acronym, review_request.deadline.isoformat()) import ietf.ietfauth.views overview_url = urlreverse(ietf.ietfauth.views.review_overview) import ietf.doc.views_review - request_url = urlreverse(ietf.doc.views_review.review_request, kwargs={ "name": review_request.doc_id, "request_id": review_request.pk }) + request_url = urlreverse(ietf.doc.views_review.review_request, kwargs={ "name": review_request.doc.name, "request_id": review_request.pk }) domain = Site.objects.get_current().domain @@ -1034,12 +1036,12 @@ def email_secretary_reminder(review_request, secretary_role): deadline_days = (review_request.deadline - datetime.date.today()).days - subject = "Reminder: deadline for review of {} in {} is {}".format(review_request.doc_id, team.acronym, review_request.deadline.isoformat()) + subject = "Reminder: deadline for review of {} in {} is {}".format(review_request.doc.name, team.acronym, review_request.deadline.isoformat()) import ietf.group.views settings_url = urlreverse(ietf.group.views.change_review_secretary_settings, kwargs={ "acronym": team.acronym, "group_type": team.type_id }) import ietf.doc.views_review - request_url = urlreverse(ietf.doc.views_review.review_request, kwargs={ "name": review_request.doc_id, "request_id": review_request.pk }) + request_url = urlreverse(ietf.doc.views_review.review_request, kwargs={ "name": review_request.doc.name, "request_id": review_request.pk }) domain = Site.objects.get_current().domain diff --git a/ietf/secr/proceedings/proc_utils.py b/ietf/secr/proceedings/proc_utils.py index 549d37237..f696c5e27 100644 --- a/ietf/secr/proceedings/proc_utils.py +++ b/ietf/secr/proceedings/proc_utils.py @@ -207,10 +207,10 @@ def get_progress_stats(sdate,edate): new_draft_events = events.filter(newrevisiondocevent__rev='00') new_drafts = list(set([ e.doc_id for e in new_draft_events ])) data['new_drafts_count'] = len(new_drafts) - data['new_drafts_updated_count'] = events.filter(doc__in=new_drafts,newrevisiondocevent__rev='01').count() - data['new_drafts_updated_more_count'] = events.filter(doc__in=new_drafts,newrevisiondocevent__rev='02').count() + data['new_drafts_updated_count'] = events.filter(doc__id__in=new_drafts,newrevisiondocevent__rev='01').count() + data['new_drafts_updated_more_count'] = events.filter(doc__id__in=new_drafts,newrevisiondocevent__rev='02').count() - update_events = events.filter(type='new_revision').exclude(doc__in=new_drafts) + update_events = events.filter(type='new_revision').exclude(doc__id__in=new_drafts) data['updated_drafts_count'] = len(set([ e.doc_id for e in update_events ])) # Calculate Final Four Weeks stats (ffw) @@ -224,7 +224,7 @@ def get_progress_stats(sdate,edate): data['ffw_new_count'] = ffw_new_count data['ffw_new_percent'] = ffw_new_percent - ffw_update_events = events.filter(time__gte=ffwdate,type='new_revision').exclude(doc__in=new_drafts) + ffw_update_events = events.filter(time__gte=ffwdate,type='new_revision').exclude(doc__id__in=new_drafts) ffw_update_count = len(set([ e.doc_id for e in ffw_update_events ])) try: ffw_update_percent = format(ffw_update_count / float(data['updated_drafts_count']),'.0%') diff --git a/ietf/settings.py b/ietf/settings.py index 2fb58bfa3..68ecd17b5 100644 --- a/ietf/settings.py +++ b/ietf/settings.py @@ -21,6 +21,7 @@ warnings.filterwarnings("ignore", message="Deprecated allow_tags attribute used warnings.filterwarnings("ignore", message="You passed a bytestring as `filenames`. This will not work on Python 3.") warnings.filterwarnings("ignore", message="django.forms.extras is deprecated.", module="bootstrap3") warnings.filterwarnings("ignore", message="defusedxml.lxml is no longer supported and will be removed in a future release.", module="tastypie") +warnings.filterwarnings("ignore", message="Duplicate index '.*' defined on the table") try: diff --git a/ietf/submit/migrations/0002_submission_document2_fk.py b/ietf/submit/migrations/0002_submission_document2_fk.py new file mode 100644 index 000000000..23ef204e4 --- /dev/null +++ b/ietf/submit/migrations/0002_submission_document2_fk.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-08 11:58 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import ietf.utils.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0015_1_add_fk_to_document_id'), + ('submit', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='submission', + name='draft2', + field=ietf.utils.models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='doc.Document', to_field=b'id'), + ), + migrations.AlterField( + model_name='submission', + name='draft', + field=ietf.utils.models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='old_submission', to='doc.Document', to_field=b'name'), + ), + ] diff --git a/ietf/submit/migrations/0003_remove_old_document_field.py b/ietf/submit/migrations/0003_remove_old_document_field.py new file mode 100644 index 000000000..20b35fca9 --- /dev/null +++ b/ietf/submit/migrations/0003_remove_old_document_field.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-25 06:44 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('submit', '0002_submission_document2_fk'), + ] + + operations = [ + migrations.RemoveField( + model_name='submission', + name='draft', + ), + ] diff --git a/ietf/submit/migrations/0004_rename_field_document2.py b/ietf/submit/migrations/0004_rename_field_document2.py new file mode 100644 index 000000000..9ff0f6d42 --- /dev/null +++ b/ietf/submit/migrations/0004_rename_field_document2.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.20 on 2019-05-25 06:46 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('doc', '0019_rename_field_document2'), + ('submit', '0003_remove_old_document_field'), + ] + + operations = [ + migrations.RenameField( + model_name='submission', + old_name='draft2', + new_name='draft', + ), + ] diff --git a/ietf/submit/tests.py b/ietf/submit/tests.py index 50cbcceb8..7f978d4a5 100644 --- a/ietf/submit/tests.py +++ b/ietf/submit/tests.py @@ -181,7 +181,7 @@ class SubmitTests(TestCase): if r.status_code == 302: submission = Submission.objects.get(name=name) self.assertEqual(submission.submitter, email.utils.formataddr((submitter_name, submitter_email))) - self.assertEqual(submission.replaces, ",".join(d.name for d in DocAlias.objects.filter(pk__in=replaces.split(",") if replaces else []))) + self.assertEqual(submission.replaces, ",".join(d.name for d in DocAlias.objects.filter(name__in=replaces.split(",") if replaces else []))) return r @@ -237,7 +237,7 @@ class SubmitTests(TestCase): mailbox_before = len(outbox) replaced_alias = draft.docalias_set.first() r = self.supply_extra_metadata(name, status_url, author.ascii, author.email().address.lower(), - replaces=str(replaced_alias.pk) + "," + str(sug_replaced_alias.pk)) + replaces=str(replaced_alias.name) + "," + str(sug_replaced_alias.name)) self.assertEqual(r.status_code, 302) status_url = r["Location"] @@ -594,16 +594,16 @@ class SubmitTests(TestCase): status_url, author = self.do_submission(name,rev) mailbox_before = len(outbox) replaced_alias = draft.docalias_set.first() - r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.pk)) + r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.name)) self.assertEqual(r.status_code, 200) self.assertTrue('cannot replace itself' in unicontent(r)) replaced_alias = DocAlias.objects.get(name='draft-ietf-random-thing') - r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.pk)) + r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.name)) self.assertEqual(r.status_code, 200) self.assertTrue('cannot replace an RFC' in unicontent(r)) replaced_alias.document.set_state(State.objects.get(type='draft-iesg',slug='approved')) replaced_alias.document.set_state(State.objects.get(type='draft',slug='active')) - r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.pk)) + r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.name)) self.assertEqual(r.status_code, 200) self.assertTrue('approved by the IESG and cannot' in unicontent(r)) r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces='') @@ -737,7 +737,7 @@ class SubmitTests(TestCase): "edit-pages": "123", "submitter-name": "Some Random Test Person", "submitter-email": "random@example.com", - "replaces": str(draft.docalias_set.all().first().pk), + "replaces": str(draft.docalias_set.all().first().name), "edit-note": "no comments", "authors-0-name": "Person 1", "authors-0-email": "person1@example.com", diff --git a/ietf/sync/tests.py b/ietf/sync/tests.py index 171bcd065..134c307ac 100644 --- a/ietf/sync/tests.py +++ b/ietf/sync/tests.py @@ -478,7 +478,7 @@ class RFCEditorUndoTests(TestCase): # get r = self.client.get(url) self.assertEqual(r.status_code, 200) - self.assertTrue(e2.doc_id in unicontent(r)) + self.assertTrue(e2.doc.name in unicontent(r)) # delete e2 deleted_before = DeletedEvent.objects.count() diff --git a/ietf/templates/community/notification_email.txt b/ietf/templates/community/notification_email.txt index 0fc1c662c..9581423f0 100644 --- a/ietf/templates/community/notification_email.txt +++ b/ietf/templates/community/notification_email.txt @@ -4,7 +4,7 @@ Hello, This is a notification from the {{ clist.long_name }}. Document: {{ event.doc }}, -https://datatracker.ietf.org/doc/{{ event.doc_id }}/ +https://datatracker.ietf.org/doc/{{ event.doc.name }}/ Change by {{ event.by }} on {{ event.time }}: diff --git a/ietf/templates/doc/document_review.html b/ietf/templates/doc/document_review.html index efa13552f..30c0f7f60 100644 --- a/ietf/templates/doc/document_review.html +++ b/ietf/templates/doc/document_review.html @@ -44,7 +44,7 @@ diff --git a/ietf/templates/doc/review_assignment_summary.html b/ietf/templates/doc/review_assignment_summary.html index e6e9bcca6..de4e82040 100644 --- a/ietf/templates/doc/review_assignment_summary.html +++ b/ietf/templates/doc/review_assignment_summary.html @@ -1,12 +1,12 @@
{% if review_assignment.state_id == "completed" or review_assignment.state_id == "part-completed" %} - - {{ review_assignment.review_request.team.acronym|upper }} {{ review_assignment.review_request.type.name }} Review{% if review_assignment.reviewed_rev and review_assignment.reviewed_rev != current_rev or review_assignment.review_request.doc_id != current_doc_name %} (of {% if review_assignment.review_request.doc_id != current_doc_name %}{{ review_assignment.review_request.doc_id }}{% endif %}-{{ review_assignment.reviewed_rev }}){% endif %}{% if review_assignment.result %}: + + {{ review_assignment.review_request.team.acronym|upper }} {{ review_assignment.review_request.type.name }} Review{% if review_assignment.reviewed_rev and review_assignment.reviewed_rev != current_rev or review_assignment.review_request.doc.name != current_doc_name %} (of {% if review_assignment.review_request.doc.name != current_doc_name %}{{ review_assignment.review_request.doc.name }}{% endif %}-{{ review_assignment.reviewed_rev }}){% endif %}{% if review_assignment.result %}: {{ review_assignment.result.name }}{% endif %} {% if review_assignment.state_id == "part-completed" %}(partially completed){% endif %} {% else %} - {{ review_assignment.review_request.team.acronym|upper }} {{ review_assignment.review_request.type.name }} Review + {{ review_assignment.review_request.team.acronym|upper }} {{ review_assignment.review_request.type.name }} Review - due: {{ review_assignment.review_request.deadline|date:"Y-m-d" }} {% endif %}
diff --git a/ietf/templates/group/manage_review_requests.html b/ietf/templates/group/manage_review_requests.html index 2da532d96..12f3f1030 100644 --- a/ietf/templates/group/manage_review_requests.html +++ b/ietf/templates/group/manage_review_requests.html @@ -61,13 +61,13 @@ {% for rlatest in r.latest_reqs %}
{% if rlatest.reviewed_rev %} - Previous review of {% if rlatest.doc_id != r.doc_id %}{{ rlatest.doc_id }}{% endif %}-{{ rlatest.reviewed_rev }} + Previous review of {% if rlatest.doc_id != r.doc_id %}{{ rlatest.doc.name }}{% endif %}-{{ rlatest.reviewed_rev }} (diff): {% if rlatest.result %}{{ rlatest.result.name }}{% else %}result unavail.{% endif %} by {{ rlatest.reviewer.person }}{% if rlatest.closed_review_request_event %} {{ rlatest.closed_review_request_event.time.date|date }}{% endif %} {% else %} - Previous review of {% if rlatest.doc_id != r.doc_id %}{{ rlatest.doc_id }}{% else %}this document{% endif %}: - {% if rlatest.result %}{{ rlatest.result.name }}{% else %}result unavail.{% endif %} + Previous review of {% if rlatest.doc_id != r.doc_id %}{{ rlatest.doc.name }}{% else %}this document{% endif %}: + {% if rlatest.result %}{{ rlatest.result.name }}{% else %}result unavail.{% endif %} by {{ rlatest.reviewer.person }}{% if rlatest.closed_review_request_event %} {{ rlatest.closed_review_request_event.time.date|date }}{% endif %} {% endif %}
diff --git a/ietf/templates/iesg/agenda_doc.txt b/ietf/templates/iesg/agenda_doc.txt index c5700d795..247d456a5 100644 --- a/ietf/templates/iesg/agenda_doc.txt +++ b/ietf/templates/iesg/agenda_doc.txt @@ -6,6 +6,6 @@ IANA Review: {{ doc.iana_review_state }}{% endif %}{% if doc.consensus %} Consensus: {{ doc.consensus }}{% endif %}{% if doc.lastcall_expires %} Last call expires: {{ doc.lastcall_expires|date:"Y-m-d" }}{% endif %}{% if doc.review_assignments %} - Reviews: {% for assignment in doc.review_assignments %}{% with current_doc_name=doc.name current_rev=doc.rev %}{% if not forloop.first %} {% endif %}{{ assignment.review_request.team.acronym|upper }} {{ assignment.review_request.type.name }} Review{% if assignment.state_id == "completed" or assignment.state_id == "part-completed" %}{% if assignment.reviewed_rev and assignment.reviewed_rev != current_rev or assignment.review_request.doc_id != current_doc_name %} (of {% if assignment.review_request.doc_id != current_doc_name %}{{ assignment.review_request.doc_id }}{% endif %}-{{ assignment.reviewed_rev }}){% endif %}{% if assignment.result %}: {{ assignment.result.name }}{% endif %} {% if assignment.state_id == "part-completed" %}(partially completed){% endif %}{% else %} - due: {{ assignment.review_request.deadline|date:"Y-m-d" }}{% endif %}{% endwith %} + Reviews: {% for assignment in doc.review_assignments %}{% with current_doc_name=doc.name current_rev=doc.rev %}{% if not forloop.first %} {% endif %}{{ assignment.review_request.team.acronym|upper }} {{ assignment.review_request.type.name }} Review{% if assignment.state_id == "completed" or assignment.state_id == "part-completed" %}{% if assignment.reviewed_rev and assignment.reviewed_rev != current_rev or assignment.review_request.doc.name != current_doc_name %} (of {% if assignment.review_request.doc.name != current_doc_name %}{{ assignment.review_request.doc.name }}{% endif %}-{{ assignment.reviewed_rev }}){% endif %}{% if assignment.result %}: {{ assignment.result.name }}{% endif %} {% if assignment.state_id == "part-completed" %}(partially completed){% endif %}{% else %} - due: {{ assignment.review_request.deadline|date:"Y-m-d" }}{% endif %}{% endwith %} {% endfor %}{% endif %} {% with doc.active_defer_event as defer %}{% if defer %} Was deferred by {{defer.by}} on {{defer.time|date:"Y-m-d"}}{% endif %}{% endwith %} diff --git a/ietf/templates/ietfauth/review_overview.html b/ietf/templates/ietfauth/review_overview.html index e79259a5b..4a48d7d65 100644 --- a/ietf/templates/ietfauth/review_overview.html +++ b/ietf/templates/ietfauth/review_overview.html @@ -95,7 +95,7 @@
{% for review_assignment in other_reviews %} - {% include "doc/review_assignment_summary.html" with current_doc_name=review_assignemnt.review_request.doc_id current_rev=review_assignment.reviewed_rev %} + {% include "doc/review_assignment_summary.html" with current_doc_name=review_assignemnt.review_request.doc.name current_rev=review_assignment.reviewed_rev %} {% endfor %}
{% for w in review_wishes %} - + - +
{{ w.doc_id }}{{ w.doc_id }} {{ w.team.acronym }}
diff --git a/ietf/templates/review/reviewer_reminder.txt b/ietf/templates/review/reviewer_reminder.txt index d2fe608cf..a15306d9b 100644 --- a/ietf/templates/review/reviewer_reminder.txt +++ b/ietf/templates/review/reviewer_reminder.txt @@ -1,4 +1,4 @@ -{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}This is just a friendly reminder that the deadline for the review of {{ review_request.doc_id }} is in {{ deadline_days }} day{{ deadline_days|pluralize }}: +{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}This is just a friendly reminder that the deadline for the review of {{ review_request.doc.name }} is in {{ deadline_days }} day{{ deadline_days|pluralize }}: {{ review_request_url }} diff --git a/ietf/templates/review/secretary_reminder.txt b/ietf/templates/review/secretary_reminder.txt index 2361489f3..5315b3646 100644 --- a/ietf/templates/review/secretary_reminder.txt +++ b/ietf/templates/review/secretary_reminder.txt @@ -1,4 +1,4 @@ -{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}This is just a friendly reminder that the deadline for the review of {{ review_request.doc_id }} is in {{ deadline_days }} day{{ deadline_days|pluralize }}: +{% load ietf_filters %}{% autoescape off %}{% filter wordwrap:78 %}This is just a friendly reminder that the deadline for the review of {{ review_request.doc.name }} is in {{ deadline_days }} day{{ deadline_days|pluralize }}: {{ review_request_url }} diff --git a/ietf/templates/sync/rfceditor_undo.html b/ietf/templates/sync/rfceditor_undo.html index 50a3ab951..4f4e319d5 100644 --- a/ietf/templates/sync/rfceditor_undo.html +++ b/ietf/templates/sync/rfceditor_undo.html @@ -22,7 +22,7 @@ {% for e in events %}
{{ e.time|date:"Y-m-d H:i:s"}}{{ e.doc_id }}{{ e.doc.name }} {{ e.desc|safe }} diff --git a/ietf/utils/history.py b/ietf/utils/history.py index 85e65024d..992902572 100644 --- a/ietf/utils/history.py +++ b/ietf/utils/history.py @@ -1,3 +1,8 @@ +# Copyright The IETF Trust 2011-2019, All Rights Reserved +# -*- coding: utf-8 -*- + +import debug # pyflakes:ignore + def find_history_active_at(obj, time): """Assumes obj has a corresponding history model (e.g. obj could be Document with a corresponding DocHistory model), then either diff --git a/ietf/utils/test_runner.py b/ietf/utils/test_runner.py index 8bd818ce1..5482de9f7 100644 --- a/ietf/utils/test_runner.py +++ b/ietf/utils/test_runner.py @@ -64,6 +64,7 @@ from django.template import TemplateDoesNotExist from django.template.loaders.base import Loader as BaseLoader from django.test.runner import DiscoverRunner from django.core.management import call_command + from django.urls import RegexURLResolver import debug # pyflakes:ignore @@ -72,7 +73,9 @@ debug.debug = True import ietf import ietf.utils.mail from ietf.checks import maybe_create_svn_symlinks +from ietf.utils.management.commands import pyflakes from ietf.utils.test_smtpserver import SMTPTestServerDriver +from ietf.utils.test_utils import TestCase loaded_templates = set() @@ -121,6 +124,19 @@ def safe_destroy_test_db(*args, **kwargs): settings.DATABASES["default"]["NAME"] = test_database_name return old_destroy(*args, **kwargs) +class PyFlakesTestCase(TestCase): + + def __init__(self, test_runner=None, **kwargs): + self.runner = test_runner + super(PyFlakesTestCase, self).__init__(**kwargs) + + def pyflakes_test(self): + self.maxDiff = None + path = os.path.join(settings.BASE_DIR) + warnings = [] + warnings = pyflakes.checkPaths([path], verbosity=0) + self.assertEqual([], [str(w) for w in warnings]) + class TemplateCoverageLoader(BaseLoader): is_usable = True @@ -375,6 +391,8 @@ class CoverageTest(unittest.TestCase): self.skipTest("Coverage switched off with --skip-coverage") def interleaved_migrations_test(self): + if self.runner.permit_mixed_migrations: + return # from django.apps import apps # unreleased = {} # for appconf in apps.get_app_configs(): @@ -474,12 +492,16 @@ class IetfTestRunner(DiscoverRunner): parser.add_argument('--html-report', action='store_true', default=False, help='Generate a html code coverage report in %s' % settings.TEST_CODE_COVERAGE_REPORT_DIR) + parser.add_argument('--permit-mixed-migrations', + action='store_true', default=False, + help='Permit interleaved unreleased migrations') - def __init__(self, skip_coverage=False, save_version_coverage=None, html_report=None, **kwargs): + def __init__(self, skip_coverage=False, save_version_coverage=None, html_report=None, permit_mixed_migrations=None, **kwargs): # self.check_coverage = not skip_coverage self.save_version_coverage = save_version_coverage self.html_report = html_report + self.permit_mixed_migrations = permit_mixed_migrations # self.root_dir = os.path.dirname(settings.BASE_DIR) self.coverage_file = os.path.join(self.root_dir, settings.TEST_COVERAGE_MASTER_FILE) @@ -668,6 +690,7 @@ class IetfTestRunner(DiscoverRunner): code_coverage_collection = True url_coverage_collection = True extra_tests += [ + PyFlakesTestCase(test_runner=self, methodName='pyflakes_test'), CoverageTest(test_runner=self, methodName='interleaved_migrations_test'), CoverageTest(test_runner=self, methodName='url_coverage_test'), CoverageTest(test_runner=self, methodName='template_coverage_test'), @@ -679,7 +702,7 @@ class IetfTestRunner(DiscoverRunner): # parent classes to later subclasses, the parent classes will # determine the ordering, so use the most specific classes # necessary to get the right ordering: - self.reorder_by += (StaticLiveServerTestCase, TemplateTagTest, CoverageTest, ) + self.reorder_by = (PyFlakesTestCase, ) + self.reorder_by + (StaticLiveServerTestCase, TemplateTagTest, CoverageTest, ) failures = super(IetfTestRunner, self).run_tests(test_labels, extra_tests=extra_tests, **kwargs) diff --git a/ietf/utils/tests.py b/ietf/utils/tests.py index ee318c30f..a23adab7d 100644 --- a/ietf/utils/tests.py +++ b/ietf/utils/tests.py @@ -37,7 +37,6 @@ from ietf.utils.bower_storage import BowerStorageFinder from ietf.utils.draft import Draft, getmeta from ietf.utils.log import unreachable, assertion from ietf.utils.mail import send_mail_preformatted, send_mail_text, send_mail_mime, outbox -from ietf.utils.management.commands import pyflakes from ietf.utils.test_runner import get_template_paths, set_coverage_checking from ietf.utils.test_utils import TestCase @@ -51,15 +50,6 @@ except ImportError as e: skip_message = "Skipping trac tests: %s" % e sys.stderr.write(" "+skip_message+'\n') -class PyFlakesTestCase(TestCase): - - def test_pyflakes(self): - self.maxDiff = None - path = os.path.join(settings.BASE_DIR) - warnings = [] - warnings = pyflakes.checkPaths([path], verbosity=0) - self.assertEqual([], [str(w) for w in warnings]) - class SendingMail(TestCase): def test_send_mail_preformatted(self): From a2cafded254ff15ee98256ef844b05a942513aa4 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Fri, 14 Jun 2019 20:38:14 +0000 Subject: [PATCH 03/14] Changed DocAlias to be many-to-many, in order to be able to handle STD aliases referring to multiple RFCs. - Legacy-Id: 16249 --- bin/add-old-drafts-from-archive.py | 2 +- ietf/doc/admin.py | 16 +++++------ ietf/doc/factories.py | 42 ++++++++++++++++++----------- ietf/doc/fields.py | 2 +- ietf/doc/models.py | 41 +++++++++++++++------------- ietf/doc/tests.py | 20 +++++++------- ietf/doc/tests_ballot.py | 6 ++--- ietf/doc/tests_downref.py | 6 ++--- ietf/doc/tests_draft.py | 4 +-- ietf/doc/tests_material.py | 2 +- ietf/doc/tests_review.py | 4 +-- ietf/doc/tests_status_change.py | 2 +- ietf/doc/utils.py | 6 ++--- ietf/doc/utils_search.py | 11 ++++---- ietf/doc/views_charter.py | 2 +- ietf/doc/views_conflict_review.py | 5 ++-- ietf/doc/views_doc.py | 6 ++--- ietf/doc/views_material.py | 3 ++- ietf/doc/views_review.py | 2 +- ietf/doc/views_search.py | 4 +-- ietf/doc/views_status_change.py | 2 +- ietf/group/dot.py | 4 +-- ietf/group/tests.py | 2 +- ietf/group/tests_info.py | 2 +- ietf/group/views.py | 4 +-- ietf/idindex/index.py | 8 +++--- ietf/idindex/tests.py | 8 +++--- ietf/iesg/tests.py | 6 ++--- ietf/ipr/admin.py | 2 +- ietf/ipr/factories.py | 2 +- ietf/ipr/tests.py | 12 ++++----- ietf/ipr/utils.py | 22 +++++++++++---- ietf/ipr/views.py | 22 +++++++-------- ietf/liaisons/forms.py | 4 +-- ietf/meeting/forms.py | 2 +- ietf/meeting/views.py | 12 ++++----- ietf/review/utils.py | 2 +- ietf/secr/drafts/views.py | 2 +- ietf/secr/proceedings/proc_utils.py | 6 ++--- ietf/secr/proceedings/tests.py | 4 +-- ietf/secr/telechat/tests.py | 2 +- ietf/secr/utils/document.py | 4 +-- ietf/stats/backfill_data.py | 4 +-- ietf/stats/tests.py | 4 +-- ietf/stats/views.py | 22 +++++++-------- ietf/submit/tests.py | 12 ++++----- ietf/submit/utils.py | 8 +++--- ietf/sync/rfceditor.py | 9 ++++--- ietf/sync/tests.py | 14 +++++----- ietf/utils/test_data.py | 38 +++++++++++--------------- 50 files changed, 228 insertions(+), 203 deletions(-) diff --git a/bin/add-old-drafts-from-archive.py b/bin/add-old-drafts-from-archive.py index 195501a26..9717e607b 100755 --- a/bin/add-old-drafts-from-archive.py +++ b/bin/add-old-drafts-from-archive.py @@ -79,7 +79,7 @@ for name in sorted(names): words=draft.get_wordcount(), expires=time+datetime.timedelta(settings.INTERNET_DRAFT_DAYS_TO_EXPIRE), ) - doc.docalias_set.create(name=doc.name) + DocAlias.objects.create(name=doc.name).docs.add(doc) doc.states.add(expired) # update authors authors = [] diff --git a/ietf/doc/admin.py b/ietf/doc/admin.py index d61ccb191..73c1a37ed 100644 --- a/ietf/doc/admin.py +++ b/ietf/doc/admin.py @@ -19,9 +19,9 @@ class StateAdmin(admin.ModelAdmin): filter_horizontal = ["next_states"] admin.site.register(State, StateAdmin) -class DocAliasInline(admin.TabularInline): - model = DocAlias - extra = 1 +# class DocAliasInline(admin.TabularInline): +# model = DocAlias +# extra = 1 class DocAuthorInline(admin.TabularInline): model = DocumentAuthor @@ -58,7 +58,7 @@ class DocumentAdmin(admin.ModelAdmin): search_fields = ['name'] list_filter = ['type'] raw_id_fields = ['group', 'shepherd', 'ad'] - inlines = [DocAliasInline, DocAuthorInline, RelatedDocumentInline, ] + inlines = [DocAuthorInline, RelatedDocumentInline, ] form = DocumentForm def save_model(self, request, obj, form, change): @@ -88,9 +88,9 @@ class DocHistoryAdmin(admin.ModelAdmin): admin.site.register(DocHistory, DocHistoryAdmin) class DocAliasAdmin(admin.ModelAdmin): - list_display = ['name', 'document_link'] - search_fields = ['name', 'document__name'] - raw_id_fields = ['document'] +# list_display = ['name', 'document_link'] +# search_fields = ['name', 'document__name'] + raw_id_fields = ['docs'] admin.site.register(DocAlias, DocAliasAdmin) class DocReminderAdmin(admin.ModelAdmin): @@ -102,7 +102,7 @@ admin.site.register(DocReminder, DocReminderAdmin) class RelatedDocumentAdmin(admin.ModelAdmin): list_display = ['source', 'target', 'relationship', ] list_filter = ['relationship', ] - search_fields = ['source__name', 'target__name', 'target__document__name', ] + search_fields = ['source__name', 'target__name', 'target__docs__name', ] raw_id_fields = ['source', 'target', ] admin.site.register(RelatedDocument, RelatedDocumentAdmin) diff --git a/ietf/doc/factories.py b/ietf/doc/factories.py index f5f669181..6d12779ac 100644 --- a/ietf/doc/factories.py +++ b/ietf/doc/factories.py @@ -33,13 +33,14 @@ class BaseDocumentFactory(factory.DjangoModelFactory): newrevisiondocevent = factory.RelatedFactory('ietf.doc.factories.NewRevisionDocEventFactory','doc') - alias = factory.RelatedFactory('ietf.doc.factories.DocAliasFactory','document') - @factory.post_generation def other_aliases(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument + alias = DocAliasFactory(name=obj.name) + alias.docs.add(obj) if create and extracted: - for alias in extracted: - obj.docalias_set.create(name=alias) + for name in extracted: + alias = DocAliasFactory(name=name) + alias.docs.add(obj) @factory.post_generation def states(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument @@ -61,10 +62,14 @@ class BaseDocumentFactory(factory.DjangoModelFactory): @factory.post_generation def relations(obj, create, extracted, **kwargs): # pylint: disable=no-self-argument if create and extracted: - for (rel_id,docalias) in extracted: - if isinstance(docalias,Document): - docalias = docalias.docalias_set.first() - obj.relateddocument_set.create(relationship_id=rel_id,target=docalias) + for (rel_id, doc) in extracted: + if isinstance(doc, Document): + docalias = doc.docalias.first() + elif isinstance(doc, DocAlias): + docalias = doc + else: + continue + obj.relateddocument_set.create(relationship_id=rel_id, target=docalias) @classmethod def _after_postgeneration(cls, obj, create, results=None): @@ -195,9 +200,9 @@ class ConflictReviewFactory(BaseDocumentFactory): if not create: return if extracted: - obj.relateddocument_set.create(relationship_id='conflrev',target=extracted.docalias_set.first()) + obj.relateddocument_set.create(relationship_id='conflrev',target=extracted.docalias.first()) else: - obj.relateddocument_set.create(relationship_id='conflrev',target=DocumentFactory(type_id='draft',group=Group.objects.get(type_id='individ')).docalias_set.first()) + obj.relateddocument_set.create(relationship_id='conflrev',target=DocumentFactory(type_id='draft',group=Group.objects.get(type_id='individ')).docalias.first()) @factory.post_generation def states(obj, create, extracted, **kwargs): @@ -219,12 +224,19 @@ class DocAliasFactory(factory.DjangoModelFactory): class Meta: model = DocAlias - document = factory.SubFactory('ietf.doc.factories.DocumentFactory') + @factory.post_generation + def document(self, create, extracted, **kwargs): + if create and extracted: + self.docs.add(extracted) + self.name = extracted.name + + @factory.post_generation + def docs(self, create, extracted, **kwargs): + if create and extracted: + for doc in extracted: + if not doc in self.docs.all(): + self.docs.add(doc) - @factory.lazy_attribute - def name(self): - return self.document.name - class DocEventFactory(factory.DjangoModelFactory): class Meta: diff --git a/ietf/doc/fields.py b/ietf/doc/fields.py index 3285e1416..0ec3d10c9 100644 --- a/ietf/doc/fields.py +++ b/ietf/doc/fields.py @@ -59,7 +59,7 @@ class SearchableDocumentsField(forms.CharField): value = self.model.objects.filter(Q(name__in=names)|Q(id__in=ids)) filter_args = {} if self.model == DocAlias: - filter_args["document__type"] = self.doc_type + filter_args["docs__type"] = self.doc_type else: filter_args["type"] = self.doc_type value = value.filter(**filter_args) diff --git a/ietf/doc/models.py b/ietf/doc/models.py index 87ada27cc..746bb6b90 100644 --- a/ietf/doc/models.py +++ b/ietf/doc/models.py @@ -323,7 +323,7 @@ class DocumentInfo(models.Model): elif state.slug == "repl": rs = self.related_that("replaces") if rs: - return mark_safe("Replaced by " + ", ".join("%s" % (urlreverse('ietf.doc.views_doc.document_main', kwargs=dict(name=alias.document)), alias.document) for alias in rs)) + return mark_safe("Replaced by " + ", ".join("%s" % (urlreverse('ietf.doc.views_doc.document_main', kwargs=dict(name=alias.document.name)), alias.document) for alias in rs)) else: return "Replaced" elif state.slug == "active": @@ -411,9 +411,9 @@ class DocumentInfo(models.Model): if not isinstance(relationship, tuple): raise TypeError("Expected a string or tuple, received %s" % type(relationship)) if isinstance(self, Document): - return RelatedDocument.objects.filter(target__document=self, relationship__in=relationship).select_related('source') + return RelatedDocument.objects.filter(target__docs=self, relationship__in=relationship).select_related('source') elif isinstance(self, DocHistory): - return RelatedDocHistory.objects.filter(target__document=self.doc, relationship__in=relationship).select_related('source') + return RelatedDocHistory.objects.filter(target__docs=self.doc, relationship__in=relationship).select_related('source') else: raise TypeError("Expected method called on Document or DocHistory") @@ -434,9 +434,9 @@ class DocumentInfo(models.Model): if not isinstance(relationship, tuple): raise TypeError("Expected a string or tuple, received %s" % type(relationship)) if isinstance(self, Document): - return RelatedDocument.objects.filter(source=self, relationship__in=relationship).select_related('target__document') + return RelatedDocument.objects.filter(source=self, relationship__in=relationship).select_related('target') elif isinstance(self, DocHistory): - return RelatedDocHistory.objects.filter(source=self, relationship__in=relationship).select_related('target__document') + return RelatedDocHistory.objects.filter(source=self, relationship__in=relationship).select_related('target') else: raise TypeError("Expected method called on Document or DocHistory") @@ -447,14 +447,15 @@ class DocumentInfo(models.Model): for r in rels: if not r in related: related += ( r, ) - related = r.target.document.all_relations_that_doc(relationship, related) + for doc in r.target.docs.all(): + related = doc.all_relations_that_doc(relationship, related) return related def related_that(self, relationship): - return list(set([x.source.docalias_set.get(name=x.source.name) for x in self.relations_that(relationship)])) + return list(set([x.source.docalias.get(name=x.source.name) for x in self.relations_that(relationship)])) def all_related_that(self, relationship, related=None): - return list(set([x.source.docalias_set.get(name=x.source.name) for x in self.all_relations_that(relationship)])) + return list(set([x.source.docalias.get(name=x.source.name) for x in self.all_relations_that(relationship)])) def related_that_doc(self, relationship): return list(set([x.target for x in self.relations_that_doc(relationship)])) @@ -463,7 +464,7 @@ class DocumentInfo(models.Model): return list(set([x.target for x in self.all_relations_that_doc(relationship)])) def replaces(self): - return set([ r.document for r in self.related_that_doc("replaces")]) + return set([ d for r in self.related_that_doc("replaces") for d in r.docs.all() ]) def replaces_canonical_name(self): s = set([ r.document for r in self.related_that_doc("replaces")]) @@ -657,7 +658,7 @@ class Document(DocumentInfo): if not hasattr(self, '_canonical_name'): name = self.name if self.type_id == "draft" and self.get_state_slug() == "rfc": - a = self.docalias_set.filter(name__startswith="rfc").order_by('-name').first() + a = self.docalias.filter(name__startswith="rfc").order_by('-name').first() if a: name = a.name elif self.type_id == "charter": @@ -671,7 +672,7 @@ class Document(DocumentInfo): def canonical_docalias(self): - return self.docalias_set.get(name=self.name) + return self.docalias.get(name=self.name) def display_name(self): name = self.canonical_name() @@ -766,14 +767,14 @@ class Document(DocumentInfo): def ipr(self,states=('posted','removed')): """Returns the IPR disclosures against this document (as a queryset over IprDocRel).""" from ietf.ipr.models import IprDocRel - return IprDocRel.objects.filter(document__document=self,disclosure__state__in=states) + return IprDocRel.objects.filter(document__docs=self, disclosure__state__in=states) def related_ipr(self): """Returns the IPR disclosures against this document and those documents this document directly or indirectly obsoletes or replaces """ from ietf.ipr.models import IprDocRel - iprs = IprDocRel.objects.filter(document__in=list(self.docalias_set.all())+self.all_related_that_doc(('obs','replaces'))).filter(disclosure__state__in=('posted','removed')).values_list('disclosure', flat=True).distinct() + iprs = IprDocRel.objects.filter(document__in=list(self.docalias.all())+self.all_related_that_doc(('obs','replaces'))).filter(disclosure__state__in=('posted','removed')).values_list('disclosure', flat=True).distinct() return iprs def future_presentations(self): @@ -889,8 +890,9 @@ class DocHistory(DocumentInfo): return self.doc.groupmilestone_set @property - def docalias_set(self): - return self.doc.docalias_set + def docalias(self): + log.unreachable('2019-06-11') + return self.doc.docalias def is_dochistory(self): return True @@ -909,11 +911,14 @@ class DocAlias(models.Model): to by RFC number, primarily, after achieving RFC status. """ name = models.CharField(max_length=255, unique=True) - document = ForeignKey(Document) -# docs = models.ManyToManyField(Document, related_name='aliases') + docs = models.ManyToManyField(Document, related_name='docalias') + + @property + def document(self): + return self.docs.first() def __unicode__(self): - return "%s-->%s" % (self.name, self.document.name) + return "%s-->%s" % (self.name, ','.join([unicode(d.name) for d in self.docs.all() if isinstance(d, Document) ])) document_link = admin_link("document") class Meta: verbose_name = "document alias" diff --git a/ietf/doc/tests.py b/ietf/doc/tests.py index 7fac55de8..43629e278 100644 --- a/ietf/doc/tests.py +++ b/ietf/doc/tests.py @@ -216,7 +216,7 @@ class SearchTests(TestCase): draft.set_state(State.objects.get(type='draft-iesg', slug='lc')) rfc = IndividualDraftFactory(ad=ad) rfc.set_state(State.objects.get(type='draft', slug='rfc')) - rfc.docalias_set.create(name='rfc6666') + DocAlias.objects.create(name='rfc6666').docs.add(rfc) conflrev = DocumentFactory(type_id='conflrev',ad=ad) conflrev.set_state(State.objects.get(type='conflrev', slug='iesgeval')) statchg = DocumentFactory(type_id='statchg',ad=ad) @@ -278,7 +278,7 @@ class SearchTests(TestCase): self.assertEqual(data[0]["id"], draft.pk) # DocAlias - doc_alias = draft.docalias_set.get() + doc_alias = draft.docalias.first() url = urlreverse('ietf.doc.views_search.ajax_select2_search_docs', kwargs={ "model_name": "docalias", @@ -499,7 +499,7 @@ Man Expires September 22, 2015 [Page 3] draft = WgDraftFactory(name='draft-ietf-mars-test',rev='01') HolderIprDisclosureFactory(docs=[draft]) replaced = IndividualDraftFactory() - draft.relateddocument_set.create(relationship_id='replaces',source=draft,target=replaced.docalias_set.first()) + draft.relateddocument_set.create(relationship_id='replaces',source=draft,target=replaced.docalias.first()) # these tests aren't testing all attributes yet, feel free to # expand them @@ -580,7 +580,7 @@ Man Expires September 22, 2015 [Page 3] shepherd_id=draft.shepherd_id, ad_id=draft.ad_id, expires=draft.expires, notify=draft.notify, note=draft.note) rel = RelatedDocument.objects.create(source=replacement, - target=draft.docalias_set.get(name__startswith="draft"), + target=draft.docalias.get(name__startswith="draft"), relationship_id="replaces") r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name))) @@ -595,8 +595,10 @@ Man Expires September 22, 2015 [Page 3] draft.save_with_history([DocEvent.objects.create(doc=draft, rev=draft.rev, type="published_rfc", by=Person.objects.get(name="(System)"))]) - rfc_alias = DocAlias.objects.create(name="rfc123456", document=draft) - bcp_alias = DocAlias.objects.create(name="bcp123456", document=draft) + rfc_alias = DocAlias.objects.create(name="rfc123456") + rfc_alias.docs.add(draft) + bcp_alias = DocAlias.objects.create(name="bcp123456") + bcp_alias.docs.add(draft) r = self.client.get(urlreverse("ietf.doc.views_doc.document_main", kwargs=dict(name=draft.name))) self.assertEqual(r.status_code, 302) @@ -759,8 +761,8 @@ class DocTestCase(TestCase): self.assertFalse('more YES or NO' in unicontent(r)) # status change - IndividualDraftFactory().docalias_set.create(name='rfc9998') - IndividualDraftFactory().docalias_set.create(name='rfc9999') + DocAlias.objects.create(name='rfc9998').docs.add(IndividualDraftFactory()) + DocAlias.objects.create(name='rfc9999').docs.add(IndividualDraftFactory()) doc = DocumentFactory(type_id='statchg',name='status-change-imaginary-mid-review') iesgeval_pk = str(State.objects.get(slug='iesgeval',type__slug='statchg').pk) self.client.login(username='ad', password='ad+password') @@ -1003,7 +1005,7 @@ class ReferencesTest(TestCase): def test_references(self): doc1 = WgDraftFactory(name='draft-ietf-mars-test') - doc2 = IndividualDraftFactory(name='draft-imaginary-independent-submission').docalias_set.first() + doc2 = IndividualDraftFactory(name='draft-imaginary-independent-submission').docalias.first() RelatedDocument.objects.get_or_create(source=doc1,target=doc2,relationship=DocRelationshipName.objects.get(slug='refnorm')) url = urlreverse('ietf.doc.views_doc.document_references', kwargs=dict(name=doc1.name)) r = self.client.get(url) diff --git a/ietf/doc/tests_ballot.py b/ietf/doc/tests_ballot.py index 46340abf8..dcd24ebeb 100644 --- a/ietf/doc/tests_ballot.py +++ b/ietf/doc/tests_ballot.py @@ -741,7 +741,7 @@ class ApproveBallotTests(TestCase): self.assertTrue("No downward references for" in r.content) # Add a downref, the page should ask if it should be added to the registry - rel = draft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'),relationship_id='refnorm') + rel = draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'),relationship_id='refnorm') d = [rdoc for rdoc in draft.relateddocument_set.all() if rel.is_approved_downref()] original_len = len(d) r = self.client.get(url) @@ -970,7 +970,7 @@ class RegenerateLastCallTestCase(TestCase): std_level_id='inf', ) - draft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'),relationship_id='refnorm') + draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'),relationship_id='refnorm') r = self.client.post(url, dict(regenerate_last_call_text="1")) self.assertEqual(r.status_code, 200) @@ -980,7 +980,7 @@ class RegenerateLastCallTestCase(TestCase): self.assertTrue("rfc6666" in lc_text) self.assertTrue("Independent Submission Editor stream" in lc_text) - draft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'),relationship_id='downref-approval') + draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'),relationship_id='downref-approval') r = self.client.post(url, dict(regenerate_last_call_text="1")) self.assertEqual(r.status_code, 200) diff --git a/ietf/doc/tests_downref.py b/ietf/doc/tests_downref.py index ad35e89c1..41b2a165c 100644 --- a/ietf/doc/tests_downref.py +++ b/ietf/doc/tests_downref.py @@ -21,7 +21,7 @@ class Downref(TestCase): WgDraftFactory(name='draft-ietf-mars-test') doc = WgDraftFactory(name='draft-ietf-mars-approved-document',states=[('draft-iesg','rfcqueue')]) rfc = WgRfcFactory(alias2__name='rfc9998') - RelatedDocument.objects.create(source=doc, target=rfc.docalias_set.get(name='rfc9998'),relationship_id='downref-approval') + RelatedDocument.objects.create(source=doc, target=rfc.docalias.get(name='rfc9998'),relationship_id='downref-approval') def test_downref_registry(self): url = urlreverse('ietf.doc.views_downref.downref_registry') @@ -118,7 +118,7 @@ class Downref(TestCase): draft = WgDraftFactory(name='draft-ietf-mars-ready-for-lc-document',intended_std_level_id='ps',states=[('draft-iesg','iesg-eva')]) WgDraftFactory(name='draft-ietf-mars-another-approved-document',states=[('draft-iesg','rfcqueue')]) rfc9999 = WgRfcFactory(alias2__name='rfc9999', std_level_id=None) - RelatedDocument.objects.create(source=draft, target=rfc9999.docalias_set.get(name='rfc9999'), relationship_id='refnorm') + RelatedDocument.objects.create(source=draft, target=rfc9999.docalias.get(name='rfc9999'), relationship_id='refnorm') url = urlreverse('ietf.doc.views_ballot.lastcalltext', kwargs=dict(name=draft.name)) login_testing_unauthorized(self, "secretary", url) @@ -130,7 +130,7 @@ class Downref(TestCase): self.assertIn('The document contains these normative downward references', text) # now, the announcement text about the downref to RFC 9999 should be gone - RelatedDocument.objects.create(source=draft, target=rfc9999.docalias_set.get(name='rfc9999'),relationship_id='downref-approval') + RelatedDocument.objects.create(source=draft, target=rfc9999.docalias.get(name='rfc9999'),relationship_id='downref-approval') r = self.client.post(url, dict(regenerate_last_call_text="1")) self.assertEqual(r.status_code, 200) q = PyQuery(r.content) diff --git a/ietf/doc/tests_draft.py b/ietf/doc/tests_draft.py index 13c551d1c..9aa2f909b 100644 --- a/ietf/doc/tests_draft.py +++ b/ietf/doc/tests_draft.py @@ -1569,7 +1569,7 @@ class ChangeReplacesTests(TestCase): # Post that says replacea replaces base a empty_outbox() - RelatedDocument.objects.create(source=self.replacea, target=self.basea.docalias_set.first(), + RelatedDocument.objects.create(source=self.replacea, target=self.basea.docalias.first(), relationship=DocRelationshipName.objects.get(slug="possibly-replaces")) self.assertEqual(self.basea.get_state().slug,'active') r = self.client.post(url, dict(replaces=self.basea.name)) @@ -1617,7 +1617,7 @@ class ChangeReplacesTests(TestCase): def test_review_possibly_replaces(self): - replaced = self.basea.docalias_set.first() + replaced = self.basea.docalias.first() RelatedDocument.objects.create(source=self.replacea, target=replaced, relationship=DocRelationshipName.objects.get(slug="possibly-replaces")) diff --git a/ietf/doc/tests_material.py b/ietf/doc/tests_material.py index 687719a5c..a963ac1a6 100644 --- a/ietf/doc/tests_material.py +++ b/ietf/doc/tests_material.py @@ -52,7 +52,7 @@ class GroupMaterialTests(TestCase): doc = Document.objects.create(name="slides-testteam-test-file", rev="01", type_id="slides", group=group) doc.set_state(State.objects.get(type="slides", slug="active")) doc.set_state(State.objects.get(type="reuse_policy", slug="multiple")) - DocAlias.objects.create(name=doc.name, document=doc) + DocAlias.objects.create(name=doc.name).docs.add(doc) NewRevisionDocEvent.objects.create(doc=doc,by=Person.objects.get(name="(System)"),rev='00',type='new_revision',desc='New revision available') NewRevisionDocEvent.objects.create(doc=doc,by=Person.objects.get(name="(System)"),rev='01',type='new_revision',desc='New revision available') diff --git a/ietf/doc/tests_review.py b/ietf/doc/tests_review.py index d78c31437..857cc1155 100644 --- a/ietf/doc/tests_review.py +++ b/ietf/doc/tests_review.py @@ -144,8 +144,8 @@ class ReviewTests(TestCase): # check we can fish it out old_doc = WgDraftFactory(name="draft-foo-mars-test") older_doc = WgDraftFactory(name="draft-older") - RelatedDocument.objects.create(source=old_doc, target=older_doc.docalias_set.first(), relationship_id='replaces') - RelatedDocument.objects.create(source=doc, target=old_doc.docalias_set.first(), relationship_id='replaces') + RelatedDocument.objects.create(source=old_doc, target=older_doc.docalias.first(), relationship_id='replaces') + RelatedDocument.objects.create(source=doc, target=old_doc.docalias.first(), relationship_id='replaces') review_req.doc = older_doc review_req.save() diff --git a/ietf/doc/tests_status_change.py b/ietf/doc/tests_status_change.py index 937191d6c..30477b9e8 100644 --- a/ietf/doc/tests_status_change.py +++ b/ietf/doc/tests_status_change.py @@ -74,7 +74,7 @@ class StatusChangeTests(TestCase): self.assertEqual(status_change.rev,u'00') self.assertEqual(status_change.ad.name,u'AreaĆ° Irector') self.assertEqual(status_change.notify,u'ipu@ietf.org') - self.assertTrue(status_change.relateddocument_set.filter(relationship__slug='tois',target__document__name='draft-ietf-random-thing')) + self.assertTrue(status_change.relateddocument_set.filter(relationship__slug='tois',target__docs__name='draft-ietf-random-thing')) def test_change_state(self): diff --git a/ietf/doc/utils.py b/ietf/doc/utils.py index c5a05ad1e..d07d158c1 100644 --- a/ietf/doc/utils.py +++ b/ietf/doc/utils.py @@ -684,10 +684,8 @@ def extract_complete_replaces_ancestor_mapping_for_docs(names): if not front: break - relations = RelatedDocument.objects.filter( - source__name__in=front, relationship="replaces" - ).select_related("target").values_list("source__name", "target__document__name") - + relations = ( RelatedDocument.objects.filter(source__name__in=front, relationship="replaces") + .select_related("target").values_list("source__name", "target__docs__name") ) if not relations: break diff --git a/ietf/doc/utils_search.py b/ietf/doc/utils_search.py index d042616d1..f99b7a24f 100644 --- a/ietf/doc/utils_search.py +++ b/ietf/doc/utils_search.py @@ -49,7 +49,7 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False): doc_dict = dict((d.pk, d) for d in docs) doc_ids = doc_dict.keys() - rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", document__id__in=doc_ids).values_list("document__id", "name")) + rfc_aliases = dict([ (a.document.id, a.name) for a in DocAlias.objects.filter(name__startswith="rfc", docs__id__in=doc_ids) ]) # latest event cache event_types = ("published_rfc", @@ -122,11 +122,10 @@ def fill_in_document_table_attributes(docs, have_telechat_date=False): d.updated_by_list = [] xed_by = RelatedDocument.objects.filter(target__name__in=rfc_aliases.values(), - relationship__in=("obs", "updates")).select_related('target__document') - rel_rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", - document__in=[rel.source_id for rel in xed_by]).values_list('document', 'name')) + relationship__in=("obs", "updates")).select_related('target') + rel_rfc_aliases = dict([ (a.document.id, a.name) for a in DocAlias.objects.filter(name__startswith="rfc", docs__id__in=[rel.source_id for rel in xed_by]) ]) for rel in xed_by: - d = doc_dict[rel.target.document_id] + d = doc_dict[rel.target.document.id] if rel.relationship_id == "obs": l = d.obsoleted_by_list elif rel.relationship_id == "updates": @@ -146,7 +145,7 @@ def prepare_document_table(request, docs, query=None, max_results=200): # the number of queries docs = docs.select_related("ad", "std_level", "intended_std_level", "group", "stream", "shepherd", ) docs = docs.prefetch_related("states__type", "tags", "groupmilestone_set__group", "reviewrequest_set__team", - "submission_set__checks", "ad__email_set", "docalias_set__iprdocrel_set") + "submission_set__checks", "ad__email_set", "docalias__iprdocrel_set") if docs.count() > max_results: docs = docs[:max_results] diff --git a/ietf/doc/views_charter.py b/ietf/doc/views_charter.py index 39e8eac99..8aae5b259 100644 --- a/ietf/doc/views_charter.py +++ b/ietf/doc/views_charter.py @@ -392,7 +392,7 @@ def submit(request, name, option=None): abstract=group.name, rev=next_rev, ) - DocAlias.objects.create(name=charter.name, document=charter) + DocAlias.objects.create(name=charter.name).docs.add(charter) charter.set_state(State.objects.get(used=True, type="charter", slug="notrev")) diff --git a/ietf/doc/views_conflict_review.py b/ietf/doc/views_conflict_review.py index 350d5a4c4..5705bbf39 100644 --- a/ietf/doc/views_conflict_review.py +++ b/ietf/doc/views_conflict_review.py @@ -388,7 +388,7 @@ def start_review_sanity_check(request, name): raise Http404 # sanity check that there's not already a conflict review document for this document - if [ rel.source for alias in doc_to_review.docalias_set.all() for rel in alias.relateddocument_set.filter(relationship='conflrev') ]: + if [ rel.source for alias in doc_to_review.docalias.all() for rel in alias.relateddocument_set.filter(relationship='conflrev') ]: raise Http404 return doc_to_review @@ -421,7 +421,8 @@ def build_conflict_review_document(login, doc_to_review, ad, notify, create_in_s ) conflict_review.set_state(create_in_state) - DocAlias.objects.create( name=review_name , document=conflict_review ) + DocAlias.objects.create( name=review_name).docs.add( conflict_review ) + conflict_review.relateddocument_set.create(target=DocAlias.objects.get(name=doc_to_review.name),relationship_id='conflrev') diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py index cd2ee59a9..444d071f0 100644 --- a/ietf/doc/views_doc.py +++ b/ietf/doc/views_doc.py @@ -103,7 +103,7 @@ def document_main(request, name, rev=None): doc = get_object_or_404(Document.objects.select_related(), docalias__name=name) # take care of possible redirections - aliases = DocAlias.objects.filter(document=doc).values_list("name", flat=True) + aliases = DocAlias.objects.filter(docs=doc).values_list("name", flat=True) if rev==None and doc.type_id == "draft" and not name.startswith("rfc"): for a in aliases: if a.startswith("rfc"): @@ -714,7 +714,7 @@ def document_history(request, name): if doc.get_state_slug() == "rfc": e = doc.latest_event(type="published_rfc") - aliases = doc.docalias_set.filter(name__startswith="rfc") + aliases = doc.docalias.filter(name__startswith="rfc") if aliases: name = aliases[0].name diff_revisions.append((name, "", e.time if e else doc.time, name)) @@ -1009,7 +1009,7 @@ def document_json(request, name, rev=None): data["expires"] = doc.expires.strftime("%Y-%m-%d %H:%M:%S") if doc.expires else None data["title"] = doc.title data["abstract"] = doc.abstract - data["aliases"] = list(doc.docalias_set.values_list("name", flat=True)) + data["aliases"] = list(doc.docalias.values_list("name", flat=True)) data["state"] = extract_name(doc.get_state()) data["intended_std_level"] = extract_name(doc.intended_std_level) data["std_level"] = extract_name(doc.std_level) diff --git a/ietf/doc/views_material.py b/ietf/doc/views_material.py index dbbc98369..d270e5cd1 100644 --- a/ietf/doc/views_material.py +++ b/ietf/doc/views_material.py @@ -142,7 +142,8 @@ def edit_material(request, name=None, acronym=None, action=None, doc_type=None): dest.write(chunk) if action == "new": - DocAlias.objects.get_or_create(name=doc.name, document=doc) + alias, __ = DocAlias.objects.get_or_create(name=doc.name) + alias.docs.add(doc) if prev_rev != doc.rev: e = NewRevisionDocEvent(type="new_revision", doc=doc, rev=doc.rev) diff --git a/ietf/doc/views_review.py b/ietf/doc/views_review.py index 8101226b7..2c00abe63 100644 --- a/ietf/doc/views_review.py +++ b/ietf/doc/views_review.py @@ -593,7 +593,7 @@ def complete_review(request, name, assignment_id): name = "-".join(c for c in name_components if c).lower() if not Document.objects.filter(name=name).exists(): review = Document.objects.create(name=name) - DocAlias.objects.create(document=review, name=review.name) + DocAlias.objects.create(name=review.name).docs.add(review) break review.type = DocTypeName.objects.get(slug="review") diff --git a/ietf/doc/views_search.py b/ietf/doc/views_search.py index f91a20254..f93f139d9 100644 --- a/ietf/doc/views_search.py +++ b/ietf/doc/views_search.py @@ -478,7 +478,7 @@ def index_all_drafts(request): else: heading = "%s Internet-Drafts" % state.name - draft_names = DocAlias.objects.filter(document__states=state).values_list("name", "document__name") + draft_names = DocAlias.objects.filter(docs__states=state).values_list("name", "docs__name") names = [] names_to_skip = set() @@ -528,7 +528,7 @@ def ajax_select2_search_docs(request, model_name, doc_type): if model == Document: qs = qs.filter(type=doc_type) elif model == DocAlias: - qs = qs.filter(document__type=doc_type) + qs = qs.filter(docs__type=doc_type) for t in q: qs = qs.filter(name__icontains=t) diff --git a/ietf/doc/views_status_change.py b/ietf/doc/views_status_change.py index 5be43e3c7..f1f4b7080 100644 --- a/ietf/doc/views_status_change.py +++ b/ietf/doc/views_status_change.py @@ -527,7 +527,7 @@ def start_rfc_status_change(request,name): ) status_change.set_state(form.cleaned_data['create_in_state']) - DocAlias.objects.create( name= 'status-change-'+form.cleaned_data['document_name'], document=status_change ) + DocAlias.objects.create( name= 'status-change-'+form.cleaned_data['document_name']).docs.add(status_change) for key in form.cleaned_data['relations']: status_change.relateddocument_set.create(target=DocAlias.objects.get(name=key), diff --git a/ietf/group/dot.py b/ietf/group/dot.py index 00a65f733..adafb111e 100644 --- a/ietf/group/dot.py +++ b/ietf/group/dot.py @@ -100,7 +100,7 @@ def get_node_styles(node, group): def make_dot(group): references = Q(source__group=group, source__type='draft', relationship__slug__startswith='ref') - both_rfcs = Q(source__states__slug='rfc', target__document__states__slug='rfc') + both_rfcs = Q(source__states__slug='rfc', target__docs__states__slug='rfc') inactive = Q(source__states__slug__in=['expired', 'repl']) attractor = Q(target__name__in=['rfc5000', 'rfc5741']) removed = Q(source__states__slug__in=['auth-rm', 'ietf-rm']) @@ -114,7 +114,7 @@ def make_dot(group): edges.add(Edge(x)) replacements = RelatedDocument.objects.filter(relationship__slug='replaces', - target__document__in=[x.relateddocument.target.document for x in edges]) + target__docs__in=[x.relateddocument.target.document for x in edges]) for x in replacements: edges.add(Edge(x)) diff --git a/ietf/group/tests.py b/ietf/group/tests.py index 752eb2584..bae5be447 100644 --- a/ietf/group/tests.py +++ b/ietf/group/tests.py @@ -71,7 +71,7 @@ class GroupDocDependencyGraphTests(TestCase): set_coverage_checking(False) a = WgDraftFactory() b = WgDraftFactory() - RelatedDocument.objects.create(source=a,target=b.docalias_set.first(),relationship_id='normref') + RelatedDocument.objects.create(source=a,target=b.docalias.first(),relationship_id='normref') def tearDown(self): set_coverage_checking(True) diff --git a/ietf/group/tests_info.py b/ietf/group/tests_info.py index c6e7bf186..89d35b5fa 100644 --- a/ietf/group/tests_info.py +++ b/ietf/group/tests_info.py @@ -325,7 +325,7 @@ class GroupPagesTests(TestCase): type_id="slides", ) doc.set_state(State.objects.get(type="slides", slug="active")) - DocAlias.objects.create(name=doc.name, document=doc) + DocAlias.objects.create(name=doc.name).docs.add(doc) for url in group_urlreverse_list(group, 'ietf.group.views.materials'): r = self.client.get(url) diff --git a/ietf/group/views.py b/ietf/group/views.py index 18c407de4..6fce21fd4 100644 --- a/ietf/group/views.py +++ b/ietf/group/views.py @@ -188,7 +188,7 @@ def fill_in_wg_roles(group): group.secretaries = get_roles("secr", []) def fill_in_wg_drafts(group): - aliases = DocAlias.objects.filter(document__type="draft", document__group=group).select_related('document').order_by("name") + aliases = DocAlias.objects.filter(docs__type="draft", docs__group=group).prefetch_related('docs').order_by("name") group.drafts = [] group.rfcs = [] for a in aliases: @@ -804,7 +804,7 @@ def group_photos(request, group_type=None, acronym=None): # charter.set_state(State.objects.get(used=True, type="charter", slug="notrev")) # # # Create an alias as well -# DocAlias.objects.create(name=charter.name, document=charter) +# DocAlias.objects.create(name=charter.name).docs.add(charter) # # return charter # diff --git a/ietf/idindex/index.py b/ietf/idindex/index.py index d97f9b544..8eb0f6e6b 100644 --- a/ietf/idindex/index.py +++ b/ietf/idindex/index.py @@ -29,9 +29,9 @@ def all_id_txt(): return t.strftime("%Y-%m-%d") if t else "" rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", - document__states=State.objects.get(type="draft", slug="rfc")).values_list("document__name", "name")) + docs__states=State.objects.get(type="draft", slug="rfc")).values_list("docs__name", "name")) - replacements = dict(RelatedDocument.objects.filter(target__document__states=State.objects.get(type="draft", slug="repl"), + replacements = dict(RelatedDocument.objects.filter(target__docs__states=State.objects.get(type="draft", slug="repl"), relationship="replaces").values_list("target__name", "source__name")) @@ -110,9 +110,9 @@ def all_id2_txt(): drafts = drafts.prefetch_related("states") rfc_aliases = dict(DocAlias.objects.filter(name__startswith="rfc", - document__states=State.objects.get(type="draft", slug="rfc")).values_list("document__name", "name")) + docs__states=State.objects.get(type="draft", slug="rfc")).values_list("docs__name", "name")) - replacements = dict(RelatedDocument.objects.filter(target__document__states=State.objects.get(type="draft", slug="repl"), + replacements = dict(RelatedDocument.objects.filter(target__docs__states=State.objects.get(type="draft", slug="repl"), relationship="replaces").values_list("target__name", "source__name")) revision_time = dict(DocEvent.objects.filter(type="new_revision", doc__name__startswith="draft-").order_by('time').values_list("doc__name", "time")) diff --git a/ietf/idindex/tests.py b/ietf/idindex/tests.py index d4979087e..2412e7c76 100644 --- a/ietf/idindex/tests.py +++ b/ietf/idindex/tests.py @@ -47,7 +47,7 @@ class IndexTests(TestCase): # published draft.set_state(State.objects.get(type="draft", slug="rfc")) - DocAlias.objects.create(name="rfc1234", document=draft) + DocAlias.objects.create(name="rfc1234").docs.add(draft) txt = all_id_txt() self.assertTrue(draft.name + "-" + draft.rev in txt) @@ -59,7 +59,7 @@ class IndexTests(TestCase): RelatedDocument.objects.create( relationship=DocRelationshipName.objects.get(slug="replaces"), source=Document.objects.create(type_id="draft", rev="00", name="draft-test-replacement"), - target=draft.docalias_set.get(name__startswith="draft")) + target=draft.docalias.get(name__startswith="draft")) txt = all_id_txt() self.assertTrue(draft.name + "-" + draft.rev in txt) @@ -109,7 +109,7 @@ class IndexTests(TestCase): # test RFC draft.set_state(State.objects.get(type="draft", slug="rfc")) - DocAlias.objects.create(name="rfc1234", document=draft) + DocAlias.objects.create(name="rfc1234").docs.add(draft) t = get_fields(all_id2_txt()) self.assertEqual(t[4], "1234") @@ -118,7 +118,7 @@ class IndexTests(TestCase): RelatedDocument.objects.create( relationship=DocRelationshipName.objects.get(slug="replaces"), source=Document.objects.create(type_id="draft", rev="00", name="draft-test-replacement"), - target=draft.docalias_set.get(name__startswith="draft")) + target=draft.docalias.get(name__startswith="draft")) t = get_fields(all_id2_txt()) self.assertEqual(t[5], "draft-test-replacement") diff --git a/ietf/iesg/tests.py b/ietf/iesg/tests.py index 16a738512..5a8e91751 100644 --- a/ietf/iesg/tests.py +++ b/ietf/iesg/tests.py @@ -92,7 +92,7 @@ class IESGAgendaTests(TestCase): mars = GroupFactory(acronym='mars',parent=Group.objects.get(acronym='farfut')) wgdraft = WgDraftFactory(name='draft-ietf-mars-test', group=mars, intended_std_level_id='ps') rfc = IndividualRfcFactory.create(stream_id='irtf', other_aliases=['rfc6666',], states=[('draft','rfc'),('draft-iesg','pub')], std_level_id='inf', ) - wgdraft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'), relationship_id='refnorm') + wgdraft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'), relationship_id='refnorm') ise_draft = IndividualDraftFactory(name='draft-imaginary-independent-submission') ise_draft.stream = StreamName.objects.get(slug="ise") ise_draft.save_with_history([DocEvent(doc=ise_draft, rev=ise_draft.rev, type="changed_stream", by=Person.objects.get(user__username="secretary"), desc="Test")]) @@ -216,7 +216,7 @@ class IESGAgendaTests(TestCase): relation = RelatedDocument.objects.create( source=statchg, - target=DocAlias.objects.filter(name__startswith='rfc', document__std_level="ps")[0], + target=DocAlias.objects.filter(name__startswith='rfc', docs__std_level="ps")[0], relationship_id="tohist") statchg.group = Group.objects.get(acronym="mars") @@ -234,7 +234,7 @@ class IESGAgendaTests(TestCase): self.assertTrue(statchg in agenda_data(date_str)["sections"]["2.3.3"]["docs"]) # 3.3 document status changes - relation.target = DocAlias.objects.filter(name__startswith='rfc', document__std_level="inf")[0] + relation.target = DocAlias.objects.filter(name__startswith='rfc', docs__std_level="inf")[0] relation.save() statchg.group = Group.objects.get(acronym="mars") diff --git a/ietf/ipr/admin.py b/ietf/ipr/admin.py index 2656dce90..c22a57f40 100644 --- a/ietf/ipr/admin.py +++ b/ietf/ipr/admin.py @@ -91,7 +91,7 @@ admin.site.register(IprDocRel, IprDocRelAdmin) class RelatedIprAdmin(admin.ModelAdmin): list_display = ['source', 'target', 'relationship', ] - search_fields = ['source__name', 'target__name', 'target__document__name', ] + search_fields = ['source__name', 'target__name', 'target__docs__name', ] raw_id_fields = ['source', 'target', ] admin.site.register(RelatedIpr, RelatedIprAdmin) diff --git a/ietf/ipr/factories.py b/ietf/ipr/factories.py index f7c333625..8758b5fc7 100644 --- a/ietf/ipr/factories.py +++ b/ietf/ipr/factories.py @@ -34,7 +34,7 @@ class IprDisclosureBaseFactory(factory.DjangoModelFactory): return if extracted: for doc in extracted: - IprDocRel.objects.create(disclosure=self,document=doc.docalias_set.first()) + IprDocRel.objects.create(disclosure=self,document=doc.docalias.first()) @factory.post_generation def updates(self, create, extracted, **kwargs): diff --git a/ietf/ipr/tests.py b/ietf/ipr/tests.py index fe03a3c28..4870170d8 100644 --- a/ietf/ipr/tests.py +++ b/ietf/ipr/tests.py @@ -157,7 +157,7 @@ class IprTests(TestCase): self.assertTrue(draft.name in unicontent(r)) self.assertTrue(ipr.title not in unicontent(r)) - DocAlias.objects.create(name="rfc321", document=draft) + DocAlias.objects.create(name="rfc321").docs.add(draft) # find RFC r = self.client.get(url + "?submit=rfc&rfc=321") @@ -260,7 +260,7 @@ class IprTests(TestCase): "ietfer_contact_info": "555-555-0101", "iprdocrel_set-TOTAL_FORMS": 2, "iprdocrel_set-INITIAL_FORMS": 0, - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().name, + "iprdocrel_set-0-document": "%s" % draft.docalias.first().name, "iprdocrel_set-0-revisions": '00', "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().name, "patent_number": "SE12345678901", @@ -303,7 +303,7 @@ class IprTests(TestCase): "ietfer_contact_info": "555-555-0101", "iprdocrel_set-TOTAL_FORMS": 2, "iprdocrel_set-INITIAL_FORMS": 0, - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().name, + "iprdocrel_set-0-document": "%s" % draft.docalias.first().name, "iprdocrel_set-0-revisions": '00', "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().name, "patent_number": "SE12345678901", @@ -351,7 +351,7 @@ class IprTests(TestCase): "holder_legal_name": "Test Legal", "ietfer_contact_info": "555-555-0101", "ietfer_name": "Test Participant", - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().name, + "iprdocrel_set-0-document": "%s" % draft.docalias.first().name, "iprdocrel_set-0-revisions": '00', "iprdocrel_set-INITIAL_FORMS": 0, "iprdocrel_set-TOTAL_FORMS": 1, @@ -400,7 +400,7 @@ class IprTests(TestCase): "ietfer_contact_info": "555-555-0101", "iprdocrel_set-TOTAL_FORMS": 2, "iprdocrel_set-INITIAL_FORMS": 0, - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().name, + "iprdocrel_set-0-document": "%s" % draft.docalias.first().name, "iprdocrel_set-0-revisions": '00', "iprdocrel_set-1-document": DocAlias.objects.filter(name__startswith="rfc").first().name, "patent_number": "SE12345678901", @@ -438,7 +438,7 @@ class IprTests(TestCase): "holder_contact_email": "test@holder.com", "iprdocrel_set-TOTAL_FORMS": 1, "iprdocrel_set-INITIAL_FORMS": 0, - "iprdocrel_set-0-document": "%s" % draft.docalias_set.first().name, + "iprdocrel_set-0-document": "%s" % draft.docalias.first().name, "iprdocrel_set-0-revisions": '00', "patent_number": "SE12345678901", "patent_inventor": "A. Nonymous", diff --git a/ietf/ipr/utils.py b/ietf/ipr/utils.py index 04bab1e39..2cb05aa29 100644 --- a/ietf/ipr/utils.py +++ b/ietf/ipr/utils.py @@ -1,3 +1,8 @@ +# Copyright The IETF Trust 2014-2019, All Rights Reserved +# -*- coding: utf-8 -*- + +import debug # pyflakes:ignore + def get_genitive(name): """Return the genitive form of name""" return name + "'" if name.endswith('s') else name + "'s" @@ -29,23 +34,30 @@ def iprs_from_docs(aliases,**kwargs): """Returns a list of IPRs related to doc aliases""" iprdocrels = [] for alias in aliases: - if alias.document.ipr(**kwargs): - iprdocrels += alias.document.ipr(**kwargs) + for document in alias.docs.all(): + if document.ipr(**kwargs): + iprdocrels += document.ipr(**kwargs) return list(set([i.disclosure for i in iprdocrels])) def related_docs(alias, relationship=('replaces', 'obs')): """Returns list of related documents""" - results = list(alias.document.docalias_set.all()) + + results = [] + for doc in alias.docs.all(): + results += list(doc.docalias.all()) - rels = alias.document.all_relations_that_doc(relationship) + rels = [] + for doc in alias.docs.all(): + rels += list(doc.all_relations_that_doc(relationship)) for rel in rels: - rel_aliases = list(rel.target.document.docalias_set.all()) + rel_aliases = list(rel.target.document.docalias.all()) for x in rel_aliases: x.related = rel x.relation = rel.relationship.revname results += rel_aliases + return list(set(results)) diff --git a/ietf/ipr/views.py b/ietf/ipr/views.py index c5d9614df..4f150d016 100644 --- a/ietf/ipr/views.py +++ b/ietf/ipr/views.py @@ -460,16 +460,16 @@ def by_draft_recursive_txt(request): for o in IprDocRel.objects.filter(disclosure__state='posted').select_related('document'): alias = o.document - document = alias.document name = alias.name - related = set(document.docalias_set.all()) | set(document.all_related_that_doc(('obs', 'replaces'))) - for alias in related: - name = alias.name - if name.startswith("rfc"): - name = name.upper() - if not name in docipr: - docipr[name] = [] - docipr[name].append(o.disclosure_id) + for document in alias.docs.all(): + related = set(document.docalias.all()) | set(document.all_related_that_doc(('obs', 'replaces'))) + for alias in related: + name = alias.name + if name.startswith("rfc"): + name = name.upper() + if not name in docipr: + docipr[name] = [] + docipr[name].append(o.disclosure_id) lines = [ u"# Machine-readable list of IPR disclosures by draft name" ] for name, iprs in docipr.iteritems(): @@ -700,7 +700,7 @@ def search(request): # Search by wg acronym # Document list with IPRs elif search_type == "group": - docs = list(DocAlias.objects.filter(document__group=q)) + docs = list(DocAlias.objects.filter(docs__group=q)) related = [] for doc in docs: doc.product_of_this_wg = True @@ -714,7 +714,7 @@ def search(request): # Search by rfc and id title # Document list with IPRs elif search_type == "doctitle": - docs = list(DocAlias.objects.filter(document__title__icontains=q)) + docs = list(DocAlias.objects.filter(docs__title__icontains=q)) related = [] for doc in docs: related += related_docs(doc) diff --git a/ietf/liaisons/forms.py b/ietf/liaisons/forms.py index b059ed5f2..8ec66e40a 100644 --- a/ietf/liaisons/forms.py +++ b/ietf/liaisons/forms.py @@ -25,7 +25,7 @@ from ietf.liaisons.fields import SearchableLiaisonStatementsField from ietf.group.models import Group from ietf.person.models import Email from ietf.person.fields import SearchableEmailField -from ietf.doc.models import Document +from ietf.doc.models import Document, DocAlias from ietf.utils.fields import DatepickerDateField ''' @@ -370,7 +370,7 @@ class LiaisonModelForm(BetterModelForm): ) ) if created: - attach.docalias_set.create(name=attach.name) + DocAlias.objects.create(name=attach.name).docs.add(attach) LiaisonStatementAttachment.objects.create(statement=self.instance,document=attach) attach_file = open(os.path.join(settings.LIAISON_ATTACH_PATH, attach.name + extension), 'w') attach_file.write(attached_file.read()) diff --git a/ietf/meeting/forms.py b/ietf/meeting/forms.py index 645ad6b40..3a1a3ae5e 100644 --- a/ietf/meeting/forms.py +++ b/ietf/meeting/forms.py @@ -271,7 +271,7 @@ class InterimSessionModelForm(forms.ModelForm): # FIXME: What about agendas in html or markdown format? uploaded_filename='{}-00.txt'.format(filename)) doc.set_state(State.objects.get(type__slug=doc.type.slug, slug='active')) - DocAlias.objects.create(name=doc.name, document=doc) + DocAlias.objects.create(name=doc.name).docs.add(doc) self.instance.sessionpresentation_set.create(document=doc, rev=doc.rev) NewRevisionDocEvent.objects.create( type='new_revision', diff --git a/ietf/meeting/views.py b/ietf/meeting/views.py index 19de5cf03..57d906da1 100644 --- a/ietf/meeting/views.py +++ b/ietf/meeting/views.py @@ -38,7 +38,7 @@ from django.views.generic import RedirectView from ietf.doc.fields import SearchableDocumentsField -from ietf.doc.models import Document, State, DocEvent, NewRevisionDocEvent +from ietf.doc.models import Document, State, DocEvent, NewRevisionDocEvent, DocAlias from ietf.group.models import Group from ietf.group.utils import can_manage_materials from ietf.ietfauth.utils import role_required, has_role @@ -1218,7 +1218,7 @@ def upload_session_bluesheets(request, session_id, num): rev = '00', ) doc.states.add(State.objects.get(type_id='bluesheets',slug='active')) - doc.docalias_set.create(name=doc.name) + DocAlias.objects.create(name=doc.name).docs.add(doc) session.sessionpresentation_set.create(document=doc,rev='00') filename = '%s-%s%s'% ( doc.name, doc.rev, ext) doc.uploaded_filename = filename @@ -1307,7 +1307,7 @@ def upload_session_minutes(request, session_id, num): group = session.group, rev = '00', ) - doc.docalias_set.create(name=doc.name) + DocAlias.objects.create(name=doc.name).docs.add(doc) doc.states.add(State.objects.get(type_id='minutes',slug='active')) if session.sessionpresentation_set.filter(document=doc).exists(): sp = session.sessionpresentation_set.get(document=doc) @@ -1410,7 +1410,7 @@ def upload_session_agenda(request, session_id, num): group = session.group, rev = '00', ) - doc.docalias_set.create(name=doc.name) + DocAlias.objects.create(name=doc.name).docs.add(doc) doc.states.add(State.objects.get(type_id='agenda',slug='active')) if session.sessionpresentation_set.filter(document=doc).exists(): sp = session.sessionpresentation_set.get(document=doc) @@ -1513,7 +1513,7 @@ def upload_session_slides(request, session_id, num, name): group = session.group, rev = '00', ) - doc.docalias_set.create(name=doc.name) + DocAlias.objects.create(name=doc.name).docs.add(doc) doc.states.add(State.objects.get(type_id='slides',slug='active')) doc.states.add(State.objects.get(type_id='reuse_policy',slug='single')) if session.sessionpresentation_set.filter(document=doc).exists(): @@ -2448,7 +2448,7 @@ def approve_proposed_slides(request, slidesubmission_id, num): group = submission.session.group, rev = '00', ) - doc.docalias_set.create(name=doc.name) + DocAlias.objects.create(name=doc.name).docs.add(doc) doc.states.add(State.objects.get(type_id='slides',slug='active')) doc.states.add(State.objects.get(type_id='reuse_policy',slug='single')) if submission.session.sessionpresentation_set.filter(document=doc).exists(): diff --git a/ietf/review/utils.py b/ietf/review/utils.py index 5b8ce5bc5..3d2754423 100644 --- a/ietf/review/utils.py +++ b/ietf/review/utils.py @@ -834,7 +834,7 @@ def make_assignment_choices(email_queryset, review_req): possible_emails = list(email_queryset) possible_person_ids = [e.person_id for e in possible_emails] - aliases = DocAlias.objects.filter(document=doc).values_list("name", flat=True) + aliases = DocAlias.objects.filter(docs=doc).values_list("name", flat=True) # settings reviewer_settings = { diff --git a/ietf/secr/drafts/views.py b/ietf/secr/drafts/views.py index 3c0b0f621..524e9f47a 100644 --- a/ietf/secr/drafts/views.py +++ b/ietf/secr/drafts/views.py @@ -579,7 +579,7 @@ def view(request, id): draft.rfc_number = get_rfc_num(draft) # check for replaced bys - qs = Document.objects.filter(relateddocument__target__document=draft, relateddocument__relationship='replaces') + qs = Document.objects.filter(relateddocument__target__docs=draft, relateddocument__relationship='replaces') if qs: draft.replaced_by = qs[0] diff --git a/ietf/secr/proceedings/proc_utils.py b/ietf/secr/proceedings/proc_utils.py index f696c5e27..5a4e5245b 100644 --- a/ietf/secr/proceedings/proc_utils.py +++ b/ietf/secr/proceedings/proc_utils.py @@ -113,10 +113,10 @@ def attach_recording(doc, sessions): document=doc, rev=doc.rev) session.sessionpresentation_set.add(presentation) - if not doc.docalias_set.filter(name__startswith='recording-{}-{}'.format(session.meeting.number,session.group.acronym)): + if not doc.docalias.filter(name__startswith='recording-{}-{}'.format(session.meeting.number,session.group.acronym)): sequence = get_next_sequence(session.group,session.meeting,'recording') name = 'recording-{}-{}-{}'.format(session.meeting.number,session.group.acronym,sequence) - doc.docalias_set.create(name=name) + DocAlias.objects.create(name=name).docs.add(doc) def normalize_room_name(name): '''Returns room name converted to be used as portion of filename''' @@ -150,7 +150,7 @@ def create_recording(session, url, title=None, user=None): type_id='recording') doc.set_state(State.objects.get(type='recording', slug='active')) - doc.docalias_set.create(name=name) + DocAlias.objects.create(name=doc.name).docs.add(doc) # create DocEvent NewRevisionDocEvent.objects.create(type='new_revision', diff --git a/ietf/secr/proceedings/tests.py b/ietf/secr/proceedings/tests.py index 8da4b99a8..5997c6463 100644 --- a/ietf/secr/proceedings/tests.py +++ b/ietf/secr/proceedings/tests.py @@ -132,8 +132,8 @@ class RecordingTestCase(TestCase): import_audio_files(meeting) doc = mars_session.materials.filter(type='recording').first() self.assertTrue(doc in ames_session.materials.all()) - self.assertTrue(doc.docalias_set.filter(name='recording-42-mars-1')) - self.assertTrue(doc.docalias_set.filter(name='recording-42-ames-1')) + self.assertTrue(doc.docalias.filter(name='recording-42-mars-1')) + self.assertTrue(doc.docalias.filter(name='recording-42-ames-1')) def test_normalize_room_name(self): self.assertEqual(normalize_room_name('Test Room'),'testroom') diff --git a/ietf/secr/telechat/tests.py b/ietf/secr/telechat/tests.py index 3dd066e6e..8c01842b8 100644 --- a/ietf/secr/telechat/tests.py +++ b/ietf/secr/telechat/tests.py @@ -63,7 +63,7 @@ class SecrTelechatTestCase(TestCase): draft = WgDraftFactory(ad=ad, intended_std_level_id='ps', states=[('draft-iesg','pub-req'),]) rfc = IndividualRfcFactory.create(stream_id='irtf', other_aliases=['rfc6666',], states=[('draft','rfc'),('draft-iesg','pub')], std_level_id='inf', ) - draft.relateddocument_set.create(target=rfc.docalias_set.get(name='rfc6666'), + draft.relateddocument_set.create(target=rfc.docalias.get(name='rfc6666'), relationship_id='refnorm') create_ballot_if_not_open(None, draft, ad, 'approve') d = get_next_telechat_date() diff --git a/ietf/secr/utils/document.py b/ietf/secr/utils/document.py index 535758425..ecdc1166f 100644 --- a/ietf/secr/utils/document.py +++ b/ietf/secr/utils/document.py @@ -10,11 +10,11 @@ def get_full_path(doc): return os.path.join(doc.get_file_path(), doc.uploaded_filename) def get_rfc_num(doc): - qs = doc.docalias_set.filter(name__startswith='rfc') + qs = doc.docalias.filter(name__startswith='rfc') return qs[0].name[3:] if qs else None def is_draft(doc): - if doc.docalias_set.filter(name__startswith='rfc'): + if doc.docalias.filter(name__startswith='rfc'): return False else: return True diff --git a/ietf/stats/backfill_data.py b/ietf/stats/backfill_data.py index 8af30442f..88819adb0 100755 --- a/ietf/stats/backfill_data.py +++ b/ietf/stats/backfill_data.py @@ -68,9 +68,9 @@ def unicode(text): start = time.time() say("Running query for documents to process ...") -for doc in docs_qs.prefetch_related("docalias_set", "formal_languages", "documentauthor_set", "documentauthor_set__person", "documentauthor_set__person__alias_set"): +for doc in docs_qs.prefetch_related("docalias", "formal_languages", "documentauthor_set", "documentauthor_set__person", "documentauthor_set__person__alias_set"): canonical_name = doc.name - for n in doc.docalias_set.all(): + for n in doc.docalias.all(): if n.name.startswith("rfc"): canonical_name = n.name diff --git a/ietf/stats/tests.py b/ietf/stats/tests.py index 13656a723..c2ca7ccec 100644 --- a/ietf/stats/tests.py +++ b/ietf/stats/tests.py @@ -71,10 +71,10 @@ class StatisticsTests(TestCase): words=100 ) referencing_draft.set_state(State.objects.get(used=True, type="draft", slug="active")) - DocAlias.objects.create(document=referencing_draft, name=referencing_draft.name) + DocAlias.objects.create(name=referencing_draft.name).docs.add(referencing_draft) RelatedDocument.objects.create( source=referencing_draft, - target=draft.docalias_set.first(), + target=draft.docalias.first(), relationship=DocRelationshipName.objects.get(slug="refinfo") ) NewRevisionDocEvent.objects.create( diff --git a/ietf/stats/views.py b/ietf/stats/views.py index 4eeac6506..baf888d7d 100644 --- a/ietf/stats/views.py +++ b/ietf/stats/views.py @@ -205,13 +205,13 @@ def document_stats(request, stats_type=None): if any(stats_type == t[0] for t in possible_document_stats_types): # filter documents - docalias_filters = Q(document__type="draft") + docalias_filters = Q(docs__type="draft") rfc_state = State.objects.get(type="draft", slug="rfc") if document_type == "rfc": - docalias_filters &= Q(document__states=rfc_state) + docalias_filters &= Q(docs__states=rfc_state) elif document_type == "draft": - docalias_filters &= ~Q(document__states=rfc_state) + docalias_filters &= ~Q(docs__states=rfc_state) if from_time: # this is actually faster than joining in the database, @@ -222,7 +222,7 @@ def document_stats(request, stats_type=None): docevent__type__in=["published_rfc", "new_revision"], ).values_list("pk")) - docalias_filters &= Q(document__in=docs_within_time_constraint) + docalias_filters &= Q(docs__in=docs_within_time_constraint) docalias_qs = DocAlias.objects.filter(docalias_filters) @@ -233,10 +233,10 @@ def document_stats(request, stats_type=None): else: doc_label = "document" - total_docs = docalias_qs.values_list("document").distinct().count() + total_docs = docalias_qs.values_list("docs__name").distinct().count() def generate_canonical_names(docalias_qs): - for doc_id, ts in itertools.groupby(docalias_qs.order_by("document"), lambda t: t[0]): + for doc_id, ts in itertools.groupby(docalias_qs.order_by("docs__name"), lambda t: t[0]): chosen = None for t in ts: if chosen is None: @@ -254,7 +254,7 @@ def document_stats(request, stats_type=None): bins = defaultdict(set) - for name, canonical_name, author_count in generate_canonical_names(docalias_qs.values_list("document", "name").annotate(Count("document__documentauthor"))): + for name, canonical_name, author_count in generate_canonical_names(docalias_qs.values_list("docs__name", "name").annotate(Count("docs__documentauthor"))): bins[author_count].add(canonical_name) series_data = [] @@ -270,7 +270,7 @@ def document_stats(request, stats_type=None): bins = defaultdict(set) - for name, canonical_name, pages in generate_canonical_names(docalias_qs.values_list("document", "name", "document__pages")): + for name, canonical_name, pages in generate_canonical_names(docalias_qs.values_list("docs__name", "name", "docs__pages")): bins[pages].add(canonical_name) series_data = [] @@ -289,7 +289,7 @@ def document_stats(request, stats_type=None): bins = defaultdict(set) - for name, canonical_name, words in generate_canonical_names(docalias_qs.values_list("document", "name", "document__words")): + for name, canonical_name, words in generate_canonical_names(docalias_qs.values_list("docs__name", "name", "docs__words")): bins[put_into_bin(words, bin_size)].add(canonical_name) series_data = [] @@ -314,7 +314,7 @@ def document_stats(request, stats_type=None): submission_types[doc_name] = file_types doc_names_with_missing_types = {} - for doc_name, canonical_name, rev in generate_canonical_names(docalias_qs.values_list("document", "name", "document__rev")): + for doc_name, canonical_name, rev in generate_canonical_names(docalias_qs.values_list("docs__name", "name", "docs__rev")): types = submission_types.get(doc_name) if types: for dot_ext in types.split(","): @@ -359,7 +359,7 @@ def document_stats(request, stats_type=None): bins = defaultdict(set) - for name, canonical_name, formal_language_name in generate_canonical_names(docalias_qs.values_list("document", "name", "document__formal_languages__name")): + for name, canonical_name, formal_language_name in generate_canonical_names(docalias_qs.values_list("docs__name", "name", "docs__formal_languages__name")): bins[formal_language_name].add(canonical_name) series_data = [] diff --git a/ietf/submit/tests.py b/ietf/submit/tests.py index 7f978d4a5..c33f1fe2b 100644 --- a/ietf/submit/tests.py +++ b/ietf/submit/tests.py @@ -224,8 +224,8 @@ class SubmitTests(TestCase): note="", ) sug_replaced_draft.set_state(State.objects.get(used=True, type="draft", slug="active")) - sug_replaced_alias = DocAlias.objects.create(document=sug_replaced_draft, name=sug_replaced_draft.name) - + sug_replaced_alias = DocAlias.objects.create(name=sug_replaced_draft.name) + sug_replaced_alias.docs.add(sug_replaced_draft) name = "draft-ietf-mars-testing-tests" rev = "00" @@ -235,7 +235,7 @@ class SubmitTests(TestCase): # supply submitter info, then draft should be in and ready for approval mailbox_before = len(outbox) - replaced_alias = draft.docalias_set.first() + replaced_alias = draft.docalias.first() r = self.supply_extra_metadata(name, status_url, author.ascii, author.email().address.lower(), replaces=str(replaced_alias.name) + "," + str(sug_replaced_alias.name)) @@ -593,7 +593,7 @@ class SubmitTests(TestCase): rev = '%02d'%(int(draft.rev)+1) status_url, author = self.do_submission(name,rev) mailbox_before = len(outbox) - replaced_alias = draft.docalias_set.first() + replaced_alias = draft.docalias.first() r = self.supply_extra_metadata(name, status_url, "Submitter Name", "author@example.com", replaces=str(replaced_alias.name)) self.assertEqual(r.status_code, 200) self.assertTrue('cannot replace itself' in unicontent(r)) @@ -737,7 +737,7 @@ class SubmitTests(TestCase): "edit-pages": "123", "submitter-name": "Some Random Test Person", "submitter-email": "random@example.com", - "replaces": str(draft.docalias_set.all().first().name), + "replaces": str(draft.docalias.first().name), "edit-note": "no comments", "authors-0-name": "Person 1", "authors-0-email": "person1@example.com", @@ -757,7 +757,7 @@ class SubmitTests(TestCase): self.assertEqual(submission.pages, 123) self.assertEqual(submission.note, "no comments") self.assertEqual(submission.submitter, "Some Random Test Person ") - self.assertEqual(submission.replaces, draft.docalias_set.all().first().name) + self.assertEqual(submission.replaces, draft.docalias.first().name) self.assertEqual(submission.state_id, "manual") authors = submission.authors diff --git a/ietf/submit/utils.py b/ietf/submit/utils.py index 3aa6c05db..43b1b07f2 100644 --- a/ietf/submit/utils.py +++ b/ietf/submit/utils.py @@ -1,8 +1,9 @@ # Copyright The IETF Trust 2011-2019, All Rights Reserved # -*- coding: utf-8 -*- -import os import datetime +import os +import re import six # pyflakes:ignore import xml2rfc @@ -259,7 +260,8 @@ def post_submission(request, submission, approvedDesc): events.append(e) # update related objects - DocAlias.objects.get_or_create(name=submission.name, document=draft) + alias, __ = DocAlias.objects.get_or_create(name=submission.name) + alias.docs.add(draft) draft.set_state(State.objects.get(used=True, type="draft", slug="active")) @@ -373,7 +375,7 @@ def update_replaces_from_submission(request, submission, draft): if request.user.is_authenticated: is_chair_of = list(Group.objects.filter(role__person__user=request.user, role__name="chair")) - replaces = DocAlias.objects.filter(name__in=submission.replaces.split(",")).select_related("document", "document__group") + replaces = DocAlias.objects.filter(name__in=submission.replaces.split(",")).prefetch_related("docs", "docs__group") existing_replaces = list(draft.related_that_doc("replaces")) existing_suggested = set(draft.related_that_doc("possibly-replaces")) diff --git a/ietf/sync/rfceditor.py b/ietf/sync/rfceditor.py index aad98a0e5..834937902 100644 --- a/ietf/sync/rfceditor.py +++ b/ietf/sync/rfceditor.py @@ -370,7 +370,7 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None): # make sure we got the document and alias doc = None name = "rfc%s" % rfc_number - a = DocAlias.objects.filter(name=name).select_related("document") + a = DocAlias.objects.filter(name=name) if a: doc = a[0].document else: @@ -385,7 +385,8 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None): doc = Document.objects.create(name=name, type=DocTypeName.objects.get(slug="draft")) # add alias - DocAlias.objects.get_or_create(name=name, document=doc) + alias, __ = DocAlias.objects.get_or_create(name=name) + alias.docs.add(doc) changes.append("created alias %s" % prettify_std_name(name)) # check attributes @@ -458,7 +459,7 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None): if x[:3] in ("NIC", "IEN", "STD", "RTR"): # try translating this to RFCs that we can handle # sensibly; otherwise we'll have to ignore them - l = DocAlias.objects.filter(name__startswith="rfc", document__docalias__name=x.lower()) + l = DocAlias.objects.filter(name__startswith="rfc", docs__docalias__name=x.lower()) else: l = DocAlias.objects.filter(name=x.lower()) @@ -481,7 +482,7 @@ def update_docs_from_rfc_index(data, skip_older_than_date=None): for a in also: a = a.lower() if not DocAlias.objects.filter(name=a): - DocAlias.objects.create(name=a, document=doc) + DocAlias.objects.create(name=a).docs.add(doc) changes.append("created alias %s" % prettify_std_name(a)) if has_errata: diff --git a/ietf/sync/tests.py b/ietf/sync/tests.py index 134c307ac..6b1aae3a5 100644 --- a/ietf/sync/tests.py +++ b/ietf/sync/tests.py @@ -22,7 +22,7 @@ from ietf.utils.test_utils import TestCase class IANASyncTests(TestCase): def test_protocol_page_sync(self): draft = WgDraftFactory() - DocAlias.objects.create(name="rfc1234", document=draft) + DocAlias.objects.create(name="rfc1234").docs.add(draft) DocEvent.objects.create(doc=draft, rev=draft.rev, type="published_rfc", by=Person.objects.get(name="(System)")) rfc_names = iana.parse_protocol_page('RFC 1234') @@ -234,8 +234,8 @@ class RFCSyncTests(TestCase): # too, but for testing purposes ... updated_doc = Document.objects.create(name="draft-ietf-something") - DocAlias.objects.create(name=updated_doc.name, document=updated_doc) - DocAlias.objects.create(name="rfc123", document=updated_doc) + DocAlias.objects.create(name=updated_doc.name).docs.add(updated_doc) + DocAlias.objects.create(name="rfc123").docs.add(updated_doc) today = datetime.date.today() @@ -337,10 +337,10 @@ class RFCSyncTests(TestCase): self.assertEqual(doc.docevent_set.all()[1].type, "published_rfc") self.assertEqual(doc.docevent_set.all()[1].time.date(), today) self.assertTrue("errata" in doc.tags.all().values_list("slug", flat=True)) - self.assertTrue(DocAlias.objects.filter(name="rfc1234", document=doc)) - self.assertTrue(DocAlias.objects.filter(name="bcp1", document=doc)) - self.assertTrue(DocAlias.objects.filter(name="fyi1", document=doc)) - self.assertTrue(DocAlias.objects.filter(name="std1", document=doc)) + self.assertTrue(DocAlias.objects.filter(name="rfc1234", docs=doc)) + self.assertTrue(DocAlias.objects.filter(name="bcp1", docs=doc)) + self.assertTrue(DocAlias.objects.filter(name="fyi1", docs=doc)) + self.assertTrue(DocAlias.objects.filter(name="std1", docs=doc)) self.assertTrue(RelatedDocument.objects.filter(source=doc, target__name="rfc123", relationship="updates")) self.assertEqual(doc.title, "A Testing RFC") self.assertEqual(doc.abstract, "This is some interesting text.") diff --git a/ietf/utils/test_data.py b/ietf/utils/test_data.py index 04fc0f3a9..d47fff226 100644 --- a/ietf/utils/test_data.py +++ b/ietf/utils/test_data.py @@ -158,10 +158,7 @@ def make_test_data(): charter.set_state(State.objects.get(used=True, slug="approved", type="charter")) group.charter = charter group.save() - DocAlias.objects.create( - name=charter.name, - document=charter - ) + DocAlias.objects.create(name=charter.name).docs.add(charter) setup_default_community_list_for_group(group) # ames WG @@ -183,10 +180,7 @@ def make_test_data(): rev="00", ) charter.set_state(State.objects.get(used=True, slug="infrev", type="charter")) - DocAlias.objects.create( - name=charter.name, - document=charter - ) + DocAlias.objects.create(name=charter.name).docs.add(charter) group.charter = charter group.save() setup_default_community_list_for_group(group) @@ -220,10 +214,7 @@ def make_test_data(): # rev="00", # ) #charter.set_state(State.objects.get(used=True, slug="infrev", type="charter")) - #DocAlias.objects.create( - # name=charter.name, - # document=charter - # ) + #DocAlias.objects.create(name=charter.name).docs.add(charter) #group.charter = charter #group.save() @@ -266,7 +257,8 @@ def make_test_data(): expires=datetime.datetime.now(), ) old_draft.set_state(State.objects.get(used=True, type="draft", slug="expired")) - old_alias = DocAlias.objects.create(document=old_draft, name=old_draft.name) + old_alias = DocAlias.objects.create(name=old_draft.name) + old_alias.docs.add(old_draft) # draft draft = Document.objects.create( @@ -291,10 +283,8 @@ def make_test_data(): draft.set_state(State.objects.get(used=True, type="draft-iesg", slug="pub-req")) draft.set_state(State.objects.get(used=True, type="draft-stream-%s" % draft.stream_id, slug="wg-doc")) - doc_alias = DocAlias.objects.create( - document=draft, - name=draft.name, - ) + doc_alias = DocAlias.objects.create(name=draft.name) + doc_alias.docs.add(draft) RelatedDocument.objects.create(source=draft, target=old_alias, relationship=DocRelationshipName.objects.get(slug='replaces')) old_draft.set_state(State.objects.get(type='draft', slug='repl')) @@ -371,16 +361,17 @@ def make_test_data(): doc = Document.objects.create(name='draft-imaginary-independent-submission',type_id='draft',rev='00', title="Some Independent Notes on Imagination") doc.set_state(State.objects.get(used=True, type="draft", slug="active")) - DocAlias.objects.create(name=doc.name, document=doc) + DocAlias.objects.create(name=doc.name).docs.add(doc) # an irtf submission mid review doc = Document.objects.create(name='draft-imaginary-irtf-submission', type_id='draft',rev='00', stream=StreamName.objects.get(slug='irtf'), title="The Importance of Research Imagination") - docalias = DocAlias.objects.create(name=doc.name, document=doc) + docalias = DocAlias.objects.create(name=doc.name) + docalias.docs.add(doc) doc.set_state(State.objects.get(type="draft", slug="active")) crdoc = Document.objects.create(name='conflict-review-imaginary-irtf-submission', type_id='conflrev', rev='00', notify="fsm@ietf.org", title="Conflict Review of IRTF Imagination Document") - DocAlias.objects.create(name=crdoc.name, document=crdoc) + DocAlias.objects.create(name=crdoc.name).docs.add(crdoc) crdoc.set_state(State.objects.get(name='Needs Shepherd', type__slug='conflrev')) crdoc.relateddocument_set.create(target=docalias,relationship_id='conflrev') @@ -389,14 +380,15 @@ def make_test_data(): doc = Document.objects.create(name='status-change-imaginary-mid-review',type_id='statchg', rev='00', notify="fsm@ietf.org", group=iesg, title="Status Change Review without Imagination") doc.set_state(State.objects.get(slug='needshep',type__slug='statchg')) - docalias = DocAlias.objects.create(name='status-change-imaginary-mid-review',document=doc) + docalias = DocAlias.objects.create(name='status-change-imaginary-mid-review') + docalias.docs.add(doc) # Some things for a status change to affect def rfc_for_status_change_test_factory(name,rfc_num,std_level_id): target_rfc = Document.objects.create(name=name, type_id='draft', std_level_id=std_level_id, notify="%s@ietf.org"%name) target_rfc.set_state(State.objects.get(slug='rfc',type__slug='draft')) - docalias = DocAlias.objects.create(name=name,document=target_rfc) - docalias = DocAlias.objects.create(name='rfc%d'%rfc_num,document=target_rfc) # pyflakes:ignore + DocAlias.objects.create(name=name).docs.add(target_rfc) + DocAlias.objects.create(name='rfc%d'%rfc_num).docs.add(target_rfc) return target_rfc rfc_for_status_change_test_factory('draft-ietf-random-thing',9999,'ps') rfc_for_status_change_test_factory('draft-ietf-random-otherthing',9998,'inf') From 0122ac5bdd7bc860c52b0ea81185586db099ed8d Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Fri, 14 Jun 2019 20:45:06 +0000 Subject: [PATCH 04/14] Test commit - Legacy-Id: 16250 --- x | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 x diff --git a/x b/x new file mode 100644 index 000000000..e69de29bb From 274cef934dd0851507edc637b9979f625273d6aa Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Fri, 14 Jun 2019 20:53:24 +0000 Subject: [PATCH 05/14] Test commit - Legacy-Id: 16251 --- x | 1 + 1 file changed, 1 insertion(+) diff --git a/x b/x index e69de29bb..b7ba293f2 100644 --- a/x +++ b/x @@ -0,0 +1 @@ +Fri Jun 14 13:48:27 PDT 2019 From a8327ad21df93647e2b6cb595482c238e4734d5f Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Fri, 14 Jun 2019 20:55:00 +0000 Subject: [PATCH 06/14] Test commit - Legacy-Id: 16252 --- x | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x b/x index b7ba293f2..b86de7293 100644 --- a/x +++ b/x @@ -1 +1 @@ -Fri Jun 14 13:48:27 PDT 2019 +Fri Jun 14 13:54:54 PDT 2019 From 8e5bdf06aaae20fda7d19e457fed1c6c38b0cf5c Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Fri, 14 Jun 2019 20:56:40 +0000 Subject: [PATCH 07/14] Test commit - Legacy-Id: 16253 --- x | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x b/x index b86de7293..72d3e6307 100644 --- a/x +++ b/x @@ -1 +1 @@ -Fri Jun 14 13:54:54 PDT 2019 +Fri Jun 14 13:56:40 PDT 2019 From b5093da3dac1c16f6cd000852cfcc02bb91caeb3 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Fri, 14 Jun 2019 20:59:54 +0000 Subject: [PATCH 08/14] Test commit - Legacy-Id: 16254 --- x | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x b/x index 72d3e6307..5f70d75f9 100644 --- a/x +++ b/x @@ -1 +1 @@ -Fri Jun 14 13:56:40 PDT 2019 +Fri Jun 14 13:59:53 PDT 2019 From cc68354d5eac26467c5bde4c24699a7063e4ad92 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Fri, 14 Jun 2019 21:02:22 +0000 Subject: [PATCH 09/14] Test commit - Legacy-Id: 16255 --- x | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x b/x index 5f70d75f9..b70255f3f 100644 --- a/x +++ b/x @@ -1 +1 @@ -Fri Jun 14 13:59:53 PDT 2019 +Fri Jun 14 14:02:22 PDT 2019 From ee66c55d0e9248f6018ce6fb3d939ef6eebfd626 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Fri, 14 Jun 2019 21:14:31 +0000 Subject: [PATCH 10/14] Test commit - Legacy-Id: 16256 --- x | 1 - x.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 x create mode 100644 x.py diff --git a/x b/x deleted file mode 100644 index b70255f3f..000000000 --- a/x +++ /dev/null @@ -1 +0,0 @@ -Fri Jun 14 14:02:22 PDT 2019 diff --git a/x.py b/x.py new file mode 100644 index 000000000..a04ca2f58 --- /dev/null +++ b/x.py @@ -0,0 +1 @@ +Fri Jun 14 14:14:30 PDT 2019 From 9b709b15bf8b0c8d66565d5e72273521341183b9 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Fri, 14 Jun 2019 21:14:46 +0000 Subject: [PATCH 11/14] Test commit - Legacy-Id: 16257 --- x.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x.py b/x.py index a04ca2f58..d120b8393 100644 --- a/x.py +++ b/x.py @@ -1 +1 @@ -Fri Jun 14 14:14:30 PDT 2019 +Fri Jun 14 14:14:45 PDT 2019 From eeb20ca4350b7c6331d03118fb71144b6e5a47b7 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Fri, 14 Jun 2019 21:15:06 +0000 Subject: [PATCH 12/14] Test commit - Legacy-Id: 16258 --- x.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x.py b/x.py index d120b8393..7f4b236d2 100644 --- a/x.py +++ b/x.py @@ -1 +1 @@ -Fri Jun 14 14:14:45 PDT 2019 +Fri Jun 14 14:15:05 PDT 2019 From 061d532231c1d09315be37f65ee875edb07c6c2b Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Fri, 14 Jun 2019 21:16:43 +0000 Subject: [PATCH 13/14] Test commit - Legacy-Id: 16259 --- x.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x.py b/x.py index 7f4b236d2..98bec07c8 100644 --- a/x.py +++ b/x.py @@ -1 +1 @@ -Fri Jun 14 14:15:05 PDT 2019 +Fri Jun 14 14:16:42 PDT 2019 From 83efb34962792eb4737bf3b409a1381632cf9046 Mon Sep 17 00:00:00 2001 From: Henrik Levkowetz Date: Fri, 14 Jun 2019 21:22:20 +0000 Subject: [PATCH 14/14] - Legacy-Id: 16260 --- x.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 x.py diff --git a/x.py b/x.py deleted file mode 100644 index 98bec07c8..000000000 --- a/x.py +++ /dev/null @@ -1 +0,0 @@ -Fri Jun 14 14:16:42 PDT 2019