Skip to content

Problems with ManyModelChoiceField validation. #5

@LolusKekus

Description

@LolusKekus

Hello!
I have model like this:

class TestModel(peewee.Model):
    foo = peewee.ForeignKeyField(ModelOne)
    bar = peewee.ForeignKeyField(ModelTwo)
    class Meta:
        indexes = (
            (("foo", "bar"), True),
        )

And when i use <select multiple> i have a mysql error like this:
ERROR 1241 (21000): Operand should contain 1 column(s)

So, i'd made some research and find the problem.

    def perform_index_validation(self, data):
        """
        Validate any unique indexes specified on the model.
        This should happen after all the normal fields have been validated.
        This can add error messages to multiple fields.

        :return: None
        """
        # Build a list of dict containing query values for each unique index.
        index_data = []
        for columns, unique in self.instance._meta.indexes:
            if not unique:
                continue
            index_data.append({col: data.get(col, None) for col in columns})

        # Then query for each unique index to see if the value is unique.
        for index in index_data:
            _query = self.instance.filter(**index)_
            # If we have a primary key, need to exclude the current record from the check.
            if self.pk_field and self.pk_value:
                query = query.where(~(self.pk_field == self.pk_value))
            if query.count():
                err = ValidationError('index', fields=str.join(', ', index.keys()))
                for col in index.keys():
                    self.add_error(col, err)

query = self.instance.filter(**index) generate invalid sql query:

Count(*) 
FROM testmodel AS t1 
INNER JOIN modelone AS t2 ON (t1.foo_id = t2.id) 
INNER JOIN modeltwo AS t3 ON (t1.bar_id = t3.id) 
WHERE ((t1.foo_id = 7) AND (t1.bar_id = (2, 4)));

(t1.bar_id = (2, 4))) - this is a problem sql

I know, this is a peewee orm error, but you can solve this problem on your side like this:

    def perform_index_validation(self, data):
        """
        Validate any unique indexes specified on the model.
        This should happen after all the normal fields have been validated.
        This can add error messages to multiple fields.

        :return: None
        """
        # Build a list of dict containing query values for each unique index.
        index_data = []
        for columns, unique in self.instance._meta.indexes:
            if not unique:
                continue
            index_data.append({col: data.get(col, None) for col in columns})

        # Then query for each unique index to see if the value is unique.
        for index in index_data:
            new_index = {}
            for k, v in index.items():
                if issubclass(type(v), Iterable):
                    k = '%s__in' % k
                new_index[k] = v
            query = self.instance.filter(**new_index)
            # If we have a primary key, need to exclude the current record from the check.
            if self.pk_field and self.pk_value:
                if issubclass(type(self.pk_value), Iterable):
                    query = query.where(~(self.pk_field >> self.pk_value))
                else:
                    query = query.where(~(self.pk_field == self.pk_value))
            if query.count():
                err = ValidationError('index', fields=str.join(', ', index.keys()))
                for col in index.keys():
                    self.add_error(col, err)

p.s.
Your product wery handy. Thank you for it!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions