2015-03-04 13 views
9

Nếu tôi có một số giá trị (chuỗi) từ yêu cầu GET hoặc POST với các trường hợp Property liên quan, một IntegerProperty và một TextProperty, có cách nào đó để chuyển đổi các giá trị sang loại người dùng thích hợp mà không có chuỗi dài tẻ nhạt trong số isinstance cuộc gọi?Cách đúng để chuyển đổi chuỗi thành loại thích hợp cho thuộc tính NDB?

Tôi đang tìm để tái tạo loại này chức năng (tất cả các xác nhận đầu vào bỏ qua cho rõ ràng):

for key, value in self.request.POST.iteritems(): 
    prop = MyModel._properties[key] 

    if isinstance(prop, ndb.IntegerProperty): 
     value = int(value) 
    elif isinstance(prop, (ndb.TextProperty, ndb.StringProperty)): 
     pass # it's already the right type 
    elif ... 
    else 
     raise RuntimeError("I don't know how to deal with this property: {}" 
          .format(prop)) 

    setattr(mymodelinstance, key, value) 

Ví dụ, nếu có một cách để có được những lớp int từ một IntegerProperty và lớp bool từ một số BooleanProperty v.v., điều đó sẽ thực hiện công việc.

API siêu dữ liệu ndb không thực sự giải quyết điều này một cách tao nhã, theo như tôi thấy; với get_representations_of_kind Tôi có thể giảm số lượng các trường hợp, mặc dù.

+0

Tôi có thể cảm thấy nỗi đau của bạn ... một câu hỏi, bạn nên biết các loại dữ liệu dự kiến ​​từ các mục ** POST **, vậy tại sao không chỉ nhận được ** giá trị ** theo dự kiến ​​** phím ** và chuyển đổi chúng thành loại thích hợp? – Anzel

+0

@Anzel Không chắc chắn ý của bạn về việc biết các kiểu dữ liệu mong muốn từ các mục POST. Trong định nghĩa mô hình, tôi có 45 thuộc tính của một vài kiểu khác nhau; vì tôi không lặp lại bản đồ giữa tên và loại thuộc tính ở bất kỳ đâu nhưng vẫn biết liệu giá trị như "Đúng" hay "5" cần được hiểu là bool, string hoặc int . –

+0

Tôi hiểu những gì bạn đang cố gắng làm, nhưng vì dữ liệu bạn sẽ chuyển đổi là dữ liệu GET/POST, bạn có thể xác định hàm chuyển đổi để ánh xạ cặp khóa/giá trị ... – Anzel

Trả lời

0

Có gói Python được gọi là WTForms rất hữu ích cho việc này và thường làm cho biểu mẫu xử lý trải nghiệm thú vị hơn nhiều.

Dưới đây là một ví dụ rất đơn giản:

class MyForm(wt.Form): 
    text = MyTextAreaField("Enter text") 
    n = wt.IntegerField("A number") 

f = MyForm(self.request.POST) 
f.validate() 
print f.text.data 
print f.n.data 

Calling f.validate() sẽ tự động chuyển dữ liệu POST để kiểu dữ liệu theo quy định của biểu mẫu. Vì vậy, f.text.data sẽ là một chuỗi và f.n.data sẽ là một int.

Nó cũng xử lý dữ liệu không hợp lệ một cách duyên dáng. Nếu người dùng nhập một chữ cái cho trường số nguyên, thì f.n.data sẽ là None. Bạn cũng có thể chỉ định các thông báo lỗi dễ dàng được tích hợp vào trang web của bạn.

WTForms mất một số lượng lớn các drudgery trong xử lý hình thức!

2

Bạn có thể sử dụng dict để ánh xạ giữa các loại do người dùng xác định với các loại được tạo sẵn bằng cách sử dụng type đối tượng làm khóa và giá trị được tích hợp sẵn.

F.e.

class IntegerProperty(int): 
    pass 

class StringProperty(str): 
    pass 

a, b = IntegerProperty('1'), StringProperty('string') 

def to_primitive(obj): 
    switch = {IntegerProperty: int, StringProperty: str} 
    return switch[type(obj)](obj) 

for x in (a, b): 
     print(to_primitive(x)) 

Bởi vì ở đây chính là kiểu của đối tượng thay vì isinstance kiểm tra, nếu bản đồ nhiều hơn một kiểu do người dùng định nghĩa một đơn built-in loại KeyError sẽ xảy ra nếu loại không nằm trong dict. Vì vậy, bạn phải thêm một cách rõ ràng mọi loại do người dùng xác định vào công tắc dict.

F.e.

class TextProperty(StringProperty): 
    pass 
switch = {IntegerProperty: int, StringProperty: str, TextProperty: str} 

Trên chúng tôi đã thêm mới TextProperty đến switch mặc dù TextProperty là lớp con của StringProperty. Nếu bạn không muốn làm điều đó, chúng tôi phải lấy chìa khóa từ kiểm tra isinstance.
Dưới đây là cách thực hiện;

class IntegerProperty(int): 
    pass 

class StringProperty(str): 
    pass 

class TextProperty(StringProperty): 
    pass 

a, b, c = IntegerProperty('1'), StringProperty('string'), TextProperty('text') 

def to_primitive(obj): 
    switch = {IntegerProperty: int, StringProperty: str} 
    key = filter(lambda cls: isinstance(obj, cls), switch.keys()) 
    if not key: 
     raise TypeError('Unknown type: {}'.format(repr(obj))) 
    key = key[0] 

    return switch[key](obj) 

for x in (a, b, c): 
     print(to_primitive(x)) 
Các vấn đề liên quan