mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 00:36:38 -04:00
add ability to update fields when importing
This commit is contained in:
parent
dd00d1a5e1
commit
e3dd736460
3 changed files with 119 additions and 1 deletions
|
@ -18,8 +18,8 @@ from anki.cards import cardsTable
|
||||||
from anki.facts import factsTable, fieldsTable
|
from anki.facts import factsTable, fieldsTable
|
||||||
from anki.lang import _
|
from anki.lang import _
|
||||||
from anki.utils import genID, canonifyTags
|
from anki.utils import genID, canonifyTags
|
||||||
|
from anki.utils import canonifyTags, ids2str
|
||||||
from anki.errors import *
|
from anki.errors import *
|
||||||
from anki.utils import canonifyTags
|
|
||||||
from anki.deck import NEW_CARDS_RANDOM
|
from anki.deck import NEW_CARDS_RANDOM
|
||||||
|
|
||||||
# Base importer
|
# Base importer
|
||||||
|
@ -35,6 +35,9 @@ class Importer(object):
|
||||||
|
|
||||||
needMapper = True
|
needMapper = True
|
||||||
tagDuplicates = False
|
tagDuplicates = False
|
||||||
|
# if set, update instead of regular importing
|
||||||
|
# (foreignCardFieldIndex, fieldModelId)
|
||||||
|
updateKey = None
|
||||||
multipleCardsAllowed = True
|
multipleCardsAllowed = True
|
||||||
needDelimiter = False
|
needDelimiter = False
|
||||||
|
|
||||||
|
@ -49,6 +52,8 @@ class Importer(object):
|
||||||
|
|
||||||
def doImport(self):
|
def doImport(self):
|
||||||
"Import. Caller must .reset()"
|
"Import. Caller must .reset()"
|
||||||
|
if self.updateKey is not None:
|
||||||
|
return self.doUpdate()
|
||||||
random = self.deck.newCardOrder == NEW_CARDS_RANDOM
|
random = self.deck.newCardOrder == NEW_CARDS_RANDOM
|
||||||
num = 7
|
num = 7
|
||||||
if random:
|
if random:
|
||||||
|
@ -68,6 +73,85 @@ class Importer(object):
|
||||||
if c:
|
if c:
|
||||||
self.deck.setModified()
|
self.deck.setModified()
|
||||||
|
|
||||||
|
def doUpdate(self):
|
||||||
|
self.deck.startProgress(8)
|
||||||
|
# grab the data from the external file
|
||||||
|
self.deck.updateProgress(_("Updating..."))
|
||||||
|
cards = self.foreignCards()
|
||||||
|
# grab data from db
|
||||||
|
self.deck.updateProgress()
|
||||||
|
fields = self.deck.s.all("""
|
||||||
|
select factId, value from fields where fieldModelId = :id
|
||||||
|
and value != ''""",
|
||||||
|
id=self.updateKey[1])
|
||||||
|
# hash it
|
||||||
|
self.deck.updateProgress()
|
||||||
|
vhash = {}
|
||||||
|
fids = []
|
||||||
|
for (fid, val) in fields:
|
||||||
|
fids.append(fid)
|
||||||
|
vhash[val] = fid
|
||||||
|
# prepare tags
|
||||||
|
tagsIdx = None
|
||||||
|
try:
|
||||||
|
tagsIdx = self.mapping.index(0)
|
||||||
|
for c in cards:
|
||||||
|
c.tags = canonifyTags(self.tagsToAdd + " " + c.fields[tagsIdx])
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
# look for matches
|
||||||
|
self.deck.updateProgress()
|
||||||
|
upcards = []
|
||||||
|
newcards = []
|
||||||
|
for c in cards:
|
||||||
|
v = c.fields[self.updateKey[0]]
|
||||||
|
if v in vhash:
|
||||||
|
# ignore empty keys
|
||||||
|
if v:
|
||||||
|
# fid, card
|
||||||
|
upcards.append((vhash[v], c))
|
||||||
|
else:
|
||||||
|
newcards.append(c)
|
||||||
|
# update fields
|
||||||
|
for fm in self.model.fieldModels:
|
||||||
|
if fm.id == self.updateKey[1]:
|
||||||
|
# don't update key
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
index = self.mapping.index(fm)
|
||||||
|
except ValueError:
|
||||||
|
# not mapped
|
||||||
|
continue
|
||||||
|
data = [{'fid': fid,
|
||||||
|
'fmid': fm.id,
|
||||||
|
'v': c.fields[index]}
|
||||||
|
for (fid, c) in upcards]
|
||||||
|
self.deck.s.execute("""
|
||||||
|
update fields set value = :v where factId = :fid and fieldModelId = :fmid""",
|
||||||
|
data)
|
||||||
|
# update tags
|
||||||
|
self.deck.updateProgress()
|
||||||
|
if tagsIdx:
|
||||||
|
data = [{'factId': fid,
|
||||||
|
'tags': c.fields[tagsIdx]}
|
||||||
|
for (fid, c) in upcards]
|
||||||
|
self.deck.s.execute(
|
||||||
|
"update facts set tags = :t where id = :fid",
|
||||||
|
data)
|
||||||
|
# rebuild caches
|
||||||
|
self.deck.updateProgress()
|
||||||
|
cids = self.deck.s.column0(
|
||||||
|
"select id from cards where factId in %s" %
|
||||||
|
ids2str(fids))
|
||||||
|
self.deck.updateCardTags(cids)
|
||||||
|
self.deck.updateProgress()
|
||||||
|
self.deck.updatePriorities(cids)
|
||||||
|
self.deck.updateProgress()
|
||||||
|
self.deck.updateCardsFromFactIds(fids)
|
||||||
|
self.total = len(fids)
|
||||||
|
self.deck.setModified()
|
||||||
|
self.deck.finishProgress()
|
||||||
|
|
||||||
def fields(self):
|
def fields(self):
|
||||||
"The number of fields."
|
"The number of fields."
|
||||||
return 0
|
return 0
|
||||||
|
|
11
tests/importing/text-update.txt
Normal file
11
tests/importing/text-update.txt
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# this is a test file
|
||||||
|
|
||||||
|
食べる to ate
|
||||||
|
む to drink
|
||||||
|
テスト testing
|
||||||
|
to eat 食べる
|
||||||
|
飲む to drink
|
||||||
|
多すぎる too many fields
|
||||||
|
not, enough, fields
|
||||||
|
遊ぶ
|
||||||
|
to play
|
|
@ -114,3 +114,26 @@ def test_dingsbums():
|
||||||
i.doImport()
|
i.doImport()
|
||||||
assert 7 == i.total
|
assert 7 == i.total
|
||||||
deck.s.close()
|
deck.s.close()
|
||||||
|
|
||||||
|
def test_updating():
|
||||||
|
# get the standard csv deck first
|
||||||
|
deck = DeckStorage.Deck()
|
||||||
|
deck.addModel(BasicModel())
|
||||||
|
file = unicode(os.path.join(testDir, "importing/text-2fields.txt"))
|
||||||
|
i = csvfile.TextImporter(deck, file)
|
||||||
|
i.doImport()
|
||||||
|
# now update
|
||||||
|
file = unicode(os.path.join(testDir, "importing/text-update.txt"))
|
||||||
|
i = csvfile.TextImporter(deck, file)
|
||||||
|
# first field
|
||||||
|
i.updateKey = (0, deck.currentModel.fieldModels[0].id)
|
||||||
|
i.multipleCardsAllowed = False
|
||||||
|
i.doImport()
|
||||||
|
ans = deck.s.scalar(
|
||||||
|
u"select answer from cards where question like '%食べる%'")
|
||||||
|
assert "to ate" in ans
|
||||||
|
# try again with tags
|
||||||
|
i.updateKey = (0, deck.currentModel.fieldModels[0].id)
|
||||||
|
i.mapping[1] = 0
|
||||||
|
i.doImport()
|
||||||
|
deck.s.close()
|
||||||
|
|
Loading…
Reference in a new issue