"""This example demonstrates most basic operations with single modeland a Table definition generation with comment support"""classEvent(db.Model):id=db.IntField(pk=True)name=db.TextField(description="Name of the event that corresponds to an action")datetime=db.DatetimeField(null=True,description="Datetime of when the event was generated")classMeta:table="event"table_description="This table contains a list of all the example events"def__str__(self):returnself.name@app.route("/events")asyncdefevents():event=awaitEvent.create(name="Test")awaitEvent.filter(id=event.id).update(name="Updated name")print(awaitEvent.filter(name="Updated name").first())awaitEvent(name="Test 2").save()print(awaitEvent.all().values_list("id",flat=True))print(awaitEvent.all().values("id","name"))return'null'if__name__=="__main__":app.run()
"""This example demonstrates how you can use transactions with tortoise"""fromtortoise.exceptionsimportOperationalErrorfromtortoise.transactionsimportatomic,in_transactionclassEvent(db.Model):id=db.IntField(pk=True)name=db.TextField()classMeta:table="event"def__str__(self):returnself.name@app.route("/run")asyncdefrun():try:asyncwithin_transaction()asconnection:event=Event(name="Test")awaitevent.save(using_db=connection)awaitEvent.filter(id=event.id).using_db(connection).update(name="Updated name")saved_event=awaitEvent.filter(name="Updated name").using_db(connection).first()awaitconnection.execute_query("SELECT * FROM non_existent_table")exceptOperationalError:passsaved_event=awaitEvent.filter(name="Updated name").first()print(saved_event)@atomic()asyncdefbound_to_fall():event=awaitEvent.create(name="Test")awaitEvent.filter(id=event.id).update(name="Updated name")saved_event=awaitEvent.filter(name="Updated name").first()print(saved_event.name)raiseOperationalError()try:awaitbound_to_fall()exceptOperationalError:passsaved_event=awaitEvent.filter(name="Updated name").first()print(saved_event)return'null'if__name__=="__main__":app.run()
"""This example shows some more complex queryingKey points are filtering by related names and using Q objects"""fromtortoise.query_utilsimportQclassTournament(db.Model):id=db.IntField(pk=True)name=db.TextField()events:db.ReverseRelation["Event"]def__str__(self):returnself.nameclassEvent(db.Model):id=db.IntField(pk=True)name=db.TextField()tournament:db.ForeignKeyRelation[Tournament]=db.ForeignKeyField("models.Tournament",related_name="events")participants:db.ManyToManyRelation["Team"]=db.ManyToManyField("models.Team",related_name="events",through="event_team")def__str__(self):returnself.nameclassTeam(db.Model):id=db.IntField(pk=True)name=db.TextField()events:db.ManyToManyRelation[Event]def__str__(self):returnself.name@app.route("/aniket")asyncdefrun():tournament=Tournament(name="Tournament")awaittournament.save()second_tournament=Tournament(name="Tournament 2")awaitsecond_tournament.save()event_first=Event(name="1",tournament=tournament)awaitevent_first.save()event_second=awaitEvent.create(name="2",tournament=second_tournament)awaitEvent.create(name="3",tournament=tournament)awaitEvent.create(name="4",tournament=second_tournament)awaitEvent.filter(tournament=tournament)team_first=Team(name="First")awaitteam_first.save()team_second=Team(name="Second")awaitteam_second.save()awaitteam_first.events.add(event_first)awaitevent_second.participants.add(team_second)print(awaitEvent.filter(Q(id__in=[event_first.id,event_second.id])|Q(name="3")).filter(participants__not=team_second.id).order_by("tournament__id").distinct())print(awaitTeam.filter(events__tournament_id=tournament.id).order_by("-events__name"))print(awaitTournament.filter(events__name__in=["1","3"]).order_by("-events__participants__name").distinct())print(awaitTeam.filter(name__icontains="CON"))print(awaitTournament.filter(events__participants__name__startswith="Fir"))print(awaitTournament.filter(id__icontains=1).count())return'null'if__name__=="__main__":app.run()
"""This example shows how relations between models work.Key points in this example are use of ForeignKeyField and ManyToManyFieldto declare relations and use of .prefetch_related() and .fetch_related()to get this related objects"""fromtortoise.exceptionsimportNoValuesFetchedclassTournament(db.Model):id=db.IntField(pk=True)name=db.TextField()events:db.ReverseRelation["Event"]def__str__(self):returnself.nameclassEvent(db.Model):id=db.IntField(pk=True)name=db.TextField()tournament:db.ForeignKeyRelation[Tournament]=db.ForeignKeyField("models.Tournament",related_name="events")participants:db.ManyToManyRelation["Team"]=db.ManyToManyField("models.Team",related_name="events",through="event_team")def__str__(self):returnself.nameclassAddress(db.Model):city=db.CharField(max_length=64)street=db.CharField(max_length=128)event:db.OneToOneRelation[Event]=db.OneToOneField("models.Event",on_delete=db.CASCADE,related_name="address",pk=True)def__str__(self):returnf"Address({self.city}, {self.street})"classTeam(db.Model):id=db.IntField(pk=True)name=db.TextField()events:db.ManyToManyRelation[Event]def__str__(self):returnself.name@app.route("/verloop")asyncdefrun():tournament=Tournament(name="New Tournament")awaittournament.save()awaitEvent(name="Without participants",tournament_id=tournament.id).save()event=Event(name="Test",tournament_id=tournament.id)awaitevent.save()awaitAddress.create(city="Santa Monica",street="Ocean",event=event)participants=[]foriinrange(2):team=Team(name=f"Team {(i+1)}")awaitteam.save()participants.append(team)awaitevent.participants.add(participants[0],participants[1])awaitevent.participants.add(participants[0],participants[1])try:forteaminevent.participants:print(team.id)exceptNoValuesFetched:passasyncforteaminevent.participants:print(team.id)forteaminevent.participants:print(team.id)print(awaitEvent.filter(participants=participants[0].id).prefetch_related("participants","tournament"))print(awaitparticipants[0].fetch_related("events"))print(awaitTeam.fetch_for_list(participants,"events"))print(awaitTeam.filter(events__tournament__id=tournament.id))print(awaitEvent.filter(tournament=tournament))print(awaitTournament.filter(events__name__in=["Test","Prod"]).order_by("-events__participants__name").distinct())print(awaitEvent.filter(id=event.id).values("id","name",tournament="tournament__name"))print(awaitEvent.filter(id=event.id).values_list("id","participants__name"))print(awaitAddress.filter(event=event).first())event_reload1=awaitEvent.filter(id=event.id).first()print(awaitevent_reload1.address)event_reload2=awaitEvent.filter(id=event.id).prefetch_related("address").first()print(event_reload2.address)return'null'if__name__=="__main__":app.run()
"""This example shows how relations between models especially unique field work.Key points in this example are use of ForeignKeyField and OneToOneField has to_field.For other basic parts, it is the same as relation exmaple."""fromtortoise.query_utilsimportPrefetchclassSchool(db.Model):uuid=db.UUIDField(pk=True)name=db.TextField()id=db.IntField(unique=True)students:db.ReverseRelation["Student"]principal:db.ReverseRelation["Principal"]classStudent(db.Model):id=db.IntField(pk=True)name=db.TextField()school:db.ForeignKeyRelation[School]=db.ForeignKeyField("models.School",related_name="students",to_field="id")classPrincipal(db.Model):id=db.IntField(pk=True)name=db.TextField()school:db.OneToOneRelation[School]=db.OneToOneField("models.School",on_delete=db.CASCADE,related_name="principal",to_field="id")@app.route("/forloop")asyncdefrun():school1=awaitSchool.create(id=1024,name="School1")student1=awaitStudent.create(name="Sang-Heon Jeon1",school_id=school1.id)student_schools=awaitStudent.filter(name="Sang-Heon Jeon1").values("name","school__name")print(student_schools[0])awaitStudent.create(name="Sang-Heon Jeon2",school=school1)school_with_filtered=(awaitSchool.all().prefetch_related(Prefetch("students",queryset=Student.filter(name="Sang-Heon Jeon1"))).first())school_without_filtered=awaitSchool.first().prefetch_related("students")print(len(school_with_filtered.students))print(len(school_without_filtered.students))school2=awaitSchool.create(id=2048,name="School2")awaitStudent.all().update(school=school2)student=awaitStudent.first()print(student.school_id)awaitStudent.filter(id=student1.id).update(school=school1)schools=awaitSchool.all().order_by("students__name")print([school.nameforschoolinschools])fetched_principal=awaitPrincipal.create(name="Sang-Heon Jeon3",school=school1)print(fetched_principal.name)fetched_school=awaitSchool.filter(name="School1").prefetch_related("principal").first()print(fetched_school.name)return'null'if__name__=="__main__":app.run()
"""This example shows how self-referential (recursive) relations work.Key points in this example are:* Use of ForeignKeyField that refers to self* To pass in the (optional) parent node at creation* To use async iterator to fetch children* To use .fetch_related(…) to emulate sync behaviour* That insert-order gets preserved for ForeignFields, but not ManyToManyFields"""classEmployee(db.Model):name=db.CharField(max_length=50)manager:db.ForeignKeyNullableRelation["Employee"]=db.ForeignKeyField("models.Employee",related_name="team_members",null=True)team_members:db.ReverseRelation["Employee"]talks_to:db.ManyToManyRelation["Employee"]=db.ManyToManyField("models.Employee",related_name="gets_talked_to")gets_talked_to:db.ManyToManyRelation["Employee"]def__str__(self):returnself.nameasyncdeffull_hierarchy__async_for(self,level=0):""" Demonstrates ``async for` to fetch relations An async iterator will fetch the relationship on-demand. """text=["{}{} (to: {}) (from: {})".format(level*" ",self,", ".join([str(val)asyncforvalinself.talks_to]),", ".join([str(val)asyncforvalinself.gets_talked_to]),)]asyncformemberinself.team_members:text.append(awaitmember.full_hierarchy__async_for(level+1))return"\n".join(text)asyncdeffull_hierarchy__fetch_related(self,level=0):""" Demonstrates ``await .fetch_related`` to fetch relations On prefetching the data, the relationship files will contain a regular list. This is how one would get relations working on sync serialization/templating frameworks. """awaitself.fetch_related("team_members","talks_to","gets_talked_to")text=["{}{} (to: {}) (from: {})".format(level*" ",self,", ".join([str(val)forvalinself.talks_to]),", ".join([str(val)forvalinself.gets_talked_to]),)]formemberinself.team_members:text.append(awaitmember.full_hierarchy__fetch_related(level+1))return"\n".join(text)@app.route("/relationer")asyncdefrun():root=awaitEmployee.create(name="Root")loose=awaitEmployee.create(name="Loose")_1=awaitEmployee.create(name="1. First H1",manager=root)_2=awaitEmployee.create(name="2. Second H1",manager=root)_1_1=awaitEmployee.create(name="1.1. First H2",manager=_1)_1_1_1=awaitEmployee.create(name="1.1.1. First H3",manager=_1_1)_2_1=awaitEmployee.create(name="2.1. Second H2",manager=_2)_2_2=awaitEmployee.create(name="2.2. Third H2",manager=_2)await_1.talks_to.add(_2,_1_1_1,loose)await_2_1.gets_talked_to.add(_2_2,_1_1,loose)# Evaluated off creation objectsprint(awaitloose.full_hierarchy__fetch_related())print(awaitroot.full_hierarchy__async_for())print(awaitroot.full_hierarchy__fetch_related())# Evaluated off new objects → Result is identicalroot2=awaitEmployee.get(name="Root")loose2=awaitEmployee.get(name="Loose")print(awaitloose2.full_hierarchy__fetch_related())print(awaitroot2.full_hierarchy__async_for())print(awaitroot2.full_hierarchy__fetch_related())return'null'if__name__=="__main__":app.run()