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

Fixed #27452 -- Added serial fields to contrib.postgres. #18123

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

csirmazbendeguz
Copy link

@csirmazbendeguz csirmazbendeguz commented May 3, 2024

Trac ticket number

ticket-27452

Branch description

Added SmallSerialField, SerialField, BigSerialField to contrib.postgres.

Previous PR

Checklist

  • This PR targets the main branch.
  • The commit message is written in past tense, mentions the ticket number, and ends with a period.
  • I have checked the "Has patch" ticket flag in the Trac system.
  • I have added or updated relevant tests.
  • I have added or updated relevant docs, including release notes if applicable.
  • I have attached screenshots in both light and dark modes for any UI changes.

@ngnpope ngnpope self-requested a review May 3, 2024 06:37
@csirmazbendeguz csirmazbendeguz force-pushed the ticket_27452 branch 4 times, most recently from e892da4 to 97cbc23 Compare May 3, 2024 08:31
@csirmazbendeguz csirmazbendeguz marked this pull request as draft May 3, 2024 10:21
@csirmazbendeguz csirmazbendeguz force-pushed the ticket_27452 branch 12 times, most recently from fccac26 to 2b48193 Compare May 4, 2024 13:05
Copy link
Contributor

@LilyFoote LilyFoote left a comment

Choose a reason for hiding this comment

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

This looks like a great start!

In addition to the specific comments I added, we'll need some migrations tests to cover adding/removing serial fields and converting between serial and auto fields.

django/contrib/postgres/fields/serial.py Outdated Show resolved Hide resolved
django/contrib/postgres/fields/serial.py Outdated Show resolved Hide resolved
django/contrib/postgres/fields/serial.py Outdated Show resolved Hide resolved
django/contrib/postgres/fields/serial.py Outdated Show resolved Hide resolved
django/db/backends/postgresql/operations.py Show resolved Hide resolved
django/db/backends/postgresql/schema.py Outdated Show resolved Hide resolved
django/db/backends/postgresql/schema.py Show resolved Hide resolved
Comment on lines 5742 to 5812
@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific")
@isolate_apps("schema")
@tag("serial")
def test_serial_to_integer(self):
from django.contrib.postgres.fields import SerialField

self.serial_to_integer_test(SerialField, IntegerField)

@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific")
@isolate_apps("schema")
@tag("serial")
def test_serial_to_small_integer(self):
from django.contrib.postgres.fields import SerialField

self.serial_to_integer_test(SerialField, SmallIntegerField)

@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific")
@isolate_apps("schema")
@tag("serial")
def test_serial_to_big_integer(self):
from django.contrib.postgres.fields import SerialField

self.serial_to_integer_test(SerialField, BigIntegerField)

@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific")
@isolate_apps("schema")
@tag("serial")
def test_small_serial_to_integer(self):
from django.contrib.postgres.fields import SmallSerialField

self.serial_to_integer_test(SmallSerialField, IntegerField)

@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific")
@isolate_apps("schema")
@tag("serial")
def test_small_serial_to_small_integer(self):
from django.contrib.postgres.fields import SmallSerialField

self.serial_to_integer_test(SmallSerialField, SmallIntegerField)

@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific")
@isolate_apps("schema")
@tag("serial")
def test_small_serial_to_big_integer(self):
from django.contrib.postgres.fields import SmallSerialField

self.serial_to_integer_test(SmallSerialField, BigIntegerField)

@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific")
@isolate_apps("schema")
@tag("serial")
def test_big_serial_to_big_integer(self):
from django.contrib.postgres.fields import BigSerialField

self.serial_to_integer_test(BigSerialField, BigIntegerField)

@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific")
@isolate_apps("schema")
@tag("serial")
def test_big_serial_to_integer(self):
from django.contrib.postgres.fields import BigSerialField

self.serial_to_integer_test(BigSerialField, IntegerField)

@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL specific")
@isolate_apps("schema")
@tag("serial")
def test_big_serial_to_small_integer(self):
from django.contrib.postgres.fields import BigSerialField

self.serial_to_integer_test(BigSerialField, SmallIntegerField)
Copy link
Contributor

Choose a reason for hiding this comment

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

This feels like a good use case for subTest to me.

Copy link
Author

Choose a reason for hiding this comment

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

Yes, the issue is we would either need to generate the test models with a dynamic name, or clean up the test models after the subtests - IMO it's more trouble than worth it.

tests/schema/tests.py Outdated Show resolved Hide resolved
@csirmazbendeguz csirmazbendeguz force-pushed the ticket_27452 branch 2 times, most recently from e7fdd21 to 8052e52 Compare May 5, 2024 10:37
@csirmazbendeguz
Copy link
Author

This looks like a great start!

In addition to the specific comments I added, we'll need some migrations tests to cover adding/removing serial fields and converting between serial and auto fields.

@LilyFoote , thanks for the review! Could you point me to some tests I could copy to get started? I'm not sure how to test the migrations other than with the tests/schema tests.

@LilyFoote
Copy link
Contributor

For database defaults I added tests in tests/migrations/test_autodetector.py and tests/migrations/test_operations.py.

@csirmazbendeguz csirmazbendeguz force-pushed the ticket_27452 branch 5 times, most recently from 569c960 to 0ebc30b Compare May 6, 2024 06:40
@csirmazbendeguz csirmazbendeguz force-pushed the ticket_27452 branch 2 times, most recently from 0fc425d to d4f4219 Compare May 6, 2024 11:22
@csirmazbendeguz csirmazbendeguz marked this pull request as ready for review May 6, 2024 11:24
@csirmazbendeguz csirmazbendeguz force-pushed the ticket_27452 branch 4 times, most recently from 4c086eb to 51ed545 Compare May 6, 2024 12:03
@csirmazbendeguz
Copy link
Author

csirmazbendeguz commented May 8, 2024

I have managed to test these operations (add, alter, remove serial field) in the schema.tests, I'm not sure if more tests are necessary?

Copy link
Member

@ngnpope ngnpope left a comment

Choose a reason for hiding this comment

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

We will need to address the backward compatibility with pre-Django 4.1 AutoField on PostgreSQL to avoid breaking many old projects that didn't manually migrate to identity columns.

Edit: This might not be too much of a problem after all, but we should carefully consider all the places where things could break, e.g. migrations. We should likely have a test that starts out with a pre-Django 4.1 AutoField to make sure that it is handled correctly.

django/db/backends/postgresql/introspection.py Outdated Show resolved Hide resolved
django/db/backends/postgresql/operations.py Outdated Show resolved Hide resolved
docs/ref/checks.txt Outdated Show resolved Hide resolved
@csirmazbendeguz
Copy link
Author

@ngnpope , thank you for reviewing my changes ! 🙏 I have pushed a fix for the issues you mentioned.

@csirmazbendeguz
Copy link
Author

@ngnpope , I think all concerns has been addressed, let me know what you think.

Copy link
Contributor

@LilyFoote LilyFoote left a comment

Choose a reason for hiding this comment

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

I'm loving the progress you've made here. I have a few minor suggestions, but overall looks good to me!

django/contrib/postgres/fields/serial.py Show resolved Hide resolved
django/db/backends/postgresql/schema.py Outdated Show resolved Hide resolved
django/db/backends/postgresql/schema.py Show resolved Hide resolved
django/db/backends/postgresql/schema.py Outdated Show resolved Hide resolved
@csirmazbendeguz
Copy link
Author

Thanks a lot @LilyFoote ! I addressed your suggestions.

Copy link
Contributor

@sarahboyce sarahboyce left a comment

Choose a reason for hiding this comment

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

Thank you @csirmazbendeguz
I haven't reviewed this in depth but will hope to review again soon, as a first look through, this looks nice

if self.null:
return [
checks.Error(
"SerialFields do not accept null values.",
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
"SerialFields do not accept null values.",
f"{self.__class__.__name__} must not have ``null=True``.",

Saying "must not have null=True" aligns more to fields.E007.

Also this is currently documented as

``<field>`` does not accept null values.

But always says SerialFields, maybe we should do something similar to fields.E010 and update the error message depending on the field. If so, update each of these, otherwise I would document the check to be:

SerialFields does not accept null values.

Copy link
Author

Choose a reason for hiding this comment

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

@sarahboyce , I was following fields.E110 which has:

``BooleanField``\s do not accept null values

It was @ngnpope 's idea to make this error message general, and I agree with it, because this way we wouldn't need to define a new error code every time a new field doesn't accept a null value.

If you would like to make this specific to serial fields, I believe we should choose a different error code.

I agree with using the class name instead of "SerialFields" - I adjusted it.

django/contrib/postgres/fields/serial.py Outdated Show resolved Hide resolved
docs/ref/contrib/postgres/fields.txt Outdated Show resolved Hide resolved
docs/releases/5.1.txt Outdated Show resolved Hide resolved
docs/ref/contrib/postgres/fields.txt Outdated Show resolved Hide resolved
docs/ref/contrib/postgres/fields.txt Outdated Show resolved Hide resolved
@csirmazbendeguz
Copy link
Author

Thanks a lot @sarahboyce , I addressed your comments, let me know what you think.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants