As a user, I can associate content with repositories using the content API
Now that we've got a plugin with "real" content types (pending completion of #2454), we're able to do some tinkering around in the API to see what works and what doesn't.
So far, the only thing I've found that doesn't work via the API is attempting to associate a content unit with repositories when creating content units. The "repositories" field is current exposed and writable, but attempting to create a unit with references to repositories results in an error like this:
AttributeError at /api/v3/content/file/ Cannot set values on a ManyToManyField which specifies an intermediary model. Use pulp.RepositoryContent's Manager instead.
This is true, the addition of the "updated" timestamp field to the explicitly defined RepositoryContent model means that we lose the ability to use the 'add' and 'remove' method on the related manager:
It would be pretty nice to be able to handle this association right on the content unit, and not have to expose RepositoryContent in the API directly, since that's an unfriendly workflow (create repo, create content, associate content with repo vs. create repo, create content associate with repo, and similar usability benefits for adding a repo to a content unit's list of repos).
#1 Updated by semyers about 3 years ago
There are a few options for fixing this, which I'll outline.
- Stop using the RepositoryContent through model, allowing Django to automatically create it. Associate extra data on the repo/content associate through a separate model whose values are able to be determined any time a repo/content associate is made, and saved to this separate model's table via signals.
- Modify the 'add' and 'remove' remove methods directly on the ManyRelatedManager/ReverseManyRelatedManager to disable the check for our use of a through model with extra data, and ensure the correct values for any extra data are set on the model prior to saving.
- Modify the Content serializer's save operations to correctly create/delete RepositoryContent records, rendering the implementation detail of extra data that we store on this relationship invisible to API users.
- Something I've missed here.
Of these, I think Option 2 looks like it's the best, but might not be. Implementing it would mean that both the API and Django's own model API available to application developers will "just work", and we can all but ignore the existence of the extra data (currently just the "updated" timestamp") stored on the RepositoryContent relationship, except when we explicitly need it during publishing. However, as far as I can tell, Django 1.8 does not make it easy to customize the behaviors of its ManyRelatedManagers, so modifying the behaviors of .add and .remove might be prohibitively risky and unmaintainable.
Option 1 is very simple, but comes at the potential cost of an additional join done when looking up the extra data, as well as the very real cost of keeping the "extra data" table up to date with Repo/Content associations, including the cost of getting it wrong and ending up with inconsistent data.
Option 3 is less friendly to developers, since you no longer add units to a repository using the django-provided interface. It should be very straightforward, and assuming we provide our own interface for managing the addition/removal of content from a repository that correctly sets any related timestamps, it should also be the easiest and least risky one to implement.
Throughout this entire storywriting process, I've referred to the timestamp on the RepositoryContent model as "updated", but actually it's "created". Please pardon the confusion there.
Please register to edit this issue