Example #1
0
    def previous_page_info(self) -> Optional[dict]:
        """Returns a dictionary which can be given to FlowPaginator.page()
        to get the previous page.

        @see info()
        Internal information ; notice that 'type' will always be 'backward'.
        """
        if self.has_previous():
            populate_related(self.object_list, (self._attr_name, ))

            object_iter = iter(self.object_list)
            value = self._key_field_info.value_from(next(object_iter))
            offset = self._compute_offset(value, object_iter)

            if offset == self._max_size - 1:  # NB: _max_size > 1
                # The duplicates fill this page & there can be some duplicates on the next page(s)
                if self._forward:
                    # NB: it's easy to see (with a sketch) that
                    #     duplicates_count = forward_offset + backward_offset + 1
                    #     (with here forward_offset == self._offset  & backward_offset == offset)
                    offset = self._get_duplicates_count(
                        value) - self._offset - 1
                elif self._offset:
                    # Offsets are in the same direction (backward) => we cumulate them
                    offset += self._offset + 1

            return self._build_info(_BACKWARD, value, offset)

        return None
Example #2
0
    def test_populate_related05(self):
        "Two fields related to the same model"
        user = self.login()

        create_contact = partial(FakeContact.objects.create,
                                 user=user,
                                 last_name='Simpson')
        marge = create_contact(first_name='Marge')
        homer = create_contact(first_name='Homer')

        rel = Relation.objects.create(
            user=user,
            type_id=REL_SUB_HAS,
            subject_entity=marge,
            object_entity=homer,
        )
        rel = self.refresh(rel)

        # NB: we fill the ContentType cache to not disturb assertNumQueries()
        ContentType.objects.get_for_model(CremeEntity)

        with self.assertNumQueries(1):
            populate_related([rel], ['subject_entity', 'object_entity'])

        with self.assertNumQueries(0):
            e1 = rel.subject_entity

        self.assertEqual(marge, e1.get_real_entity())
Example #3
0
    def next_page_info(self) -> Optional[dict]:
        """Returns a dictionary which can be given to FlowPaginator.page() to get the next page.

        @see info()
        Internal information ; notice that 'type' will always be 'forward'.
        """
        next_item = self._next_item

        if next_item is not None:
            populate_related([next_item, *self.object_list],
                             (self._attr_name, ))

            value = self._key_field_info.value_from(next_item)
            offset = self._compute_offset(value, reversed(self.object_list))

            if offset == self._max_size:
                # The duplicates fill this page & there can be some duplicates
                # on the previous page(s)
                if self._forward:
                    # Offsets are in the same direction (forward) => we accumulate them
                    offset += self._offset
                else:
                    # NB: it's easy to see (with a sketch) that
                    #     duplicates_count = forward_offset + backward_offset + 1
                    #     (with here forward_offset == offset & backward_offset == self._offset)
                    offset = self._get_duplicates_count(
                        value) - self._offset - 1

            return self._build_info(_FORWARD, value, offset)

        return None
Example #4
0
    def test_populate_related04(self):
        "Partially cached"
        self.login()

        contacts = self._create_contacts()
        __ = contacts[0].sector
        # __ = contacts[1].sector # Not Cached

        with self.assertNumQueries(2):
            populate_related(contacts, ['sector', 'civility'])
Example #5
0
    def test_populate_related03(self):
        "Do not retrieve already cached values"
        self.login()

        contacts = self._create_contacts()
        __ = contacts[0].sector
        __ = contacts[1].sector

        with self.assertNumQueries(1):
            populate_related(contacts, ['sector', 'civility'])
Example #6
0
    def test_populate_related08(self):
        "Two fields + depth > 1  => instances of level 2 have different models"
        user = self.login()
        user2 = self.other_user

        create_folder = partial(FakeFolder.objects.create, user=user)
        folder1 = create_folder(title='Maps')
        folder11 = create_folder(title='Earth maps', parent=folder1)
        folder2 = create_folder(title='Blue prints')

        create_doc = partial(FakeDocument.objects.create, user=user)
        docs = [
            create_doc(title='Japan map part#1', linked_folder=folder1),
            create_doc(title='Mars city 1', linked_folder=folder11),
            create_doc(title='Swordfish', linked_folder=folder2, user=user2),
        ]
        docs = [self.refresh(c) for c in docs]

        # 3 queries:
        #   1 for fhe folders of the first level.
        #   0 for fhe folders of the second level, because already in the cache.
        #   1 for the users.
        #   1 for the roles.
        with self.assertNumQueries(3):
            populate_related(docs, ['linked_folder__parent', 'user__role'])

        # Folders
        with self.assertNumQueries(0):
            f1 = docs[0].linked_folder
        self.assertEqual(folder1, f1)

        with self.assertNumQueries(0):
            f11 = docs[1].linked_folder
        self.assertEqual(folder11, f11)

        with self.assertNumQueries(0):
            f1 = f11.parent
        self.assertEqual(folder1, f1)

        with self.assertNumQueries(0):
            f2 = docs[2].linked_folder
        self.assertEqual(folder2, f2)

        # Users
        with self.assertNumQueries(0):
            u1 = docs[0].user
        self.assertEqual(user, u1)

        with self.assertNumQueries(0):
            u2 = docs[2].user
        self.assertEqual(user2, u2)

        with self.assertNumQueries(0):
            role = u2.role
        self.assertEqual(self.role, role)
Example #7
0
    def test_populate_related06(self):
        "depth = 1"
        self.login()

        contacts = self._create_contacts()

        with self.assertNumQueries(1):
            populate_related(contacts, ['sector__title'])

        with self.assertNumQueries(0):
            s1 = contacts[0].sector
        self.assertEqual(self.sector1, s1)
Example #8
0
    def test_populate_related09(self):
        "Already cached field (level 2)"
        user = self.login()
        user2 = self.other_user

        create_contact = partial(FakeContact.objects.create, user=user, last_name='Simpson')
        contacts = [
            create_contact(first_name='Homer'),
            create_contact(first_name='Lisa', user=user2),
        ]

        contacts = [self.refresh(c) for c in contacts]
        _ = contacts[1].user  # 'user' is cached

        with self.assertNumQueries(2):
            populate_related(contacts, ['user__role__name'])
Example #9
0
    def test_populate_related02(self):
        "Two fields"
        self.login()
        contacts = self._create_contacts()

        with self.assertNumQueries(2):
            populate_related(contacts, ['sector', 'civility', 'last_name'])

        with self.assertNumQueries(0):
            s1 = contacts[0].sector
        self.assertEqual(self.sector1, s1)

        with self.assertNumQueries(0):
            c1 = contacts[1].civility
        self.assertEqual(self.civ1, c1)

        self.assertIsNone(contacts[2].civility)
Example #10
0
    def get_template_context(self, context, **kwargs):
        person = context['object']
        model = type(person)
        is_hidden = context['fields_configs'].get_4_model(
            model).is_field_hidden

        def prepare_address(attr_name):
            display_button = display_content = False

            try:
                addr = getattr(person, attr_name)
            except AttributeError:
                addr = Address()
            else:
                if is_hidden(model._meta.get_field(attr_name)):
                    if addr is None:
                        addr = Address()
                elif addr is None:
                    addr = Address()
                    display_button = True
                else:
                    display_content = True

            addr.display_button = display_button
            addr.display_content = display_content

            addr.owner = person  # NB: avoids a query (per address) for credentials.

            return addr

        populate_related((person, ), ['billing_address', 'shipping_address'])
        b_address = prepare_address('billing_address')
        s_address = prepare_address('shipping_address')

        build_cell = partial(EntityCellRegularField.build, model=Address)

        return super().get_template_context(
            context,
            b_address=b_address,
            s_address=s_address,
            cells=OrderedDict((fname, build_cell(name=fname))
                              for fname in _get_address_field_names()),
        )
Example #11
0
    def test_populate_related01(self):
        "One field"
        self.login()

        with self.assertNoException():
            populate_related([], ['sector'])

        contacts = self._create_contacts()

        with self.assertNumQueries(1):
            populate_related(contacts, ['sector'])

        with self.assertNumQueries(0):
            s1 = contacts[0].sector
        self.assertEqual(self.sector1, s1)

        with self.assertNumQueries(0):
            s2 = contacts[1].sector
        self.assertEqual(self.sector2, s2)

        self.assertIsNone(contacts[2].sector)
Example #12
0
    def test_populate_related07(self):
        "Field with depth=1 is a FK"
        user = self.login()

        create_folder = partial(FakeFolder.objects.create, user=user)
        folder1 = create_folder(title='Maps')
        folder11 = create_folder(title='Earth maps', parent=folder1)
        folder12 = create_folder(title='Mars maps', parent=folder1)
        folder2 = create_folder(title='Blue prints')

        create_doc = partial(FakeDocument.objects.create, user=user)
        docs = [
            create_doc(title='Japan map part#1', linked_folder=folder11),
            create_doc(title='Japan map part#2', linked_folder=folder11),
            create_doc(title='Mars city 1', linked_folder=folder12),
            create_doc(title='Swordfish', linked_folder=folder2),
        ]
        docs = [self.refresh(c) for c in docs]

        with self.assertNumQueries(2):
            populate_related(docs, ['linked_folder__parent', 'title'])

        with self.assertNumQueries(0):
            f11 = docs[0].linked_folder
        self.assertEqual(folder11, f11)

        with self.assertNumQueries(0):
            f1 = f11.parent
        self.assertEqual(folder1, f1)

        with self.assertNumQueries(0):
            f2 = docs[3].linked_folder
        self.assertEqual(folder2, f2)

        with self.assertNumQueries(0):
            f_null = f2.parent
        self.assertIsNone(f_null)