{"componentChunkName":"component---src-templates-post-tsx","path":"/posts/2019/07/anki-sqlite-edit/","result":{"data":{"markdownRemark":{"fields":{"slug":"/2019/07/anki-sqlite-edit/"},"frontmatter":{"title":"Creating and editing Anki's *.apkg and *.anki2 via SQLite","tag":["anki","sqlite","peewee","pinned"],"image":"https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcR4ooqth-qfi7gtBk5tgnXGiF6CUAhQzLemTpLRUjtSUox19l9T"},"correctedDateEpoch":1564419600000,"html":"<p>*.apkg and *.anki2 file structure is very simple, but with some quirks of incompleteness.</p>\n<p><a href=\"https://github.com/ankidroid/Anki-Android/wiki/Database-Structure\">*.apkg file structure</a> is a zip of at least two files.</p>\n<!-- excerpt_separator -->\n<pre><code>.\n├── example\n│   ├── example.anki2\n│   ├── media\n│   ├── 1  # Media files with the names masked as numbers\n│   ├── 2\n│   ├── 3\n|   └── ...\n└── example.apkg\n</code></pre>\n<p>*.anki2 is a SQLite file with foreign key disabled, and the usage of <a href=\"/ankisync2/builder/default.py\">some JSON schemas</a> instead of <a href=\"/ankisync2/db.py#L46\">some tables</a></p>\n<p>Also, *.anki2 is used internally at <a href=\"https://github.com/patarapolw/ankisync/blob/master/ankisync/dir.py#L9\"><code>os.path.join(appdirs.user_data_dir('Anki2'), 'User 1', 'collection.anki2')</code></a>, so editing the SQLite there will also edit the database.</p>\n<p>The <code>media</code> file is a text file of at least a string of <code>{}</code>, which is actually a dictionary of keys -- stringified int; and values -- filenames.</p>\n<p>I created a <a href=\"https://github.com/patarapolw/ankisync2\">PyPI package</a> is ease the editing of this SQLite (and text file), powered by <a href=\"http://docs.peewee-orm.com/en/latest/index.html\">Peewee ORM</a>.</p>\n<p><a href=\"https://github.com/patarapolw/ankisync2\">https://github.com/patarapolw/ankisync2</a></p>"}},"pageContext":{"slug":"/2019/07/anki-sqlite-edit/"}}}