docs: def _update_related(self, obj, related, subfield_dict):
          """
          update DB objects related to a base object
              obj:            a base object to create related
              related:        dict mapping field names to lists of related objects
              subfield_list:  where to get the next layer of subfields
          """
          # keep track of whether or not anything was updated
          updated = False
  
          # for each related field - check if there are differences
          for field, items in related.items():
              # skip subitem check if it's locked anyway
              if field in obj.locked_fields:
                  continue
  
              # get items from database
              dbitems = list(getattr(obj, field).all())
              dbitems_count = len(dbitems)
  
              # default to doing nothing
              do_delete = do_update = False
  
              if items and dbitems_count:         # we have items, so does db, check for conflict
                  do_delete = do_update = items_differ(items, dbitems, subfield_dict[field][2])
              elif items and not dbitems_count:   # we have items, db doesn't, just update
                  do_update = True
              elif not items and dbitems_count:   # db has items, we don't, just delete
                  do_delete = True
              # otherwise: no items or dbitems, so nothing is done
  
              # don't delete if field is in merge_related
              if field in self.merge_related:
                  new_items = []
                  # build a list of keyfields to existing database objects
                  keylist = self.merge_related[field]
                  keyed_dbitems = {tuple(getattr(item, k) for k in keylist):
                                   item for item in dbitems}
  
                  # go through 'new' items
                  #   if item with the same keyfields exists:
                  #       update the database item w/ the new item's properties
                  #   else:
                  #       add it to new_items
                  for item in items:
                      key = tuple(item.get(k) for k in keylist)
                      dbitem = keyed_dbitems.get(key)
                      if not dbitem:
                          new_items.append(item)
                      else:
                          # update dbitem
                          for fname, val in item.items():
                              setattr(dbitem, fname, val)
                          dbitem.save()
  
                  # import anything that made it to new_items in the usual fashion
                  self._create_related(obj, {field: new_items}, subfield_dict)
              else:
                  # default logic is to just wipe and recreate subobjects
                  if do_delete:
                      updated = True
                      getattr(obj, field).all().delete()
                  if do_update:
                      updated = True
                      self._create_related(obj, {field: items}, subfield_dict)
  
          return updated