Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usability enhancements and hardening for Django models #11725 #11726

Merged
merged 7 commits into from
Jan 27, 2025

Conversation

jacobtylerwalls
Copy link
Member

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Description of Change

I found some usability improvements to make to our Django models while working on #11596, and I wanted to discuss them separately.

Issues Solved

Closes #11725

Checklist

  • I targeted one of these branches:
    • dev/8.0.x (under development): features, bugfixes not covered below
    • dev/7.6.x (main support): regressions, crashing bugs, security issues, major bugs in new features
    • dev/6.2.x (extended support): major security issues, data loss issues
  • I added a changelog in arches/releases
  • I submitted a PR to arches-docs (if appropriate)
  • Unit tests pass locally with my changes
  • I added tests that prove my fix is effective or that my feature works
  • My test fails on the target branch

Ticket Background

Further comments

See commit messages for descriptions

from django.db import migrations, models


class Migration(migrations.Migration):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This migration does not produce any SQL

from django.db import migrations, models


class Migration(migrations.Migration):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This SQL looks like:

BEGIN;
--
-- Alter field data on tilemodel
--
ALTER TABLE "tiles" ALTER COLUMN "tiledata" SET DEFAULT '{}'::jsonb;
UPDATE "tiles" SET "tiledata" = '{}'::jsonb WHERE "tiledata" IS NULL; SET CONSTRAINTS ALL IMMEDIATE;
ALTER TABLE "tiles" ALTER COLUMN "tiledata" SET NOT NULL;
ALTER TABLE "tiles" ALTER COLUMN "tiledata" DROP DEFAULT;
COMMIT;

A db_default on this field didn't seem of much value, but I will circle back to #10958 to get moving on db defaults for primary key fields.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This avoids having two representations of no data--None and {}.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could discuss whether to do the same thing for provisionaledits.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where this actually came up in practice is that while dev'ing #11596 I occasionally created corrupt tiles with data = None, and this caused failures all over where we depend on calling .data.keys().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarified over slack with Cyrus, repeating here: this doesn't represent an intent to save any tiles with {} in the data column, this is just a something-better-than-nothing way to get null=False on this column, and then we can we add some other layer of protection against {} later, e.g. as a check constraint.

@@ -99,11 +81,11 @@ def __init__(self, *args, **kwargs):
if isinstance(self.cardid, str):
self.cardid = uuid.UUID(self.cardid)

def save(self, *args, **kwargs):
def save(self, **kwargs):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Positional arguments to save() were deprecated in 5.1 and will raise errors in 6.

if self.pk == self.source_identifier_id:
self.source_identifier_id = None
add_to_update_fields(kwargs, "source_identifier_id")
super(CardModel, self).save()
super(CardModel, self).save(**kwargs)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed we were swallowing **kwargs in several places.

Comment on lines 701 to 722
related_name="children",
related_query_name="child",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively if we prefer the verbosity we could do child_nodegroups and child_nodegroup.

@@ -1209,8 +1193,10 @@ class Meta:


class ResourceInstance(models.Model):
resourceinstanceid = models.UUIDField(primary_key=True)
graph = models.ForeignKey(GraphModel, db_column="graphid", on_delete=models.CASCADE)
resourceinstanceid = models.UUIDField(primary_key=True, blank=True)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank=True lets us use built-in Django model validation without tripping over fields we expect a client to leave blank and have generated on the backend.

Comment on lines +1236 to +1287
class Meta:
managed = True
db_table = "resource_instances"
permissions = (("no_access_to_resourceinstance", "No Access"),)

def __init__(self, *args, **kwargs):
super(ResourceInstance, self).__init__(*args, **kwargs)
if not self.resourceinstanceid:
self.resourceinstanceid = uuid.uuid4()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this from the bottom of the class because I sort of expect to see it up before the other methods, but if others feel different, happy to shuffle it back.

Comment on lines +1246 to +1290
def __repr__(self):
return f"<{self.graph.name}: {self.name} ({self.pk})>"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<Scheme: AAT Entries (b73e741b-46da-496c-8960-55cc1007bec4)>

Comment on lines +1542 to +1586
related_name="children",
related_query_name="child",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same decision point as above (child_tile, child_tiles?) Or childtile for symmetry with parenttile?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, the other one on NodeGroup already merged in #11614. But we can change it if we want to wordsmith a bit more.

Comment on lines -355 to +356
self.assertIn(str(other_resource.pk), str(mock._mock_call_args))
# delete_resources() was called with the correct resource id.
self.assertEqual(other_resource.pk, mock._mock_call_args[1]["resources"].pk)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completely unrelated, but I had this lying around and didn't want to forget about it. When I wrote this test the assertion didn't really capture the issue.

Copy link
Member

@chiatt chiatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thanks for all of your comments @jacobtylerwalls - made the review much easier.

@jacobtylerwalls jacobtylerwalls merged commit 3714ef9 into dev/8.0.x Jan 27, 2025
7 checks passed
@jacobtylerwalls jacobtylerwalls deleted the jtw/cleanup-models branch January 27, 2025 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

v8 Django model field improvements
2 participants