Opened 5 years ago

Closed 5 years ago

#5421 closed defect (cant-reproduce)

Server error when trying to access atom feed with graveyard media

Reported by: ayleph Owned by:
Priority: blocker Milestone: 0.9.0
Component: programming Keywords: graveyard, feed
Cc: tsyesika Parent Tickets:

Description

Attempting to access a collection's atom feed causes an error when that feed contains graveyard items.

Error - <type 'exceptions.AttributeError'>: 'Graveyard' object has no attribute 'title'
URL: https://goblinrefuge.com/mediagoblin/u/topo/collection/free-culture/atom/
File '/path/to/mediagoblin/lib/python2.7/site-packages/Paste-1.7.5.1-py2.7.egg/paste/exceptions/errormiddleware.py', line 144 in __call__
  app_iter = self.application(environ, sr_checker)
File '/path/to/mediagoblin/mediagoblin/app.py', line 342 in __call__
  return self.call_backend(environ, start_response)
File '/path/to/mediagoblin/lib/python2.7/site-packages/Werkzeug-0.10.1-py2.7.egg/werkzeug/wsgi.py', line 591 in __call__
  return self.app(environ, start_response)
File '/path/to/mediagoblin/mediagoblin/app.py', line 276 in call_backend
  return self._finish_call_backend(request, environ, start_response)
File '/path/to/mediagoblin/mediagoblin/app.py', line 318 in _finish_call_backend
  response = controller(request)
File '/path/to/mediagoblin/mediagoblin/user_pages/views.py', line 621 in collection_atom_feed
  obj.get('title'),
File '/path/to/mediagoblin/mediagoblin/db/base.py', line 72 in get
  return getattr(self, key)
AttributeError: 'Graveyard' object has no attribute 'title'

Subtickets

Change History (5)

comment:1 Changed 5 years ago by ayleph

It looks like this issue occurs because soft_delete doesn't remove CollectionItems. From mediagoblin/db/models.py, we see that delete has a note about deleting CollectionItems with cascade, but that doesn't happen with soft_delete.

    def soft_delete(self, *args, **kwargs):
        # Find all of the media comments for this and delete them
        for comment in self.get_comments():
            comment.delete(*args, **kwargs)

        super(MediaEntry, self).soft_delete(*args, **kwargs)

    def delete(self, del_orphan_tags=True, **kwargs):
        """Delete MediaEntry and all related files/attachments/comments

        This will *not* automatically delete unused collections, which
        can remain empty...

        :param del_orphan_tags: True/false if we delete unused Tags too
        :param commit: True/False if this should end the db transaction"""
        # User's CollectionItems are automatically deleted via "cascade".
        # Comments on this Media are deleted by cascade, hopefully.

        # Delete all related files/attachments
        try: 
            delete_media_files(self)

I think this needs two courses of action.

  1. Update soft_delete to remove CollectionItems.
  2. Add a migration to remove any CollectionItems which reference graveyard media.

comment:2 Changed 5 years ago by ayleph

Cc: tsyesika added

comment:3 Changed 5 years ago by ayleph

I'm trying to replicate this, but I'm having trouble. There may be more to it than simply deleting media attached to a collection. I'll continue to dig.

comment:4 Changed 5 years ago by Jessica Tallon

Owner: set to Jessica Tallon
Status: newin_progress

I'll try to reproduce and see if I can.

comment:5 Changed 5 years ago by Jessica Tallon

Owner: Jessica Tallon deleted
Resolution: worksforme
Status: in_progressclosed

Okay, I'm not able to reproduce this, what I've tried is:

  1. Create a collection
  2. Upload media to said collection
  3. Verify the media is in the atom feet.
  4. Delete the media in the collection
  5. Check the atom feed is empty.

This works as expected. I then decided I'd dig in and find out how CollectionItem were deleted (I had forgotten what I had done). The code to delete them is

    def delete(self, commit=True, deletion=None):
        """ Delete the object either using soft or hard deletion """
        # Get the setting in the model args if none has been specified.
        if deletion is None:
            deletion = self.deletion_mode

        # If the item is in any collection then it should be removed, this will
        # cause issues if it isn't. See #5382.
        # Import here to prevent cyclic imports.
        from mediagoblin.db.models import CollectionItem, GenericModelReference, \
                                          Report, Notification
        
        # Some of the models don't have an "id" field which means they can't be
        # used with GMR, these models won't be in collections because they
        # can't be. We can skip all of this.
        if hasattr(self, "id"):
            # First find the GenericModelReference for this object
            gmr = GenericModelReference.query.filter_by(
                obj_pk=self.id,
                model_type=self.__tablename__
            ).first()

            # If there is no gmr then we've got lucky, a GMR is a requirement of
            # being in a collection.
            if gmr is not None:
                # Delete collections found
                items = CollectionItem.query.filter_by(
                    object_id=gmr.id
                )
                items.delete()

This is located on the GMGTableBase so it's run when the delete method is run on the media entry. This queries for all the collection items which point to the media and then delete them. I'm going to close this as cannot reproduce but I'm curious what issue you're having. If you can give me more information on how to reproduce this please do re-open it.

Note: See TracTickets for help on using tickets.