Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to remove attachments #132

Merged
merged 11 commits into from
Aug 10, 2018
Merged

Conversation

goldpbear
Copy link
Contributor

@goldpbear goldpbear commented Aug 5, 2018

Closes: #59
Addresses: #126

In conjunction with mapseed/platform#983

Create a new view, AttachmentInstanceView, to facilitate PATCH requests to individual attachments. Add a visible parameter to AttachmentModels to allow "deletion" of attachments from the client editor.

TODO:

  • Add tests

@@ -517,7 +517,7 @@ def test_GET_from_cache(self):
# - SELECT * FROM sa_api_attachment AS a
# WHERE a.thing_id IN (<self.place.id>);
#
with self.assertNumQueries(11):
with self.assertNumQueries(14):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a good understanding of why these tests (this one and the next two) need an adjustment. I didn't want to delay the review any longer, but I'll look into the details of the number of queries executed here and hopefully get a better understanding.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is fine to punt this issue for later, but we should file an issue and mark it as "technical-debt", and reference the issue as a TODO a comment on the three diffs below.

FYI here are the three queries that were added:

SELECT * FROM sa_api_place AS p
JOIN sa_api_submittedthing as t ON (p.submittedthing_ptr_id = t.id)
WHERE p.submittedthing_ptr_id = <self.place.id>;

SELECT * from sa_api_dataset AS d
WHERE d.id = <self.dataset.id>;

SELECT * FROM auth_user as u1
WHERE u1.id = <self.owner.id>;

These queries are being made because we added a new field to our Attachment serializer:

url = AttachmentIdentityField()

where we are querying for the place_id, dataset_slug, and owner_username in AttachmentIdentityField. There should be a way to optimize this and avoid the extra queries, but I think we should punt this and address the issue at a later time, perhaps after the 1.8 upgrade.

def partial_update(self, *args, **kwargs):
attachment_id = self.kwargs['attachment_id']
obj = self.get_object_or_404(attachment_id)
self.model.clear_instance_cache(obj)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found that we have to explicitly clear the cache on a partial_update; otherwise, deleted attachments will reappear on a page reload.

I'm not sure if this is the best way to handle cache clearing, though. Alternatively, we could overwrite partial_update (and update for that matter) in the CacheClearingModel, from which several other models inherit. I have a feeling this might address #126 too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this solution makes sense for now. Note that you don't have to pass obj to the clear_instance_cache method:

def clear_instance_cache(self):

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the following error if I don't pass obj to clear_instance_cache:

TypeError: unbound method clear_instance_cache() must be called with Attachment instance as first argument

Copy link
Contributor

@jalMogo jalMogo Aug 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's right. I think you want to do this:

obj.clear_instance_cache()

It's essentially doing the same thing, but I would prefer this approach because it's more OO versus calling the class's method and passing in the instance.

And maybe instead of obj we can call it something like attachment.

@goldpbear goldpbear self-assigned this Aug 6, 2018
Copy link
Contributor

@jalMogo jalMogo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

I have a few minor suggestions to clean up some of the code. Overall, I think this looks good!

I think we should add a test case for a PATCH on our attachment model, but I'm fine with making an issue for it and addressing it later.

def partial_update(self, *args, **kwargs):
attachment_id = self.kwargs['attachment_id']
obj = self.get_object_or_404(attachment_id)
self.model.clear_instance_cache(obj)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this solution makes sense for now. Note that you don't have to pass obj to the clear_instance_cache method:

def clear_instance_cache(self):


class AttachmentSerializer (EmptyModelSerializer, serializers.ModelSerializer):

class AttachmentListSerializer (AttachmentSerializerMixin):
file = AttachmentFileField()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this file field is not needed because our Attachment model already has a file field, which is being returned in the 'file': obj.file.storage.url(obj.file.name), field of our AttachmentSerializerMixin

file = AttachmentFileField()
url = AttachmentIdentityField()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want a url field for our attachment instance representations, as well as our attachment list representations (eg: http://localhost:8001/api/v2/smartercleanup/datasets/demo/places/3871/attachments/425)

To enable that, I think we should move this field into our AttachmentSerializerMixin.

}
fields = self.get_fields()

if 'url' in fields:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we move the url = AttachmentIdentityField() field definition to this class, then we can remove this check

@@ -794,7 +811,7 @@ def get_detailed_submission_sets(self, place):
return details

def attachments_to_native(self, obj):
return [AttachmentSerializer(a).data for a in obj.attachments.all()]
return [AttachmentListSerializer(a, context=self.context).data for a in obj.attachments.all()]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this context kwarg? All of the tests pass, and the app seems to behave fine without it.

@@ -517,7 +517,7 @@ def test_GET_from_cache(self):
# - SELECT * FROM sa_api_attachment AS a
# WHERE a.thing_id IN (<self.place.id>);
#
with self.assertNumQueries(11):
with self.assertNumQueries(14):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is fine to punt this issue for later, but we should file an issue and mark it as "technical-debt", and reference the issue as a TODO a comment on the three diffs below.

FYI here are the three queries that were added:

SELECT * FROM sa_api_place AS p
JOIN sa_api_submittedthing as t ON (p.submittedthing_ptr_id = t.id)
WHERE p.submittedthing_ptr_id = <self.place.id>;

SELECT * from sa_api_dataset AS d
WHERE d.id = <self.dataset.id>;

SELECT * FROM auth_user as u1
WHERE u1.id = <self.owner.id>;

These queries are being made because we added a new field to our Attachment serializer:

url = AttachmentIdentityField()

where we are querying for the place_id, dataset_slug, and owner_username in AttachmentIdentityField. There should be a way to optimize this and avoid the extra queries, but I think we should punt this and address the issue at a later time, perhaps after the 1.8 upgrade.

@goldpbear goldpbear merged commit 0c18080 into master Aug 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants