diff --git a/bookwyrm/activitypub/base_activity.py b/bookwyrm/activitypub/base_activity.py index b9facf2f..7ef0920f 100644 --- a/bookwyrm/activitypub/base_activity.py +++ b/bookwyrm/activitypub/base_activity.py @@ -111,15 +111,10 @@ class ActivityObject: continue model_field = getattr(model, model_field_name) - try: - # this is for one to many - related_model = model_field.field.model - related_field_name = model_field.field.name - except AttributeError: - # it's a one to one or foreign key - related_model = model_field.related.related_model - related_field_name = model_field.related.related_name - values = [values] + # creating a Work, model_field is 'editions' + # creating a User, model field is 'key_pair' + related_model = model_field.field.model + related_field_name = model_field.field.name for item in values: set_related_field.delay( @@ -142,8 +137,8 @@ class ActivityObject: @app.task @transaction.atomic def set_related_field( - model_name, origin_model_name, - related_field_name, related_remote_id, data): + model_name, origin_model_name, related_field_name, + related_remote_id, data): ''' load reverse related fields (editions, attachments) without blocking ''' model = apps.get_model('bookwyrm.%s' % model_name, require_ready=True) origin_model = apps.get_model( @@ -153,23 +148,36 @@ def set_related_field( with transaction.atomic(): if isinstance(data, str): - item = resolve_remote_id(model, data, save=False) - else: - # look for a match based on all the available data - item = model.find_existing(data) - if not item: - # create a new model instance - item = model.activity_serializer(**data) - item = item.to_model(model, save=False) + existing = model.find_existing_by_remote_id(data) + if existing: + data = existing.to_activity() + else: + data = get_data(data) + activity = model.activity_serializer(**data) + # this must exist because it's the object that triggered this function instance = origin_model.find_existing_by_remote_id(related_remote_id) if not instance: raise ValueError( 'Invalid related remote id: %s' % related_remote_id) - # edition.parent_work = instance, for example - setattr(item, related_field_name, instance) - item.save() + # set the origin's remote id on the activity so it will be there when + # the model instance is created + # edition.parentWork = instance, for example + model_field = getattr(model, related_field_name) + if hasattr(model_field, 'activitypub_field'): + setattr( + activity, + getattr(model_field, 'activitypub_field'), + instance.remote_id + ) + item = activity.to_model(model) + + # if the related field isn't serialized (attachments on Status), then + # we have to set it post-creation + if not hasattr(model_field, 'activitypub_field'): + setattr(item, related_field_name, instance) + item.save() def resolve_remote_id(model, remote_id, refresh=False, save=True): diff --git a/bookwyrm/models/book.py b/bookwyrm/models/book.py index 7e45eacd..1e1d8d20 100644 --- a/bookwyrm/models/book.py +++ b/bookwyrm/models/book.py @@ -59,9 +59,7 @@ class Book(BookDataModel): subject_places = fields.ArrayField( models.CharField(max_length=255), blank=True, null=True, default=list ) - # TODO: include an annotation about the type of authorship (ie, translator) authors = fields.ManyToManyField('Author') - # preformatted authorship string for search and easier display cover = fields.ImageField( upload_to='covers/', blank=True, null=True, alt_field='alt_text') first_published_date = fields.DateTimeField(blank=True, null=True)