App engine datastore query issue

312 views Asked by At

I have a weired problem with couple of queries I am trying to run.

I have built a method which returns a tuple of result from the query-

def get_activeproducts():
    query = Product.gql("WHERE active = True")
    choices = []
    for obj in query:
        choices.append((str(obj.key()), obj.name))
    return choices

The problem is, the result is same for each call. Even if products are deleted or changed to 'False' in the product attribute 'active'. The result will be refreshed only when I restart the sdk server. In production, it just doesnt change till I change versions.

I have seen similar issue with one more query where the query property is BooleanProperty.

Any idea on how this could be fixed?

EDIT: I am using the method in a tipfy application. It is used to populate a select field in wtforms. 'choices' basically takes in a list of tuples (value, name) pair.

class InvoiceForm(Form):
    product = SelectField('Product', choices=get_activeproducts())

I dont have any issue with editing. WHen I check it from the admin end, I can see that certain products are set to 'False'. And even if I empty(delete) the whole list of products, I get the same list I got the first time.

I am not using caching anywhere in the application.

2

There are 2 answers

1
Wooble On BEST ANSWER

Your class definition is getting cached by the App Engine runtime when an instance is started, with the default set to what it was when the instance started. To make the choices dynamic, you need to set them at runtime.

Example from the wtforms (which IIRC is what tipfy is using) docs; will need to be adjusted for App Engine queries:

class UserDetails(Form):
    group_id = SelectField(u'Group', coerce=int)

def edit_user(request, id):
    user = User.query.get(id)
    form = UserDetails(request.POST, obj=user)
    form.group_id.choices = [(g.id, g.name) for g in Group.query.order_by('name')]
0
Black Hand On

when you create your form, the function is called once.

you can overload the form __init__.py function to do this cleanly

class InvoiceForm(Form):
    product = SelectField(u'Group', choices=[])

    def __init__(self, product_select, *args, **kwargs)
        super(InvoiceForm, self).__init__(*args, **kwargs)
        self.product.choices = select_dict

----
form = InvoiceForm(product_select=get_activeproducts())