The 'anki' Module
All access to your collection and associated media go through a Python
package called anki
, located in
pylib/anki
in Anki's source repo.
The Collection
All operations on a collection file are accessed via a Collection
object. The currently-open Collection is accessible via a global mw.col
,
where mw
stands for main window
. When using the anki
module outside
of Anki, you will need to create your own Collection object.
Some basic examples of what you can do follow. Please note that you should put these in something like testFunction(). You can’t run them directly in an add-on, as add-ons are initialized during Anki startup, before any collection or profile has been loaded.
Also please note that accessing the collection directly can lead to the UI temporarily freezing if the operation doesn't complete quickly - in practice you would typically run the code below in a background thread.
Get a due card:
card = mw.col.sched.getCard()
if not card:
# current deck is finished
Answer the card:
mw.col.sched.answerCard(card, ease)
Edit a note (append " new" to the end of each field):
note = card.note()
for (name, value) in note.items():
note[name] = value + " new"
mw.col.update_note(note)
Get card IDs for notes with tag x:
ids = mw.col.find_cards("tag:x")
Get question and answer for each of those ids:
for id in ids:
card = mw.col.get_card(id)
question = card.question()
answer = card.answer()
Make reviews due tomorrow
ids = mw.col.find_cards("is:due")
mw.col.sched.set_due_date(ids, "1")
Import a text file into the collection
Requires Anki 2.1.55+.
from anki.collection import ImportCsvRequest
from aqt import mw
col = mw.col
path = "/home/dae/foo.csv"
metadata = col.get_csv_metadata(path=path, delimiter=None)
request = ImportCsvRequest(path=path, metadata=metadata)
response = col.import_csv(request)
print(response.log.found_notes, list(response.log.updated), list(response.log.new))
Almost every GUI operation has an associated function in anki, so any of the operations that Anki makes available can also be called in an add-on.
Reading/Writing Objects
Most objects in Anki can be read and written via methods in pylib.
card = col.get_card(card_id)
card.ivl += 1
col.update_card(card)
note = col.get_note(note_id)
note["Front"] += " hello"
col.update_note(note)
deck = col.decks.get(deck_id)
deck["name"] += " hello"
col.decks.save(deck)
deck = col.decks.by_name("Default hello")
...
config = col.decks.get_config(config_id)
config["new"]["perDay"] = 20
col.decks.save(config)
notetype = col.models.get(notetype_id)
notetype["css"] += "\nbody { background: grey; }\n"
col.models.save(note)
notetype = col.models.by_name("Basic")
...
You should prefer these methods over directly accessing the database, as they take care of marking items as requiring a sync, and they prevent some forms of invalid data from being written to the database.
For locating specific cards and notes, col.find_cards() and col.find_notes() are useful.
The Database
:warning: You can easily cause problems by writing directly to the database. Where possible, please use methods such as the ones mentioned above instead.
Anki’s DB object supports the following functions:
scalar() returns a single item:
showInfo("card count: %d" % mw.col.db.scalar("select count() from cards"))
list() returns a list of the first column in each row, e.g.[1, 2, 3]:
ids = mw.col.db.list("select id from cards limit 3")
all() returns a list of rows, where each row is a list:
ids_and_ivl = mw.col.db.all("select id, ivl from cards")
execute() can also be used to iterate over a result set without building an intermediate list. eg:
for id, ivl in mw.col.db.execute("select id, ivl from cards limit 3"):
showInfo("card id %d has ivl %d" % (id, ivl))
execute() allows you to perform an insert or update operation. Use named arguments with ?. eg:
mw.col.db.execute("update cards set ivl = ? where id = ?", newIvl, cardId)
Note that these changes won't sync, as they would if you used the functions mentioned in the previous section.
executemany() allows you to perform bulk update or insert operations. For large updates, this is much faster than calling execute() for each data point. eg:
data = [[newIvl1, cardId1], [newIvl2, cardId2]]
mw.col.db.executemany(same_sql_as_above, data)
As above, these changes won't sync.
Add-ons should never modify the schema of existing tables, as that may break future versions of Anki.
If you need to store addon-specific data, consider using Anki’s Configuration support.
If you need the data to sync across devices, small options can be stored within mw.col.conf. Please don’t store large amounts of data there, as it’s currently sent on every sync.