简体   繁体   中英

Flask-SQLAlchemy Can't Create Relationship - SAWarning

I used fbone to start this project off and I'm using its implementation of a Flask-SQLAlchemy column extension named DenormalizedText . I get the concept of this and how it works (not my issue) but my implementation of the add method is having odd results.

DenormalizedText

class DenormalizedText(Mutable, types.TypeDecorator):
    """
    Stores denormalized primary keys that can be
    accessed as a set.

    :param coerce: coercion function that ensures correct
               type is returned

    :param separator: separator character
    """

    impl = types.Text

    def __init__(self, coerce=int, separator=" ", **kwargs):

        self.coerce = coerce
        self.separator = separator

    super(DenormalizedText, self).__init__(**kwargs)

    def process_bind_param(self, value, dialect):
        if value is not None:
            items = [str(item).strip() for item in value]
            value = self.separator.join(item for item in items if item)
        return value

    def process_result_value(self, value, dialect):
        if not value:
            return set()
        return set(self.coerce(item) for item in value.split(self.separator))

    def copy_value(self, value):
        return set(value)

My class Person has a DenormalizedText parameter named family

family = Column(DenormalizedText)

and here's the add method

# just adds each object to the other's family relationship
def add_family(self, person):
    self.family.add(person.id)
    person.family.add(self.id)

So here's the strange bits:

  1. I have another relationship for Person done the exact same way for a different class called Residence . This works fine. So I think for a minute maybe there's an issue with a self-referencing implementation. But fbone does this with their provided User class and that works?!

  2. So I wrote a test ... and it passed!

  3. Everything leading up to the use of this method works fine. Both Person objects are in session and committed, I double check the "family member" before trying to add (make sure they were saved to the db and have an id).

    1. Occasionally I get this rare error: SAWarning: The IN-predicate on "persons.id" was invoked with an empty sequence. This results in a contradiction, which nonetheless can be expensive to evaluate. Consider alternative strategies for improved performance. SAWarning: The IN-predicate on "persons.id" was invoked with an empty sequence. This results in a contradiction, which nonetheless can be expensive to evaluate. Consider alternative strategies for improved performance.

Like I said this works fine for the residences relationship with Person but here's the relevant code from the view and form handler in case:

def create_step2_family():

    client = Person()
    spouse = Person()
    spouse_form = PersonalForm()

    # default action
    try:
        client = Person.get_by_id(session['working_client'])
    except KeyError:
        flash('Please complete this section first.', 'warning')
        return redirect(url_for('client.create_step1_personal'))
    else:

        # spouse form action
        if request.method == 'POST' and spouse_form.validate_on_submit():
            spouse_form.populate_obj(spouse)
            spouse.type_code = SPOUSE

            db.session.add(spouse)
            db.session.commit()

            if Person.get_by_id(spouse.id):
                client.add_family(spouse)
                db.session.add(client)
                db.session.commit()

    return render_template('clients/wizard/step2/family.html', active="Create",
    client=client, spouse=spouse, spouse_form=spouse_form, active_tab="family")

I need a vacation

The error " SAWarning: The IN-predicate on "persons.id" was invoked with an empty sequence. This results in a contradiction, which nonetheless can be expensive to evaluate. Consider alternative strategies for improved performance. " was because I was calling a query on the column that returned nothing, or the list of persons.id s was empty because, well, nothing was being added.

And nothing was being added because I forgot these little lines at the bottom of my add method:

def add_family(self, person):
    self.family.add(person.id)
    person.family.add(self.id)
    self.family=set(self.family)
    person.family=set(person.family)

I'm a mess. Anyway, I won't accept my answer for this if someone can provide a better explanation or improvement to the code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM