-
Notifications
You must be signed in to change notification settings - Fork 94
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
Fail if Related can't find an existing record. #212
Comments
I for one think this is definitely a needed feature. |
FWIW, I just made a Validator function: def not_transient_model_object(value):
"""
Validate if value is a model instance existing in the DB.
i.e. Throw an error if model does not exist in DB
"""
if isinstance(value, (list, tuple)):
invalid_vals = sum(val not in db.session for val in value)
if invalid_vals > 0:
raise ValidationError('{} of the given {} values do not exist'.format(invalid_vals, len(value)))
else:
if value not in db.session:
raise ValidationError('Given value does not exist') And I use it in my metaclass that I extended (something like this): class BaseModelSchemaMeta(type(ModelSchema)):
@staticmethod
def _add_related_field_validator(field_obj):
# If `allow_creation` is not given as True - don't allow creation of an object in a relation
if not field_obj.metadata.get('allow_creation', False):
field_obj.validators.append(not_transient_model_object)
def get_declared_fields(cls, klass, cls_fields, inherited_fields, dict_cls):
declared_fields = super(type(ModelSchema), cls).get_declared_fields(
klass, cls_fields, inherited_fields, dict_cls)
for fname, fvalue in declared_fields.items():
if isinstance(fvalue, Related):
cls._add_related_field_validator(fvalue)
elif isinstance(fvalue, fields.List) and isinstance(fvalue.container, Related):
cls._add_related_field_validator(fvalue.container) This way I can write the field with the kwarg It would be nice to have support for this inside the library though |
@AbdealiJK could you give an example in how to implement your code? I also want creating related objects in the database disabled by default. I'm running into an error and cant figure out where the issue is. It's happening when instantiating the schema on the last line. from marshmallow_sqlalchemy.fields import Related, RelatedList
from marshmallow_sqlalchemy.compat import with_metaclass
from rdns_app.extensions import ma, db
from rdns_app.models import GeoLocationGroup
def not_transient_model_object(value):
"""Validate if value is a model instance existing in the DB.
i.e. Throw an error if model does not exist in DB
"""
if isinstance(value, (list, tuple)):
invalid_vals = sum(val not in db.session for val in value)
if invalid_vals > 0:
raise ValidationError('{} of the given {} values do not exist'.format(invalid_vals, len(value)))
else:
if value not in db.session:
raise ValidationError('Given value does not exist')
class BaseModelSchemaMeta(type(ma.ModelSchema)):
@staticmethod
def _add_related_field_validator(field_obj):
# If `allow_creation` is not given as True - don't allow creation of an object in a relation
if not field_obj.metadata.get('allow_creation', False):
field_obj.validators.append(not_transient_model_object)
@classmethod
def get_declared_fields(cls, klass, cls_fields, inherited_fields, dict_cls):
declared_fields = super(type(ma.ModelSchema), cls).get_declared_fields(
klass, cls_fields, inherited_fields, dict_cls)
for fname, fvalue in declared_fields.items():
if isinstance(fvalue, Related):
cls._add_related_field_validator(fvalue)
elif isinstance(fvalue, fields.List) and isinstance(fvalue.container, Related):
cls._add_related_field_validator(fvalue.container)
class GeoLocationGroupSchema(with_metaclass(BaseModelSchemaMeta, ma.ModelSchema)):
class Meta:
model = GeoLocationGroup
fields = ('name', 'geolocations')
sqla_session = db.session
name = ma.String(required=True)
geolocations = RelatedList(Related(attribute="geo_locations", column='name'),
attribute='geo_locations', allow_creation=False)
geo_location_group_schema = GeoLocationGroupSchema() Traceback:
For some reason self.declared_fields is None. Did I subclass things incorrectly? |
I had written that code for a very specific marshmallow version - one of the 3.0 beta series 3.0b12 I think? |
I'm using 3.0.0rc6 |
Sorry if that was somewhat of a hijacking of the thread. Back on subject, I still think this would be a valuable addition to the library. |
Can anyone think of a case you wouldn't want it to fail? I feel like should be a default behavior. |
i'd be open to adding something like a PRs welcome! |
I'd like to be able to tell the Related field that it should fail if it can't find an existing parent record. This is for when a user doesn't have the ability to add parent records and I want to let them know that the record they are specifying does not exist yet.
Something like this in Related's deserialize method?
At the moment, I have to accomplish this via a @validates() decorator in the schema that performs this check, like so:
Thoughts?
The text was updated successfully, but these errors were encountered: