2011-03-08 6 views
7

वर्तमान में, जिस तरह से हमारे, साथ ही साथ अधिकांश वेब ढांचे ', क्रमबद्धता कार्य कुछ प्रकार के विधि आमंत्रण हैं जो मॉडल को किसी प्रकार के प्रारूप में डंप करते हैं। हमारे मामले में, हमारे पास प्रत्येक मॉडल पर to_dict() विधि है जो कि कुंजी नाम के साथ कुंजी-मूल्य शब्दकोश बनाता है और फ़ील्ड नाम होने वाला मान देता है और मान आवृत्ति चर होता है।एक्सेस नियंत्रण का सम्मान करते समय एक आरईएसटी एपीआई के लिए SQLAlchemy मॉडल Serializing?

हमारे पूरे कोड में, हमारे पास निम्न जैसे स्निपेट हैं: json.dumps(**some_model_object.to_dict()) जो some_model_object को जेसन में क्रमबद्ध करेगा। हाल ही में, हमने अपने उपयोगकर्ताओं को कुछ आंतरिक संसाधनों का खुलासा करने का निर्णय लिया है, लेकिन इनमें से कुछ संसाधनों में विशिष्ट निजी उदाहरण मान हैं जिन्हें हम क्रमशः उपयोगकर्ता को सुपर उपयोगकर्ता नहीं होने पर धारावाहिकरण के दौरान संचारित नहीं करना चाहते हैं।

मैं एक स्वच्छ डिजाइन के साथ आने की कोशिश कर रहा हूं जो आसान क्रमबद्धता की अनुमति देगा, साथ ही साथ हमें जेसन के अलावा किसी अन्य प्रारूप में क्रमबद्ध करने की अनुमति देगा। मुझे लगता है कि यह आस्पेक्ट ओरिएंटेड डिजाइन/प्रोग्रामिंग के लिए एक बहुत अच्छा उपयोग मामला है, जहां पहलुओं का अनुरोध करने वाले अनुरोध नियंत्रण का सम्मान करते हैं और उपयोगकर्ता के अनुरोधों के आधार पर ऑब्जेक्ट को क्रमबद्ध करते हैं।

from framework import current_request 


class User(SQLAlchemyDeclarativeModel): 
    __tablename__ = 'users' 

    id = Column(Integer, primary_key=True) 
    first_name = Column(Unicode(255)) 
    last_name = Column(Unicode(255)) 
    private_token = Column(Unicode(4096)) 

    def to_dict(self): 
     serialized = dict((column_name, getattr(self, column_name)) 
          for column_name in self.__table__.c.keys()) 

     # current request might not be bound yet, could be in a unit test etc. 
     if current_request and not current_request.user.is_superuser(): 
      # we explicitly define the allowed items because if we accidentally add 
      # a private variable to the User table, then it might be exposed. 
      allowed = ['id', 'first_name', 'last_name'] 
      serialized = dict((k, v) for k, v in serialized.iteritems() if k in allowed) 

     return serialized 

एक देख सकते हैं, इस आदर्श से कम क्योंकि अब मैं जोड़ी के लिए मौजूदा अनुरोध के साथ डेटाबेस मॉडल है:

यहाँ अब मैं क्या करने के लिए कुछ इसी तरह है। हालांकि यह बहुत स्पष्ट है, अनुरोध युग्मन एक कोड गंध है और मैं यह देखने की कोशिश कर रहा हूं कि इसे साफ तरीके से कैसे किया जाए।

एक तरह से मैं करने के बारे में सोचा है ऐसा जैसे मॉडल पर कुछ क्षेत्रों रजिस्टर करने के लिए है: तो फिर

class User(SQLAlchemyDeclarativeModel): 
    __tablename__ = 'users' 
    __public__ = ['id', 'first_name', 'last_name'] 
    __internal__ = User.__exposed__ + ['private_token'] 

    id = Column(Integer, primary_key=True) 
    first_name = Column(Unicode(255)) 
    last_name = Column(Unicode(255)) 
    private_token = Column(Unicode(4096)) 

, मैं एक serializer वर्ग है कि हर WSGI फोन पर वर्तमान अनुरोध के साथ ही है होता वह वांछित serializer ले जाएगा। उदाहरण के लिए:

import simplejson 

from framework import JSONSerializer # json serialization strategy 
from framework import serializer 

# assume response format was requested as json 
serializer.register_serializer(JSONSerializer(simplejson.dumps)) 
serializer.bind(current_request) 
तो मेरे विचार में

कहीं, मैं सिर्फ करना होगा:

def serialize(self, db_model_obj): 
    attributes = '__public__' 
    if self.current_request.user.is_superuser(): 
     attributes = '__private__' 

    payload = dict((c, getattr(db_model_obj, c)) 
        for c in getattr(db_model_obj, attributes)) 

    return self.serialization_strategy.execute(payload) 

इस दृष्टिकोण के पठनीयता और स्पष्टता पर विचार: इस प्रकार

from framework import Response 

user = session.query(User).first() 
return Response(code=200, serializer.serialize(user)) 

serialize लागू किया जाएगा? क्या यह समस्या के लिए एक पाइथोनिक दृष्टिकोण है?

अग्रिम धन्यवाद।

+0

मुझे यकीन नहीं है कि एक परिवर्तनीय सी नामकरण एक बहुत अच्छा विचार है। :) और मेरे पास serialization_strategy जैसे कुछ के बारे में मेरा आरक्षण है। चूंकि कक्षा पहले से ही इसके अनावश्यक है और डिजाइन पैटर्न नाम ड्रॉप की तरह लगती है। मुझे लगता है कि यह संबंधित वर्गों के दौरे की रणनीति की तरह कुछ और विशिष्ट है? मुझे आशा है कि आप वास्तव में अपने ढांचे "ढांचे" का नाम नहीं दे रहे हैं। :) –

उत्तर

7

एक mixin के माध्यम से "क्रमबद्धता" अनुबंध की स्थापना:

class Serializer(object): 
    __public__ = None 
    "Must be implemented by implementors" 

    __internal__ = None 
    "Must be implemented by implementors" 

    def to_serializable_dict(self): 
     # do stuff with __public__, __internal__ 
     # ... 

यह WSGI एकीकरण के साथ सरल रखें। "रजिस्टर", JSONSerializer किसी ऑब्जेक्ट के रूप में, और जो कुछ भी जावा/स्प्रिंग चीज़ है, उसे उस प्रशंसक की आवश्यकता नहीं है। नीचे मेरे पिलों 1.0-स्टाइल समाधान हैं, मैं अभी तक पिरामिड पर नहीं हूं:

def my_controller(self): 
    # ... 

    return to_response(request, response, myobject) 


# elsewhere 
def to_response(req, resp, obj): 
    # this would be more robust, look in 
    # req, resp, catch key errors, whatever. 
    # xxx_serialize are just functions. don't need state 
    serializer = { 
     'application/json':json_serialize, 
     'application/xml':xml_serialize, 
     # ... 
    }[req.headers['content-type']] 

    return serializer(obj) 
+0

महान सलाह।धन्यवाद माइकल। –

संबंधित मुद्दे