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

Filter condition on nested attribute #1183

Open
ck-on-github opened this issue May 15, 2023 · 3 comments
Open

Filter condition on nested attribute #1183

ck-on-github opened this issue May 15, 2023 · 3 comments

Comments

@ck-on-github
Copy link

Hello,

In my pynamodb model, I have an attribute, which can be an instance of one of the sub-classes of a polymorphic map attribute like:

class ParentClass(MapAttribute):
    cls = DiscriminatorAttribute()

class ChildClass1(ParentClass, discriminator = cls.__name__):
    filter_attr = UnicodeAttribute()

class ChildClass2(ParentClass, discriminator = cls.__name__):
    other_attr = UnicodeAttribute()

class MyModel(Model):
   ...
   attr = ParentClass() 

If I define a filter condition on MyModel.attr.filter_attr like MyModel.attr.filter_attr == value, I get the run time error

    def __getattr__(self, attr: str) -> _VT:
        # This should only be called for "raw" (i.e. non-subclassed) MapAttribute instances.
        # MapAttribute subclasses should access attributes via the Attribute descriptors.
        if self.is_raw() and self._is_attribute_container():
            try:
                return self.attribute_values[attr]
            except KeyError:
                pass
>       raise AttributeError("'{}' has no attribute '{}'".format(self.__class__.__name__, attr))
E       AttributeError: 'ParentClass' has no attribute 'filter_attr'

which makes sense because attr is of type ParentClass, which only has cls attribute.

My question is, is there a way to define a filter on a nested attribute in a pynamodb model, where the nested attribute is an instance of a child class of a polymorphic MapAttribute parent class?

@ikonst
Copy link
Contributor

ikonst commented May 15, 2023

I can't think of a good way to do this right now. You can probably go lower-level by doing something like MyModel.attr['filter_attr'] == {'S': 'foobar'}, which is not ideal syntax-wise (you lose the knowledge of filter_attr's type and end up performing serialization yourself),.

@ck-on-github
Copy link
Author

Thanks @ikonst for your prompt answer.

If I do MyModel.attr['filter_attr'] == value when ParentClass inherits MapAttribute, I get AttributeError: 'ParentClass' has no attribute 'filter_attr' again.

if ParentClass inherits DynamicMapAttribute, this seems to work though.

is there anything else I can try to make this work with MapAttribute?

@ikonst
Copy link
Contributor

ikonst commented May 15, 2023

Oh, sorry, I guess you have to do something like Path(MyModel.attr.attr_path + ['filter_attr']). Again, I wish there was a nicer way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants