pyeve / eve-sqlalchemy

SQLAlchemy data layer for Eve-powered RESTful APIs
http://eve-sqlalchemy.readthedocs.io
Other
232 stars 70 forks source link

Feature Request : Support for SOFT_DELETE #109

Open mandarvaze opened 8 years ago

mandarvaze commented 8 years ago

When I enable SOFT_DELETE in the settings.py, I get _deleted is an invalid argument error.

I can't add _deleted field myself either, because then I get the following error:

eve.exceptions.SchemaException: field(s) "_deleted" not allowed in "xyz" schema (they will be handled automatically).

dkellner commented 7 years ago

I just discovered that we miss two test cases in tests/delete.py: TestSoftDelete and TestResourceSpecificSoftDelete. So the first step to tackle this issue would be to add those (and inherit Eve's test cases) and see what needs fixing.

huiyiqun commented 7 years ago

I also require this feature. I tried to add config.DELETED to this tuple, but it failed with the issue that the eve module has no DELETED attribute.

I've seen the source of eve.utils.config, which tries to read config from current_app.config then fallbacks to eve. However, the decorator registerSchema is always executed out of the context of eve app(or flask app) and always read config from the eve module.

So I have multiple questions:

  1. What will happen if I alter the value of config.ETAG, config.LAST_UPDATED or config.DATE_CREATED in settings?
  2. Why are there duplicated default values in eve/__init__.py and eve/default_settings.py while the number of fields are not identical? How about import these values from eve/default_settings.py directly? So we have DELETED in eve module.

Do you have some suggestions?

dkellner commented 7 years ago

@huiyiqun While I cannot really answer your second question (it would be better to ask that at pyeve/eve directly), I am currently working on a fix for your first. At the moment we have several problems due to the use of registerSchema as a decorator, which is usually evaluated before the actual app creation. The plan to tackle all of them at once is to stop using a decorator, but have a convenient way to convert your SQLAlchemy models to Eve resource definitions in your settings.py. And explicitly provide some values that are needed in that process, e.g. the name of the ETAG field.

ktal90 commented 5 years ago

For anyone that might find this useful: I managed a janky SOFT_DELETE implementation by turning on the SOFT_DELETE configuration, adding the _deleted column to my models, and then adding a on_pre_GET hook on the application. Under the hood, the HTTP DELETE function is handled by Eve/Eve-SQLAlchemy, as expected. Note that there there is an inconsistency where retrieving embedded resources do not filter out the _deleted resources.

EDIT: Some code

# Register filter hook
def register_filters(app):
    app.on_pre_GET += pre_GET_callback

def pre_GET_callback(resource, request, lookup):
    if '_deleted' in request.args.get('where', {}):
        lookup['_deleted'] = True
    else:
        lookup['_deleted'] = False

# Models
class CommonColumns(Base):
    __abstract__ = True
    _created = Column(DateTime, default=func.now())
    _updated = Column(DateTime, default=func.now(), onupdate=func.now())
    _deleted = Column(Boolean,
                      server_default=expression.false(),
                      nullable=False)
    _etag = Column(String(40))
dkellner commented 5 years ago

@ktal90 Would you be interested in working on a proper implementation? As mentioned above, the first step would be to enable those missing tests from Eve.