示例#1
0
    async def get_and_cache(cls, id, model=False):
        """
        Get a user's cachable data and cache it for future use. Replaces data if exists.
        Similar to the dependency current_user.
        :param id:      User id as str
        :param model:   Also return the UserMod instance
        :return:        DOESN'T NEED cache.restoreuser() since data is from the db not redis.
                        The id key in the hash is already formatted to a str from UUID.
                        Can be None if user doesn't exist.
        """
        from app.auth import userdb

        query = UserMod.get_or_none(pk=id) \
            .prefetch_related(
                Prefetch('groups', queryset=Group.all().only('id', 'name')),
                Prefetch('options', queryset=Option.all().only('user_id', 'name', 'value')),
                Prefetch('permissions', queryset=Permission.filter(deleted_at=None).only('id', 'code'))
            )
        if userdb.oauth_account_model is not None:
            query = query.prefetch_related("oauth_accounts")
        usermod = await query.only(*userdb.select_fields)

        if usermod:
            user_dict = await usermod.to_dict(prefetch=True)
            partialkey = s.CACHE_USERNAME.format(id)
            red.set(partialkey, cache.prepareuser_dict(user_dict), clear=True)

            if model:
                return userdb.usercomplete(**user_dict), usermod
            return userdb.usercomplete(**user_dict)
async def run():
    await Tortoise.init(db_url="sqlite://:memory:", modules={"models": ["__main__"]})
    await Tortoise.generate_schemas()

    tournament = await Tournament.create(name="tournament")
    await Event.create(name="First", tournament=tournament)
    await Event.create(name="Second", tournament=tournament)
    tournament_with_filtered = (
        await Tournament.all()
        .prefetch_related(Prefetch("events", queryset=Event.filter(name="First")))
        .first()
    )
    print(tournament_with_filtered)
    print(await Tournament.first().prefetch_related("events"))

    tournament_with_filtered_to_attr = (
        await Tournament.all()
        .prefetch_related(
            Prefetch("events", queryset=Event.filter(name="First"), to_attr="to_attr_events_first"),
            Prefetch(
                "events", queryset=Event.filter(name="Second"), to_attr="to_attr_events_second"
            ),
        )
        .first()
    )
    print(tournament_with_filtered_to_attr.to_attr_events_first)
    print(tournament_with_filtered_to_attr.to_attr_events_second)
示例#3
0
 async def test_prefetch_m2m_to_attr(self):
     tournament = await Tournament.create(name="tournament")
     team = await Team.create(name="1")
     team_second = await Team.create(name="2")
     event = await Event.create(name="First", tournament=tournament)
     await event.participants.add(team, team_second)
     event = await Event.first().prefetch_related(
         Prefetch("participants", Team.filter(name="1"), to_attr="to_attr_participants_1"),
         Prefetch("participants", Team.filter(name="2"), to_attr="to_attr_participants_2"),
     )
     self.assertEqual(list(event.to_attr_participants_1), [team])
     self.assertEqual(list(event.to_attr_participants_2), [team_second])
 async def low_battery(self, percent: float) -> List[Bike]:
     """Gets all bikes with less than the given battery level."""
     low_battery_ids = {
         k: v
         for k, v in self._bike_battery.items() if v <= percent
     }
     return await Bike.filter(id__in=low_battery_ids).prefetch_related(
         "state_updates",
         Prefetch("location_updates",
                  queryset=LocationUpdate.all().limit(100)),
         Prefetch("issues",
                  queryset=Issue.filter(status__not=IssueStatus.CLOSED)))
示例#5
0
async def get_bikes(*, bike_ids: List[int] = None) -> List[Bike]:
    """Gets all the bikes from the system."""
    if bike_ids is not None:
        query = Bike.filter(id__in=bike_ids)
    else:
        query = Bike.all()

    return await query.prefetch_related(
        Prefetch("location_updates", queryset=LocationUpdate.all().limit(100)),
        "state_updates",
        Prefetch("issues",
                 queryset=Issue.filter(status__not=IssueStatus.CLOSED)))
示例#6
0
 async def test_prefetch_nested(self):
     tournament = await Tournament.create(name='tournament')
     event = await Event.create(name='First', tournament=tournament)
     await Event.create(name='Second', tournament=tournament)
     team = await Team.create(name='1')
     team_second = await Team.create(name='2')
     await event.participants.add(team, team_second)
     fetched_tournaments = await Tournament.all().prefetch_related(
         Prefetch('events', queryset=Event.filter(name='First')),
         Prefetch('events__participants',
                  queryset=Team.filter(name='1'))).first()
     self.assertEqual(len(fetched_tournaments.events[0].participants), 1)
示例#7
0
 async def test_prefetch_nested(self):
     tournament = await Tournament.create(name="tournament")
     event = await Event.create(name="First", tournament=tournament)
     await Event.create(name="Second", tournament=tournament)
     team = await Team.create(name="1")
     team_second = await Team.create(name="2")
     await event.participants.add(team, team_second)
     fetched_tournaments = (await Tournament.all().prefetch_related(
         Prefetch("events", queryset=Event.filter(name="First")),
         Prefetch("events__participants", queryset=Team.filter(name="1")),
     ).first())
     self.assertEqual(len(fetched_tournaments.events[0].participants), 1)
示例#8
0
 async def test_prefetch_direct_relation_to_attr(self):
     tournament = await Tournament.create(name="tournament")
     await Event.create(name="First", tournament=tournament)
     event = await Event.first().prefetch_related(
         Prefetch("tournament", queryset=Tournament.all(), to_attr="to_attr_tournament")
     )
     self.assertEqual(event.to_attr_tournament.id, tournament.id)
示例#9
0
async def get_broken_bikes() -> List[Tuple[Bike, List[Issue]]]:
    """
    Gets the list of all broken bikes ie. those with active issues.

    :returns: A tuple of the list of identifiers,
     a dictionary mapping the identifier to its bike,
     and a dictionary mapping the identifier to its list of issues
    """
    active_issues: List[Issue] = await Issue.filter(
        status__not=IssueStatus.CLOSED,
        bike_id__not_isnull=True).prefetch_related(
            'bike', 'bike__state_updates',
            Prefetch("bike__issues",
                     queryset=Issue.filter(status__not=IssueStatus.CLOSED)))

    broken_bikes = {}

    for issue in active_issues:
        if issue.bike.identifier not in broken_bikes:
            broken_bikes[issue.bike.identifier] = (issue.bike, [])

        bike, issues = broken_bikes[issue.bike.identifier]
        issues.append(issue)

    return list(broken_bikes.values())
示例#10
0
    async def on_get(self, req: Request, resp: Response, space: str) -> None:
        """
        Get a user

        :param int user_id: The id of the user.
        """
        space_relation = {
            "student": "student_schools",
            "headmaster": "principal_schools",
            "teacher": "teacher_schools",
        }
        try:
            user = None
            relation = space_relation.get(space, None)

            if relation is None:
                resp.status_code = 404
                resp.text = "unknown relation type"
            else:
                query = User.get_or_none(
                    id=self.current_user.id).prefetch_related(
                        Prefetch(relation,
                                 queryset=self.only(req, School.all())))
                user = await query
                SchoolModel.list_model([
                    SchoolModel.from_orm(school)
                    for school in getattr(user, relation, [])
                ]).send_json(resp)

        except Exception as error:  # pylint: disable=W0703
            error_response(resp, 500, str(error))
示例#11
0
    async def on_get(self, req: Request, resp: Response, *, right_id: int, role_id: int):
        """
        Returns a role that is associated with a given right.

        :param int right_id: The id of the right
        :param int role_id: The id of the role that has to be assiociated with the right.
        """
        try:
            # Prefetching roles for the right specified by its ID.
            # Requesting only role fields specified by the filter
            # criterias from ther request header or all, if no
            # filter was specified.
            # TODO: Maybe reverse the query, as we are looking for a specific
            # role. So start with 'await Role.get(...)'. Tis iliminates the need
            # for an extra search operation (aka find_role)
            right = await Right.get(id=right_id).prefetch_related(
                Prefetch("roles", queryset=self.only(req, Role.filter(id=role_id)))
            )
            role = find_role(right, role_id)

            if role is not None:
                RoleModel.from_orm(role).send_json(resp)
                return

            resp.status_code = 404
            resp.text = f"No role with id '{role_id}' found for right '{right.name} [{right.id}]'."

        except DoesNotExist:
            resp.status_code = 404
            resp.text = f"No right with id '{right_id}' found."

        except Exception as error:  # pylint: disable=broad-except
            error_response(resp, 500, error)
示例#12
0
 async def test_prefetch_unknown_field(self):
     with self.assertRaises(OperationalError):
         tournament = await Tournament.create(name="tournament")
         await Event.create(name="First", tournament=tournament)
         await Event.create(name="Second", tournament=tournament)
         await Tournament.all().prefetch_related(
             Prefetch("events1",
                      queryset=Event.filter(name="First"))).first()
示例#13
0
 async def test_prefetch_unknown_field(self):
     with self.assertRaises(OperationalError):
         tournament = await Tournament.create(name='tournament')
         await Event.create(name='First', tournament=tournament)
         await Event.create(name='Second', tournament=tournament)
         await Tournament.all().prefetch_related(
             Prefetch('events1',
                      queryset=Event.filter(name='First'))).first()
示例#14
0
 async def test_prefetch_o2o_to_attr(self):
     tournament = await Tournament.create(name="tournament")
     event = await Event.create(name="First", tournament=tournament)
     address = await Address.create(city="Santa Monica", street="Ocean", event=event)
     event = await Event.get(pk=event.pk).prefetch_related(
         Prefetch("address", to_attr="to_address", queryset=Address.all())
     )
     self.assertEqual(address.pk, event.to_address.pk)
示例#15
0
async def _get_lesson_tasks_with_solutions(lesson: Lesson,
                                           user: User) -> List[Task]:
    """Получение списка задач урока с их решением."""
    return await (Task.filter(lesson_id=lesson.id).prefetch_related(
        Prefetch(
            "solutions",
            queryset=TaskSolution.filter(student_id=user.id),
            to_attr="solution",
        )))
示例#16
0
    async def find_courses(self, **kwargs) -> List[COURSE]:
        try:
            school = await School.get(id=self.id).prefetch_related(
                Prefetch("courses", queryset=Course.filter(**kwargs))
            )
            return [CourseModel.from_orm(course) for course in school.courses]

        except FieldError as error:
            raise QueryError(str(error)) from error
示例#17
0
 async def test_prefetch_object(self):
     tournament = await Tournament.create(name="tournament")
     await Event.create(name="First", tournament=tournament)
     await Event.create(name="Second", tournament=tournament)
     tournament_with_filtered = (await Tournament.all().prefetch_related(
         Prefetch("events", queryset=Event.filter(name="First"))).first())
     tournament = await Tournament.first().prefetch_related("events")
     self.assertEqual(len(tournament_with_filtered.events), 1)
     self.assertEqual(len(tournament.events), 2)
示例#18
0
 async def test_prefetching(self):
     tournament = await Tournament.create(name='tournament')
     await Event.create(name='First', tournament=tournament)
     await Event.create(name='Second', tournament=tournament)
     tournament_with_filtered = await Tournament.all().prefetch_related(
         Prefetch('events', queryset=Event.filter(name='First'))).first()
     tournament = await Tournament.first().prefetch_related('events')
     self.assertEqual(len(tournament_with_filtered.events), 1)
     self.assertEqual(len(tournament.events), 2)
示例#19
0
    async def find_units(self, **kwargs) -> List[UNIT]:
        try:
            course = await Course.get(id=self.id).prefetch_related(
                Prefetch("units", queryset=Unit.filter(**kwargs))
            )
            return [UnitModel.from_orm(unit) for unit in course.units]

        except FieldError as error:
            raise QueryError(str(error)) from error
示例#20
0
    async def get_available_bikes_out_of(self,
                                         bike_ids: List[int]) -> List[Bike]:
        """Given a list of bike ids, checks if they are free or not and returns the ones that are free."""
        used_bikes = {
            bike_id
            for rental_id, bike_id in self._active_rentals.values()
        }
        available_bikes = set(bike_ids) - used_bikes

        if not available_bikes:
            return []

        query = Bike.filter(id__in=available_bikes)

        return await query.prefetch_related(
            Prefetch("location_updates",
                     queryset=LocationUpdate.all().limit(100)),
            "state_updates",
            Prefetch("issues",
                     queryset=Issue.filter(status__not=IssueStatus.CLOSED)))
示例#21
0
async def run():
    await Tortoise.init(config_file='config.json')
    await Tortoise.generate_schemas()

    tournament = await Tournament.create(name='tournament')
    await Event.create(name='First', tournament=tournament)
    await Event.create(name='Second', tournament=tournament)
    tournament_with_filtered = await Tournament.all().prefetch_related(
        Prefetch('events', queryset=Event.filter(name='First'))).first()
    print(tournament_with_filtered)
    print(await Tournament.first().prefetch_related('events'))
示例#22
0
async def get_bike(*,
                   identifier: Union[str, bytes] = None,
                   public_key: bytes = None) -> Optional[Bike]:
    """Gets a bike from the system."""
    kwargs: Dict = {}

    if public_key:
        kwargs["public_key_hex"] = public_key.hex()
    if identifier:
        kwargs["public_key_hex__startswith"] = identifier.hex() if isinstance(
            identifier, bytes) else identifier

    try:
        return await Bike.get(**kwargs).first().prefetch_related(
            Prefetch("location_updates",
                     queryset=LocationUpdate.all().limit(100)),
            "state_updates",
            Prefetch("issues",
                     queryset=Issue.filter(status__not=IssueStatus.CLOSED)))
    except DoesNotExist:
        return None
示例#23
0
async def run():
    client = SqliteClient('example_prefetching.sqlite3')
    await client.create_connection()
    Tortoise.init(client)
    await generate_schema(client)

    tournament = await Tournament.create(name='tournament')
    await Event.create(name='First', tournament=tournament)
    await Event.create(name='Second', tournament=tournament)
    tournament_with_filtered = await Tournament.all().prefetch_related(
        Prefetch('events', queryset=Event.filter(name='First'))).first()
    print(tournament_with_filtered)
    print(await Tournament.first().prefetch_related('events'))
示例#24
0
 async def test_prefetch_nested_with_aggregation(self):
     tournament = await Tournament.create(name='tournament')
     event = await Event.create(name='First', tournament=tournament)
     await Event.create(name='Second', tournament=tournament)
     team = await Team.create(name='1')
     team_second = await Team.create(name='2')
     await event.participants.add(team, team_second)
     fetched_tournaments = await Tournament.all().prefetch_related(
         Prefetch('events',
                  queryset=Event.annotate(
                      teams=Count('participants')).filter(teams=2))
     ).first()
     self.assertEqual(len(fetched_tournaments.events), 1)
     self.assertEqual(fetched_tournaments.events[0].id, event.id)
示例#25
0
 async def test_prefetch_nested_with_aggregation(self):
     tournament = await Tournament.create(name="tournament")
     event = await Event.create(name="First", tournament=tournament)
     await Event.create(name="Second", tournament=tournament)
     team = await Team.create(name="1")
     team_second = await Team.create(name="2")
     await event.participants.add(team, team_second)
     fetched_tournaments = (await Tournament.all().prefetch_related(
         Prefetch("events",
                  queryset=Event.annotate(
                      teams=Count("participants")).filter(teams=2))
     ).first())
     self.assertEqual(len(fetched_tournaments.events), 1)
     self.assertEqual(fetched_tournaments.events[0].id, event.id)
示例#26
0
async def get_jrnl_by_name(user_id: str,
                           jrnl_name: str,
                           deleted: bool = False) -> Optional[Journal]:
    if deleted:
        jrnl = await Journal.get_or_none(name_lower=jrnl_name, user_id=user_id)
        if jrnl is not None:
            await jrnl.fetch_related("entries__keywords")
    else:
        jrnl = await Journal.all()\
            .prefetch_related(Prefetch("entries", queryset=Entry.filter(deleted_on=None)))\
            .get_or_none(name_lower=jrnl_name, user_id=user_id, deleted_on=None)
        if jrnl is not None:
            await Entry.fetch_for_list(list(jrnl.entries), "keywords")

    return jrnl
    async def test_relation_with_unique(self):
        school1 = await School.create(id=1024, name="School1")
        student1 = await Student.create(name="Sang-Heon Jeon1",
                                        school_id=school1.id)

        student_schools = await Student.filter(name="Sang-Heon Jeon1").values(
            "name", "school__name")
        self.assertEqual(student_schools[0], {
            "name": "Sang-Heon Jeon1",
            "school__name": "School1"
        })
        student_schools = await Student.all().values(school="school__name")
        self.assertEqual(student_schools[0]["school"], school1.name)
        student_schools = await Student.all().values_list("school__name")
        self.assertEqual(student_schools[0][0], school1.name)

        await Student.create(name="Sang-Heon Jeon2", school=school1)
        school_with_filtered = (await School.all().prefetch_related(
            Prefetch("students",
                     queryset=Student.filter(name="Sang-Heon Jeon1"))).first())
        school_without_filtered = await School.first().prefetch_related(
            "students")
        self.assertEqual(len(school_with_filtered.students), 1)
        self.assertEqual(len(school_without_filtered.students), 2)

        student_direct_prefetch = await Student.first().prefetch_related(
            "school")
        self.assertEqual(student_direct_prefetch.school.id, school1.id)

        school2 = await School.create(id=2048, name="School2")
        await Student.all().update(school=school2)
        student = await Student.first()
        self.assertEqual(student.school_id, school2.id)

        await Student.filter(id=student1.id).update(school=school1)
        schools = await School.all().order_by("students__name")
        self.assertEqual([school.name for school in schools],
                         ["School1", "School2"])
        schools = await School.all().order_by("-students__name")
        self.assertEqual([school.name for school in schools],
                         ["School2", "School1"])

        fetched_principal = await Principal.create(name="Sang-Heon Jeon3",
                                                   school=school1)
        self.assertEqual(fetched_principal.name, "Sang-Heon Jeon3")
        fetched_school = await School.filter(
            name="School1").prefetch_related("principal").first()
        self.assertEqual(fetched_school.name, "School1")
示例#28
0
async def get_journals_for(user: User,
                           skip: int = 0,
                           limit: int = 100,
                           deleted: bool = False):
    if deleted:
        jrnls = await Journal.filter(user_id=user.id
                                     ).offset(skip).limit(limit).all()
    else:
        jrnls = await Journal.all()\
            .prefetch_related(Prefetch("entries", queryset=Entry.filter(deleted_on=None)))\
            .filter(user_id=user.id, deleted_on=None).offset(skip).limit(limit).all()

    await Journal.fetch_for_list(jrnls, "entries")
    for jrnl in jrnls:
        await Entry.fetch_for_list(list(jrnl.entries), "keywords")
        if not deleted:
            await jrnl.filter(deleted_on=None)

    return jrnls
示例#29
0
async def run():
    await Tortoise.init(db_url="sqlite://:memory:",
                        modules={"models": ["__main__"]})
    await Tortoise.generate_schemas()

    school1 = await School.create(id=1024, name="School1")
    student1 = await Student.create(name="Sang-Heon Jeon1",
                                    school_id=school1.id)

    student_schools = await Student.filter(name="Sang-Heon Jeon1"
                                           ).values("name", "school__name")
    print(student_schools[0])

    await Student.create(name="Sang-Heon Jeon2", school=school1)
    school_with_filtered = (await School.all().prefetch_related(
        Prefetch("students",
                 queryset=Student.filter(name="Sang-Heon Jeon1"))).first())
    school_without_filtered = await School.first().prefetch_related("students")
    print(len(school_with_filtered.students))
    print(len(school_without_filtered.students))

    school2 = await School.create(id=2048, name="School2")
    await Student.all().update(school=school2)
    student = await Student.first()
    print(student.school_id)

    await Student.filter(id=student1.id).update(school=school1)
    schools = await School.all().order_by("students__name")
    print([school.name for school in schools])

    fetched_principal = await Principal.create(name="Sang-Heon Jeon3",
                                               school=school1)
    print(fetched_principal.name)
    fetched_school = await School.filter(
        name="School1").prefetch_related("principal").first()
    print(fetched_school.name)
示例#30
0
 async def resolve_place_gallery(cls, parent: PlaceModel,
                                 info: ResolveInfo) -> List[FileModel]:
     gallery = await parent.gallery.all().prefetch_related(
         Prefetch('file', FileModel.all()))
     return [gm.file for gm in gallery]