Skip to content

Commit

Permalink
Allow non-primary key IDs
Browse files Browse the repository at this point in the history
  • Loading branch information
mrevutskyi committed Jan 19, 2024
1 parent 4bf0082 commit 87c55ae
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 6 deletions.
3 changes: 2 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ Changelog
Changes in Flask-Restless-NG
============================

Unreleased
Version 3.2.0
-------------
- Dropped savalidation support
- Added a parameter to serializer to skip primary key check (not recommended)


Version 3.1.0 (2023-10-14):
Expand Down
2 changes: 1 addition & 1 deletion flask_restless/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"""
#: The current version of this extension.
__version__ = '3.1.0'
__version__ = '3.2.0'


# The following names are available as part of the public API for Flask-Restless-NG.
Expand Down
4 changes: 3 additions & 1 deletion flask_restless/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ def create_api_blueprint(
allow_to_many_replacement: bool = False,
allow_delete_from_to_many_relationships: bool = False,
allow_client_generated_ids: bool = False,
allow_non_primary_key_id: bool = False,
):
"""Creates and returns a ReSTful API interface as a blueprint, but does
not register it on any :class:`flask.Flask` application.
Expand Down Expand Up @@ -547,7 +548,8 @@ def create_api_blueprint(
# provided.
if serializer is None:
serializer = DefaultSerializer(model, collection_name, self, primary_key=primary_key,
only=only, exclude=exclude, additional_attributes=additional_attributes)
only=only, exclude=exclude, additional_attributes=additional_attributes,
allow_non_primary_key_id=allow_non_primary_key_id)

session = self.session
if deserializer is None:
Expand Down
10 changes: 8 additions & 2 deletions flask_restless/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,13 @@ def deserialize(self, document):
class DefaultSerializer(Serializer):
"""Default Serializer implementation."""

def __init__(self, model, type_name, api_manager, primary_key=None, only=None, exclude=None, additional_attributes=None, **kwargs):
def __init__(self, model, type_name, api_manager,
primary_key=None,
only=None,
exclude=None,
additional_attributes=None,
allow_non_primary_key_id=False,
**kwargs):
super().__init__(**kwargs)
if only is not None and exclude is not None:
raise ValueError('Cannot specify both `only` and `exclude` keyword arguments simultaneously')
Expand All @@ -343,7 +349,7 @@ def __init__(self, model, type_name, api_manager, primary_key=None, only=None, e
self._type = type_name
pk_names = primary_key_names(model)
if primary_key:
if primary_key not in pk_names:
if not allow_non_primary_key_id and primary_key not in pk_names:
raise ValueError(f'Column `{primary_key}` is not a primary key')
else:
raise ValueError('`primary_key` is required')
Expand Down
1 change: 1 addition & 0 deletions flask_restless/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ def extract_error_messages(exception):
if hasattr(exception, 'errors'):
return exception.errors


def error(id_=None, links=None, status=None, code=None, title=None,
detail=None, source=None, meta=None):
"""Returns a dictionary representation of an error as described in the
Expand Down
15 changes: 15 additions & 0 deletions tests/test_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import enum
import json

import pytest
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import Date
Expand Down Expand Up @@ -86,3 +87,17 @@ def test_serialize_attributes():
'interval_field': 60.0,
'enum_field': 'two'
}


def test_raises_value_error_for_empty_pk():
with pytest.raises(ValueError):
DefaultSerializer(Model, 'test-model', None)


def test_raises_value_error_when_provided_pk_is_not_pk():
with pytest.raises(ValueError):
DefaultSerializer(Model, 'test-model', None, primary_key='date_field')


def test_skip_pk_test():
assert DefaultSerializer(Model, 'test-model', None, primary_key='date_field', allow_non_primary_key_id=True)
1 change: 0 additions & 1 deletion tests/test_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
client.
"""
import unittest

from sqlalchemy import Column
from sqlalchemy import ForeignKey
Expand Down

0 comments on commit 87c55ae

Please sign in to comment.