Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>There's no built-in constraint for making sure a value is unique. You can do this however:</p> <pre><code>query = MyModel.all(keys_only=True).filter('unique_property', value_to_be_used) entity = query.get() if entity: raise Exception('unique_property must have a unique value!') </code></pre> <p>I use <code>keys_only=True</code> because it'll improve the performance slightly by not fetching the data for the entity.</p> <p>A more efficient method would be to use a separate model with no fields whose key name is made up of property name + value. Then you could use <code>get_by_key_name</code> to fetch one or more of these composite key names and if you get one or more not-<code>None</code> values, you know there are duplicate values (and checking which values were not <code>None</code>, you'll know which ones were not unique.)</p> <hr> <p>As <em>onebyone</em> mentioned in the comments, these approaches &ndash; by their get first, put later nature &ndash; run the risk concurrency issues. Theoretically, an entity could be created just after the check for an existing value, and then the code after the check will still execute, leading to duplicate values. To prevent this, you will have to use transactions: <a href="http://code.google.com/appengine/docs/python/datastore/transactions.html" rel="nofollow noreferrer">Transactions - Google App Engine</a></p> <hr> <p>If you're looking to check for uniqueness across <em>all</em> entities with transactions, you'd have to put all of them in the same group using the first method, which would be very inefficient. For transactions, use the second method like this:</p> <pre><code>class UniqueConstraint(db.Model): @classmethod def check(cls, model, **values): # Create a pseudo-key for use as an entity group. parent = db.Key.from_path(model.kind(), 'unique-values') # Build a list of key names to test. key_names = [] for key in values: key_names.append('%s:%s' % (key, values[key])) def txn(): result = cls.get_by_key_name(key_names, parent) for test in result: if test: return False for key_name in key_names: uc = cls(key_name=key_name, parent=parent) uc.put() return True return db.run_in_transaction(txn) </code></pre> <p><code>UniqueConstraint.check(...)</code> will assume that every single key/value pair must be unique to return success. The transaction will use a single entity group for every model kind. This way, the transaction is reliable for several different fields at once (for only one field, this would be much simpler.) Also, even if you've got fields with the same name in one or more models, they will not conflict with each other.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload