Exported "Basic" cards create duplicate card types when imported by other users

If Alice exports a deck containing “Basic” cards from her Anki app and sends the .apkg to Bob, when Bob imports the .apkg file it will create a new card type called something like “Basic-10e7e”.

It would be better if instead, the imported cards were treated as “Basic” cards in Bob’s collection as well.

I’d like to send a PR to Anki to fix this. I think the easiest solution would be to hard-code a model ID for the “Basic” card type instead of generating one based on the timestamp when Anki is installed. Another solution would be to detect when basic cards are imported and add some special logic for converting them into the existing card type.

@dae would you accept the first solution (hardcoded model ID) or is there some issue with this approach? Anything to keep in mind (e.g. backwards compatibility) when making this change?

This also applies to “Basic (and reversed card)”, etc.

It would be better to compare if both templates are equal (before creating a new template as Basic-10e7e).

Then, this solution would work, for all templates not just the Basic one.

Note types not only define the structure of the note, but also the scope in which duplicates are checked, so I’m not sure it makes sense to automatically merge them. The importing code also makes assumptions based on the current behaviour, and any changes in this area will likely break things.

@dae I’m not sure I understand this bit of what you said:

Note types not only define the structure of the note, but also the scope in which duplicates are checked

I’m guessing you’re talking about sfld collisions because guid collisions shouldn’t happen. For Basic cards, sfld is Front. I think it’s OK to flag duplicates if Bob imports Alice’s else’s deck and one of the cards has the exact same prompt as one of Bob’s existing cards—it’s almost certainly redundant with the existing card.

The importing code also makes assumptions based on the current behaviour, and any changes in this area will likely break things.

I agree that the importing code is complex and so changes can be risky. But I read through pylib/anki/importing/anki2.py and I think it’s safe to hardcode the model ID for Basic cards. Here’s what I think would happen in anki2.py if we hardcoded the Basic model ID as x and Bob tries to import Alice’s Basic note:

Assuming the scmhash is the same between Alice and Bob and the GUID is not present in Bob’s collection:

  1. _mid would return x (i.e. the same thing we passed it).
  2. _uniquifyNote would therefore return True.
  3. And so this if statement would evaluate to True and the note would be imported as a “Basic” note.

What would happen if Bob has a newer Anki version with a different scmhash (e.g. with Front renamed to Question)? Also assuming the GUID is not present.

  1. _mid would return x + 1 (assuming that wasn’t taken).
  2. _uniquifyNote would return True because the GUID is not present.
  3. And so the note would be imported as a “Basic-123ab” note.

So I think things will be fine if we hardcode the Basic model ID. Things would also work out when an older version (non-constant model ID) tries to import a newer deck (model ID = x) or vice versa, it will import as “Basic-123ab”. If the GUID is present the note will not be imported which is also what we want.

The benefit is that it gets rid of the visual clutter of the “Basic-123ab” note types, which is admittedly not a big deal but is nice if you are trying to share decks that use these basic note types.

The change to hardcode the IDs would happen somewhere around add_stock_notetypes. It would only affect new Anki installs; existing users would already have stock note types with timestamp-based model IDs and I wouldn’t add any code to migrate them.

I’m afraid I think it’s not that simple - there are other issues to consider such as the fact that the styling from one shared deck would overwrite the styling of another if they happened to share the same fields. There may be scope to reduce note type clutter in the future, but I think it’s probably not going to be by sharing the same ID at creation time.

Makes sense, thanks for your input/help! I will probably not work on this given that it seems non-trivial.