DataStoreでの唯一性確認

  • GAE Pythonを学んでいるところ。
  • DataStoreにはUnique Constraintがないみたい。
class Location(db.Model):
    user = db.UserProperty(required = True)
    name = db.StringProperty('Name', required = True)
    description = db.TextProperty('Description')
  • 上記のようなモデルにおいて、「あるユーザは同じnameのLocationを二つ以上持てない」という制約を考えてみる。
  • Add a Unique Constraint to Google App Engineuniquemodelを使うのが確実だが...「独自性を確保確認するEntity Groupが必要」と、やや大袈裟になってしまう。
  • 対象となるモデルが、ユーザ操作以外の手段で書き換えられるのならuniquemodelを活用する以外に道はないだろう。
  • が、Formからしか操作しないのであれば、GAEについてくるDjangoのModelFormを使えばいいのではないか、と考えた。
  • 上記Locationの例だと
class LocationForm(djangoforms.ModelForm):
    class Meta:
        model = Location
        exclude = ('user',)

    def clean_name(self):
        name = self.clean_data['name']
        user = self.instance.user

        if get_my_location_by_name(user, name):
            raise forms.ValidationError('This location name is in use already')

        return name

def get_my_location_by_name(user, name):
    return Location.gql("WHERE user = :user and name = :name",
                       user = user,
                       name = name).get()
  • これでOK。
  • save()が呼ばれる時にis_valid()が評価され、clean_name()が呼ばれる。
  • GAEのDjangoは0.96なので、最近のとModelFormの扱いが微妙に違うのが難点。clean_dataとcleaned_data、みたいな。