What is the proper way to change the note type of a card from within an add-on? Is there an example for that?
See how it’s done by Anki here:
Thanks! It pushed me in the right direction!
I still can’t figure it out. This is my current code:
change_notetype_info = mw.col.models.change_notetype_info(
old_notetype_id=old_notetype_id,
new_notetype_id=new_notetype_id,
)
note_ids: Sequence[NoteId] = []
# Fill the list ...
req = ChangeNotetypeRequest()
req.ParseFromString(change_notetype_info.SerializeToString())
req.note_ids.extend(note_ids)
mw.col.models.change_notetype_of_notes(req)
But the last line triggers an error: anki.errors.BackendError: ProtoError { info: “failed to decode Protobuf message: ChangeNotetypeRequest.old_notetype_id: invalid wire type: LengthDelimited (expected Varint)” }
Any ideas?
By the way, the docstring for change_notetype_request()
does not mention that you have to serialize the argument to ParseFromString()
.
Looks like this is my bad. The note_ids
I pass look suspicious. I’ll come back, when I’ve found the reason.
The note_ids
are okay. The “suspicious” ones were were added by the ParseFromString()
call. I have checked both notetype ids. They both belong to existing models/note types. I have checked every note in note_ids
. They exist and are using the model with old_notetype_id
.
Why does this fail then?
It appears that the example given in the docstring no longer works after some changes to the protobuf structure. This example works for me:
def new_names_to_indices(new_names: list[str], old_names: list[str]) -> list[int]:
indices = []
for name in new_names:
try:
indices.append(old_names.index(name))
except ValueError:
indices.append(-1)
return indices
basic = mw.col.models.by_name("Basic")
basic_reversed = mw.col.models.by_name("Basic (and reversed card)")
info = mw.col.models.change_notetype_info(
old_notetype_id=basic["id"], new_notetype_id=basic_reversed["id"]
)
req = ChangeNotetypeRequest()
req.new_fields.extend(
new_names_to_indices(list(info.new_field_names), list(info.old_field_names))
)
req.new_templates.extend(
new_names_to_indices(
list(info.new_template_names), list(info.old_template_names)
)
)
req.old_notetype_id = basic["id"]
req.new_notetype_id = basic_reversed["id"]
req.current_schema = mw.col.db.scalar("select scm from col")
req.old_notetype_name = basic["name"]
req.is_cloze = basic["type"] == 1 or basic_reversed["type"] == 1
req.note_ids.extend([1720992551032])
mw.col.models.change_notetype_of_notes(req)
I’ll look into sending a PR to fix the docs and maybe add a helper function to do the conversion.
Thank you! That is very much appreciated.
Was that maybe this commit? Merging Notetypes on Import (#2612) · ankitects/anki@14de845 · GitHub
I guess the minimum required version of my add-on will be the release containing the change.
My guess is that it’s this commit: Change Notetype UI Rework (#1499) · ankitects/anki@6809208 · GitHub
It adds an additional field to ChangeNotetypeInfo.
My example above can be simplified a lot:
basic = mw.col.models.by_name("Basic")
basic_reversed = mw.col.models.by_name("Basic (and reversed card)")
info = mw.col.models.change_notetype_info(
old_notetype_id=basic["id"], new_notetype_id=basic_reversed["id"]
)
req = info.input
req.note_ids.extend([1720992551032])
mw.col.models.change_notetype_of_notes(req)
I can confirm that the complicated version works like a charm. But I will try the simplification, too, and then mark one of your replies as the solution. Thanks a lot again!
The simplified version is also slightly better than the long version because it also fills the “Sort Field”.
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.