2013-08-19 80 views
11

Mô hình NDB có hai thuộc tính: emailpassword. Làm thế nào để tránh thêm vào cơ sở dữ liệu hai bản ghi với cùng một email? NDB không có tùy chọn UNIQUE cho một thuộc tính, như cơ sở dữ liệu quan hệ.Duy trì tính duy nhất của một thuộc tính trong cơ sở dữ liệu NDB

Kiểm tra mới email không có trong cơ sở dữ liệu trước khi thêm — sẽ không thỏa mãn tôi, vì hai quy trình song song có thể đồng thời thực hiện việc kiểm tra và mỗi lần thêm cùng một email.

Tôi không chắc chắn rằng các giao dịch có thể trợ giúp ở đây, tôi có ấn tượng này sau khi đọc một số sách hướng dẫn. Có thể các giao dịch đồng bộ ? Liệu nó có nghĩa là từng người một?

Trả lời

6

Tạo khóa của thực thể qua email, sau đó sử dụng get_or_insert để kiểm tra xem có tồn tại hay không.

Also read about keys , entities.models

#ADD 
key_a = ndb.Key(Person, email); 
person = Person(key=key_a) 
person.put() 

#Insert unique  
a = Person.get_or_insert(email) 

hoặc nếu bạn muốn chỉ cần kiểm tra

#ADD 
key_a = ndb.Key(Person, email); 
person = Person(key=key_a) 
person.put() 

#Check if it's added 
new_key_a =ndb.Key(Person, email); 
a = new_key_a.get() 
if a is not None: 
    return 

Hãy chăm sóc. Thay đổi email sẽ thực sự khó khăn (cần phải tạo mục nhập mới và sao chép tất cả các mục nhập vào phụ huynh mới).

Đối với điều đó, có thể bạn cần phải lưu trữ email, trong một thực thể khác và có Người dùng là phụ huynh của điều đó.

Một cách khác là sử dụng Giao dịch và kiểm tra thuộc tính email. Giao dịch của công việc trong cách: Đầu tiên cam kết là lần đầu tiên thắng. Một khái niệm có nghĩa là nếu 2 người dùng kiểm tra email chỉ thì người đầu tiên (may mắn) sẽ thành công, do đó dữ liệu của bạn sẽ nhất quán.

+0

Sử dụng get_or_insert() Tôi sẽ không chắc chắn: tôi đã thêm bản ghi mới hoặc tôi đã có bản ghi hiện có. – Graduate

+1

thay đổi email sẽ là nỗi đau trong một ** ... hoặc tốt hơn .. không thể :) Vì vậy, cho email nó không phải là một giải pháp tốt ,. – Lipis

+0

@Giáo viên nên có 'key_a' sửa lỗi đó. –

4

Có thể bạn đang tìm kiếm mô-đun xác thực webapp2, có thể xử lý điều này cho bạn. Nó có thể được nhập như thế này import webapp2_extras.appengine.auth.models. Hãy xem here để có ví dụ hoàn chỉnh.

2

Tôi cũng chạy vào vấn đề này, và các giải pháp trên không giải quyết vấn đề của tôi:

  • làm cho nó một phím là không thể chấp nhận trong trường hợp của tôi (tôi cần tài sản để có thể thay đổi trong tương lai)
  • sử dụng giao dịch trên thuộc tính email không hoạt động AFAIK (bạn không thể thực hiện truy vấn trên tên không chính trong giao dịch, vì vậy bạn không thể kiểm tra xem email đã tồn tại chưa).

Tôi đã tạo mô hình riêng biệt không có thuộc tính và thuộc tính duy nhất (địa chỉ email) làm tên khóa. Trong mô hình chính, tôi lưu trữ một tham chiếu đến mô hình email (thay vì lưu trữ email dưới dạng chuỗi). Sau đó, tôi có thể thực hiện 'change_email' một giao dịch kiểm tra tính duy nhất bằng cách tra cứu email theo khóa.

0

Đây là điều tôi đã gặp phải và tôi đã giải quyết trên một biến thể của giải pháp @ Remko. Vấn đề chính của tôi với việc kiểm tra thực thể hiện tại với email đã cho là điều kiện chạy tiềm năng như op đã nêu. Tôi đã thêm một mô hình riêng biệt sử dụng địa chỉ email làm khóa và có thuộc tính chứa mã thông báo. Bằng cách sử dụng get_or_insert, mã thông báo thực thể được trả về có thể được kiểm tra dựa trên mã thông báo được nhập và nếu chúng khớp với thì mô hình được chèn vào.

import os 
from google.appengine.ext import ndb 

class UniqueEmail(ndb.Model): 
    token = ndb.StringProperty() 

class User(ndb.Model): 
    email = ndb.KeyProperty(kind=UniqueEmail, required=True) 
    password = ndb.StringProperty(required=True) 

def create_user(email, password): 
    token = os.urandom(24) 
    unique_email = UniqueEmail.get_or_insert(email, 
              token=token) 

    if token == unique_email.token: 
     # If the tokens match, that means a UniqueEmail entity 
     # was inserted by this process. 
     # Code to create User goes here. 
    # The tokens do not match, therefore the UniqueEmail entity 
    # was retrieved, so the email is already in use. 
    raise ValueError('That user already exists.') 
Các vấn đề liên quan