Ticket #35974: ticket_35974.patch

File ticket_35974.patch, 8.1 KB (added by Laurent Szyster, 11 days ago)
  • django/contrib/contenttypes/fields.py

    From da74631d9f4a4ecf0267eb2f0cdaa979421d8466 Mon Sep 17 00:00:00 2001
    From: Laurent Szyster <laurent.szyster@railnova.eu>
    Date: Sat, 7 Dec 2024 10:08:19 +0100
    Subject: [PATCH] Fixed #35974 - test only _state.adding to assert that an
     object is unsaved in RelatedManager.add and GenericRelatedObjectManager.add
    
    ---
     django/contrib/contenttypes/fields.py         |   2 +-
     .../db/models/fields/related_descriptors.py   |   2 +-
     tests/multiple_database/fixtures/replica.json |  26 +++++
     tests/multiple_database/tests.py              | 107 ++++++++++++++++--
     4 files changed, 124 insertions(+), 13 deletions(-)
     create mode 100644 tests/multiple_database/fixtures/replica.json
    
    diff --git a/django/contrib/contenttypes/fields.py b/django/contrib/contenttypes/fields.py
    index a3e87f6ed4..9a9b11ea3c 100644
    a b def create_generic_related_manager(superclass, rel):  
    692692            if bulk:
    693693                pks = []
    694694                for obj in objs:
    695                     if obj._state.adding or obj._state.db != db:
     695                    if obj._state.adding:
    696696                        raise ValueError(
    697697                            "%r instance isn't saved. Use bulk=False or save "
    698698                            "the object first." % obj
  • django/db/models/fields/related_descriptors.py

    diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py
    index 2b23085fa8..daf8fff131 100644
    a b def create_reverse_many_to_one_manager(superclass, rel):  
    820820                pks = []
    821821                for obj in objs:
    822822                    check_and_update_obj(obj)
    823                     if obj._state.adding or obj._state.db != db:
     823                    if obj._state.adding:
    824824                        raise ValueError(
    825825                            "%r instance isn't saved. Use bulk=False or save "
    826826                            "the object first." % obj
  • new file tests/multiple_database/fixtures/replica.json

    diff --git a/tests/multiple_database/fixtures/replica.json b/tests/multiple_database/fixtures/replica.json
    new file mode 100644
    index 0000000000..c6beb0c111
    - +  
     1[
     2    {
     3        "pk": 1,
     4        "model": "multiple_database.book",
     5        "fields": {
     6            "title": "The Definitive Guide to Django",
     7            "published": "2009-7-8"
     8        }
     9    },
     10    {
     11        "pk": 1,
     12        "model": "multiple_database.person",
     13        "fields": {
     14            "name": "Tim Graham"
     15        }
     16    },
     17    {
     18        "pk": 1,
     19        "model": "multiple_database.review",
     20        "fields": {
     21            "source": "Python Weekly",
     22            "content_type": 1,
     23            "object_id": 1
     24        }
     25    }
     26]
     27 No newline at end of file
  • tests/multiple_database/tests.py

    diff --git a/tests/multiple_database/tests.py b/tests/multiple_database/tests.py
    index 9587030a46..2b9b043ce7 100644
    a b class QueryTestCase(TestCase):  
    11251125            review1.content_object = dive
    11261126
    11271127        # Add to a foreign key set with an object from a different database
    1128         msg = (
    1129             "<Review: Python Monthly> instance isn't saved. "
    1130             "Use bulk=False or save the object first."
    1131         )
    11321128        with self.assertRaisesMessage(ValueError, msg):
    11331129            with transaction.atomic(using="other"):
    11341130                dive.reviews.add(review1)
    class RouterTestCase(TestCase):  
    15021498        self.assertEqual(Book.objects.using("default").count(), 1)
    15031499        self.assertEqual(Book.objects.using("other").count(), 1)
    15041500
    1505     def test_invalid_set_foreign_key_assignment(self):
     1501    def test_invalid_set_unsaved_assignment(self):
    15061502        marty = Person.objects.using("default").create(name="Marty Alchin")
    1507         dive = Book.objects.using("other").create(
     1503        dive = Book(
    15081504            title="Dive into Python",
    15091505            published=datetime.date(2009, 5, 4),
    15101506        )
    15111507        # Set a foreign key set with an object from a different database
    1512         msg = (
    1513             "<Book: Dive into Python> instance isn't saved. Use bulk=False or save the "
    1514             "object first."
    1515         )
    1516         with self.assertRaisesMessage(ValueError, msg):
     1508        msg = "Model instances without primary key value are unhashable"
     1509        with self.assertRaisesMessage(TypeError, msg):
    15171510            marty.edited.set([dive])
    15181511
    15191512    def test_foreign_key_cross_database_protection(self):
    class RelationAssignmentTests(SimpleTestCase):  
    25562549        profile = UserProfile()
    25572550        with self.assertRaisesMessage(ValueError, self.router_prevents_msg):
    25582551            user.userprofile = profile
     2552
     2553
     2554@override_settings(DATABASE_ROUTERS=[TestRouter()])
     2555class ReadWriteClusterTests(TestCase):
     2556    """see ticket #35974"""
     2557
     2558    databases = {"default", "other"}
     2559    fixtures = ["replica"]
     2560
     2561    def test_reverse_many_to_one_add(self):
     2562        person = Person.objects.get(name="Tim Graham")
     2563        book = Book.objects.get(title="The Definitive Guide to Django")
     2564        person.edited.add(book)
     2565        self.assertEqual(
     2566            list(Person.objects.using("default").get(name="Tim Graham").edited.all()),
     2567            [book],
     2568        )
     2569
     2570    def test_reverse_many_to_one_set(self):
     2571        person = Person.objects.get(name="Tim Graham")
     2572        book = Book.objects.get(title="The Definitive Guide to Django")
     2573        person.edited.set([book])
     2574        self.assertEqual(
     2575            list(Person.objects.using("default").get(name="Tim Graham").edited.all()),
     2576            [book],
     2577        )
     2578
     2579    def test_reverse_many_to_one_add_unsaved(self):
     2580        person = Person.objects.get(name="Tim Graham")
     2581        book = Book(
     2582            title="The Definitive Guide to Django",
     2583            published=datetime.date(2009, 7, 8),
     2584        )
     2585        msg = (
     2586            "<Book: The Definitive Guide to Django> instance isn't saved."
     2587            " Use bulk=False or save the object first."
     2588        )
     2589        with self.assertRaisesMessage(ValueError, msg):
     2590            person.edited.add(book)
     2591
     2592    def test_reverse_many_to_one_set_unsaved(self):
     2593        person = Person.objects.get(name="Tim Graham")
     2594        book = Book(
     2595            title="The Definitive Guide to Django",
     2596            published=datetime.date(2009, 7, 8),
     2597        )
     2598        msg = "Model instances without primary key value are unhashable"
     2599        with self.assertRaisesMessage(TypeError, msg):
     2600            person.edited.set([book])
     2601
     2602    def test_generic_related_add(self):
     2603        book = Book.objects.get(title="The Definitive Guide to Django")
     2604        review = Review.objects.get(source="Python Weekly")
     2605        book.reviews.add(review)
     2606        self.assertEqual(
     2607            list(
     2608                Book.objects.using("default")
     2609                .get(title="The Definitive Guide to Django")
     2610                .reviews.all()
     2611            ),
     2612            [review],
     2613        )
     2614
     2615    def test_generic_related_set(self):
     2616        book = Book.objects.get(title="The Definitive Guide to Django")
     2617        review = Review.objects.get(source="Python Weekly")
     2618        book.reviews.set([review])
     2619        self.assertEqual(
     2620            list(
     2621                Book.objects.using("default")
     2622                .get(title="The Definitive Guide to Django")
     2623                .reviews.all()
     2624            ),
     2625            [review],
     2626        )
     2627
     2628    def test_generic_related_add_unsaved(self):
     2629        book = Book.objects.get(title="The Definitive Guide to Django")
     2630        review = Review(source="Python Weekly")
     2631        msg = (
     2632            "<Review: Python Weekly> instance isn't saved."
     2633            " Use bulk=False or save the object first."
     2634        )
     2635        with self.assertRaisesMessage(ValueError, msg):
     2636            book.reviews.add(review)
     2637
     2638    def test_generic_related_set_unsaved(self):
     2639        book = Book.objects.get(title="The Definitive Guide to Django")
     2640        review = Review(source="Python Weekly")
     2641        msg = "Model instances without primary key value are unhashable"
     2642        with self.assertRaisesMessage(TypeError, msg):
     2643            book.reviews.set([review])
Back to Top