Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ that can help:
* If you've modified the ``trackhack.scss`` file, use
``sassc scss/trachacks.scss trac-env/htdocs/css/trachacks.css -s compressed``
to compile it to CSS.
* Load the local SQL fixtures in dependency order::

export DATABASE_URL=postgres://code.djangoproject:secret@localhost/code.djangoproject
psql "$DATABASE_URL" < sql/00_lookups.sql
psql "$DATABASE_URL" < sql/01_ticket_37239_sample.sql
psql "$DATABASE_URL" < sql/02_fake_tickets_100.sql

Restart Trac after loading the lookup data so its cached values are refreshed.

Using Docker
------------
Expand All @@ -38,6 +46,22 @@ Using Docker
docker compose exec -T db psql $DATABASE_URL < ../djangoproject.com/tracdb/trac.sql
docker compose exec trac trac-admin /code/trac-env/ permission add anonymous TRAC_ADMIN

Loading the local SQL fixtures
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

With the Docker services running, load the SQL files in this order. The second
file depends on the lookup data from the first, and the third file depends on
the lookup data as well::

export DATABASE_URL=postgres://code.djangoproject:secret@db/code.djangoproject
docker compose exec -T db psql "$DATABASE_URL" < sql/00_lookups.sql
docker compose exec -T db psql "$DATABASE_URL" < sql/01_ticket_37239_sample.sql
docker compose exec -T db psql "$DATABASE_URL" < sql/02_fake_tickets_100.sql
docker compose restart trac

Restarting Trac refreshes its cached lookup values.


Using Podman
------------

Expand Down
104 changes: 104 additions & 0 deletions sql/00_lookups.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
-- Seed data for Trac's ticket "select field" lookup tables: component, version,
-- and the enum table (severity, ticket_type). Values are the real distinct
-- values currently used on code.djangoproject.com (fetched via its public
-- /query?...&format=csv export), plus "Uncategorized", which is trac.ini's
-- configured default_component but wasn't present in the sampled query.
--
-- IMPORTANT: Trac caches these lookups in memory per-process. After running
-- this file (or any INSERT into component/version/enum) you must restart the
-- trac container for ticket pages to pick up the new values:
-- docker restart codedjangoprojectcom-trac-1
--
-- Without this data, Trac hides the corresponding ticket-box row entirely
-- (Component/Version/Severity/Type) rather than showing it empty -- it's not
-- a rendering bug, the field is just treated as unconfigured.
--
-- priority and milestone are intentionally NOT seeded here: this Trac
-- instance hides those two fields regardless of table contents (confirmed by
-- ticket CSV exports never including them), so seeding them would have no
-- visible effect.

BEGIN;

INSERT INTO component (name, owner, description) VALUES
('CSRF', '', ''),
('Core (Cache system)', '', ''),
('Core (Mail)', '', ''),
('Core (Management commands)', '', ''),
('Core (Other)', '', ''),
('Core (Serialization)', '', ''),
('Core (System checks)', '', ''),
('Core (URLs)', '', ''),
('Database layer (models, ORM)', '', ''),
('Documentation', '', ''),
('Error reporting', '', ''),
('File uploads/storage', '', ''),
('Forms', '', ''),
('GIS', '', ''),
('Generic views', '', ''),
('HTTP handling', '', ''),
('Internationalization', '', ''),
('Migrations', '', ''),
('Packaging', '', ''),
('Template system', '', ''),
('Testing framework', '', ''),
('Uncategorized', '', ''),
('Utilities', '', ''),
('contrib.admin', '', ''),
('contrib.auth', '', ''),
('contrib.contenttypes', '', ''),
('contrib.flatpages', '', ''),
('contrib.messages', '', ''),
('contrib.postgres', '', ''),
('contrib.redirects', '', ''),
('contrib.sessions', '', ''),
('contrib.sitemaps', '', ''),
('contrib.sites', '', ''),
('contrib.staticfiles', '', ''),
('contrib.syndication', '', '')
ON CONFLICT (name) DO NOTHING;

INSERT INTO version (name, "time", description) VALUES
('1.0', NULL, ''),
('1.1', NULL, ''),
('1.1-beta', NULL, ''),
('1.2', NULL, ''),
('1.2-beta', NULL, ''),
('1.3', NULL, ''),
('1.4', NULL, ''),
('1.4-beta-1', NULL, ''),
('1.5', NULL, ''),
('1.6', NULL, ''),
('1.7', NULL, ''),
('1.8', NULL, ''),
('1.9', NULL, ''),
('1.10', NULL, ''),
('1.11', NULL, ''),
('2.0', NULL, ''),
('2.1', NULL, ''),
('2.2', NULL, ''),
('3.0', NULL, ''),
('3.1', NULL, ''),
('3.2', NULL, ''),
('4.0', NULL, ''),
('4.1', NULL, ''),
('4.2', NULL, ''),
('5.0', NULL, ''),
('5.1', NULL, ''),
('5.2', NULL, ''),
('6.0', NULL, ''),
('6.1', NULL, ''),
('dev', NULL, ''),
('newforms-admin', NULL, ''),
('soc2009/admin-ui', NULL, '')
ON CONFLICT (name) DO NOTHING;

INSERT INTO enum (type, name, value) VALUES
('severity', 'Normal', '1'),
('severity', 'Release blocker', '2'),
('ticket_type', 'Bug', '1'),
('ticket_type', 'New feature', '2'),
('ticket_type', 'Cleanup/optimization', '3')
ON CONFLICT (type, name) DO NOTHING;

COMMIT;
128 changes: 128 additions & 0 deletions sql/01_ticket_37239_sample.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
-- Sample data reproducing ticket #37239 from production (code.djangoproject.com)
-- https://code.djangoproject.com/ticket/37239

BEGIN;

INSERT INTO ticket (
id, type, "time", changetime, component, severity, priority, owner, reporter, cc,
version, milestone, status, resolution, summary, description, keywords
) VALUES (
37239,
'Bug',
1785297235000000,
1785511817805600,
'Database layer (models, ORM)',
'Normal',
'',
'jacobtylerwalls',
'jacobtylerwalls',
'lilyfoote',
'5.2',
'',
'assigned',
'',
E'Saving related objects with generated primary keys doesn\'t update assigned relations',
$desc$With these models:
{{{#!py
class DBDefaultsFunctionPK(models.Model):
uuid = models.UUIDField(primary_key=True, db_default=UUID4())

class Meta:
required_db_features = {
"supports_uuid4_function",
"supports_expression_defaults",
}


class DBDefaultsFunctionPKChild(DBDefaultsFunctionPK):
parent = models.OneToOneField(
DBDefaultsFunctionPK,
models.CASCADE,
primary_key=True,
db_default=UUID4(),
related_name="child",
)

class Meta:
required_db_features = {
"supports_uuid4_function",
"supports_expression_defaults",
}
}}}
This test fails:
{{{#!py
@skipUnlessDBFeature(
"can_return_rows_from_bulk_insert",
"supports_expression_defaults",
"supports_uuid4_function",
)
def test_foreign_key_db_default_expression_via_parent(self):
parent = DBDefaultsFunctionPK()
obj = DBDefaultsFunctionPKChild(parent=parent)
parent.save()
obj.save()
self.assertEqual(obj.pk, parent.pk)
}}}
{{{
======================================================================
FAIL: test_foreign_key_db_default_expression_via_parent (field_defaults.tests.DefaultTests.test_foreign_key_db_default_expression_via_parent)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/jwalls/django/tests/field_defaults/tests.py", line 152, in test_foreign_key_db_default_expression_via_parent
self.assertEqual(obj.pk, parent.pk)
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
AssertionError: UUID('fdfe6046-e662-4c36-a2e1-b10677d0ccb3') != UUID('ddeef3dd-52bc-4b35-b643-4634876a4acc')

----------------------------------------------------------------------
Ran 1 test in 0.016s

FAILED (failures=1, errors=1)
}}}
----
A similar version of the test using `Now()` instead of `UUID4()` fails on 5.2 (since `UUID4()` is not available there), but I ran into issues with trying to use datetimes in FK constraints on sqlite, so I'm happy to take advice on the best examples to build these models with, as I could be glazing over something obviously better.
----
This is the "separate non-release-blocker ticket" mentioned in #37238, and the underlying reason for the relaxed assertions on the PR for it.$desc$,
''
);

INSERT INTO ticket_custom (ticket, name, value) VALUES
(37239, 'easy', '0'),
(37239, 'has_patch', '1'),
(37239, 'needs_better_patch', '0'),
(37239, 'needs_docs', '0'),
(37239, 'needs_tests', '0'),
(37239, 'stage', 'Accepted'),
(37239, 'ui_ux', '0');

-- comment:1 -- Jacob Walls, 2026-07-28 22:58:01 -05:00
INSERT INTO ticket_change (ticket, "time", author, field, oldvalue, newvalue) VALUES
(37239, 1785297481122372, 'jacobtylerwalls', 'has_patch', '0', '1'),
(37239, 1785297481122372, 'jacobtylerwalls', 'comment', '', $c1$[https://github.com/django/django/pull/21694 PR]$c1$);

-- comment:2 -- Sarah Boyce, 2026-07-29 02:47:58 -05:00
INSERT INTO ticket_change (ticket, "time", author, field, oldvalue, newvalue) VALUES
(37239, 1785311278521760, 'sarahboyce', 'cc', '', 'lilyfoote'),
(37239, 1785311278521760, 'sarahboyce', 'stage', 'Unreviewed', 'Accepted'),
(37239, 1785311278521760, 'sarahboyce', 'comment', '', 'Thank you!');

-- comment:3 -- Sarah Boyce, 2026-07-29 03:23:32 -05:00
INSERT INTO ticket_change (ticket, "time", author, field, oldvalue, newvalue) VALUES
(37239, 1785313412940074, 'sarahboyce', 'needs_better_patch', '0', '1');

-- comment:4 -- Sarah Boyce, 2026-07-29 05:00:18 -05:00
INSERT INTO ticket_change (ticket, "time", author, field, oldvalue, newvalue) VALUES
(37239, 1785319218661765, 'sarahboyce', 'summary',
E'After assigning a related object with a db_default, the db_default expression is reevaluated when saving the other object',
E'Saving related objects with generated primary keys doesn\'t update assigned relations'),
(37239, 1785319218661765, 'sarahboyce', 'comment', '',
$c4$I have closed #37238 as a duplicate as the fix for this appears to resolve that issue.
That ticket gives different example models we could use that wouldn't use `UUID4`$c4$);

-- comment:5 -- Jacob Walls, 2026-07-31 10:30:17 -05:00
INSERT INTO ticket_change (ticket, "time", author, field, oldvalue, newvalue) VALUES
(37239, 1785511817805600, 'jacobtylerwalls', 'needs_better_patch', '1', '0');

-- Keep the id sequence in sync so future trac-created tickets don't collide.
SELECT setval('ticket_id_seq', GREATEST((SELECT MAX(id) FROM ticket), 1));

COMMIT;
Loading
Loading