2010-04-06 9 views
15

में @property विधियों को सीरियलाइज़ करें क्या कोई Django मॉडल क्लास को क्रमबद्ध करते समय किसी भी @property परिभाषाओं को एक जेसन सीरियलाइज़र से गुज़रने का कोई तरीका है?पाइथन कक्षा

उदाहरण:

def list_class_properties(cls): 
    return [k for k,v in cls.__dict__.iteritems() if type(v) is property] 

उदाहरण के लिए:

[{ 

    'name' : 'Test User', 

    'foo' : 'My name is Test User', 
},] 

उत्तर

0

आप कुछ काला जादू का उपयोग कर एक वर्ग के गुणों के सभी प्राप्त कर सकते हैं:

class FooBar(object.Model) 

    name = models.CharField(...) 

    @property 
    def foo(self): 
     return "My name is %s" %self.name 

को क्रमानुसार करने चाहते हैं:

>>> class Foo: 
     @property 
     def bar(self): 
      return "bar" 

>>> list_class_properties(Foo) 
['bar'] 

फिर आप शब्दकोश बना सकते हैं और इसे वहां से क्रमबद्ध कर सकते हैं।

+0

कि अनिवार्य रूप से की आवश्यकता होगी अपने ही हैश बनाने, केवल अनिवार्य रूप से एक हैश को क्रमानुसार करने। अगर मैं उस मार्ग पर जाता हूं, तो मैं लगभग पूरे क्रमबद्धता को काट सकता हूं। मैं डीजेंगो मॉडल क्लास का उपयोग जारी रखने की उम्मीद कर रहा था और बस सीरियलize ('जेसन', my_object, ...) – ashchristopher

+0

दुर्भाग्यवश, ऐसा प्रतीत होता है कि Django के कोर सीरियलाइजेशन दिनचर्या विशेष रूप से '_meta' में नहीं है जो कुछ भी बहिष्कृत करते हैं) मूल रूप से केवल डीबी मॉडल फ़ील्ड के लिए दिखता है। तो जब आप एक ऐसा फ़ंक्शन लिख सकते हैं जो केवल संपत्ति फ़ील्ड खींचता है (जो 'निरीक्षण के साथ बेहतर किया जा सकता है।getmembers 'विधि को दूसरी ब्लश पर),' serializers.serialize' विधि पर 'फ़ील्ड' पैरामीटर का उपयोग करने से भी काम नहीं करेगा। यहां देखें, जहां वे पास की गई क्वेरीसेट पर फिर से सक्रिय होते हैं और केवल '_meta' में सामान ढूंढते हैं: http://code.djangoproject.com/browser/django/trunk/django/core/serializers/base.py# L39 –

12

आप Django के serializers को बिना/बहुत अधिक काम के विस्तार कर सकते हैं। यहां एक कस्टम धारावाहिक है जो एक क्वेरीसेट और विशेषताओं की सूची (फ़ील्ड या नहीं) लेता है, और जेएसओएन देता है।

from StringIO import StringIO 
from django.core.serializers.json import Serializer 

class MySerializer(Serializer): 
    def serialize(self, queryset, list_of_attributes, **options): 
     self.options = options 
     self.stream = options.get("stream", StringIO()) 
     self.start_serialization() 
     for obj in queryset: 
      self.start_object(obj) 
      for field in list_of_attributes: 
       self.handle_field(obj, field) 
      self.end_object(obj) 
     self.end_serialization() 
     return self.getvalue() 

    def handle_field(self, obj, field): 
     self._current[field] = getattr(obj, field) 

उपयोग:

>>> MySerializer().serialize(MyModel.objects.all(), ["field1", "property2", ...]) 
बेशक

, यह सिर्फ अपनी खुद की सरल JSON serializer लिखने की तुलना में शायद अधिक काम है, लेकिन शायद अपने स्वयं के XML serializer से नहीं अधिक काम (आप को फिर से परिभाषित करना होगा ऐसा करने के लिए बेस क्लास को बदलने के अलावा एक्सएमएल केस से मेल खाने के लिए "हैंडलफील्ड")।

+0

"MySerializer 'ऑब्जेक्ट प्राप्त करने से Django (1.5.4) –

5

2010 से चीजें थोड़ी-थोड़ी बदल गई हैं, इसलिए @ user85461 का उत्तर अब Django 1.8 और पायथन 3.4 के साथ काम नहीं कर रहा है। यह मेरे लिए काम करने के लिए एक अद्यतन उत्तर है।

from django.core.serializers.base import Serializer as BaseSerializer 
from django.core.serializers.python import Serializer as PythonSerializer 
from django.core.serializers.json import Serializer as JsonSerializer 
from django.utils import six 

class ExtBaseSerializer(BaseSerializer): 
    """ Abstract serializer class; everything is the same as Django's base except from the marked lines """ 
    def serialize(self, queryset, **options): 
     self.options = options 

     self.stream = options.pop('stream', six.StringIO()) 
     self.selected_fields = options.pop('fields', None) 
     self.selected_props = options.pop('props', None) # added this 
     self.use_natural_keys = options.pop('use_natural_keys', False) 
     self.use_natural_foreign_keys = options.pop('use_natural_foreign_keys', False) 
     self.use_natural_primary_keys = options.pop('use_natural_primary_keys', False) 

     self.start_serialization() 
     self.first = True 
     for obj in queryset: 
      self.start_object(obj) 
      concrete_model = obj._meta.concrete_model 
      for field in concrete_model._meta.local_fields: 
       if field.serialize: 
        if field.rel is None: 
         if self.selected_fields is None or field.attname in self.selected_fields: 
          self.handle_field(obj, field) 
        else: 
         if self.selected_fields is None or field.attname[:-3] in self.selected_fields: 
          self.handle_fk_field(obj, field) 
      for field in concrete_model._meta.many_to_many: 
       if field.serialize: 
        if self.selected_fields is None or field.attname in self.selected_fields: 
         self.handle_m2m_field(obj, field) 
      # added this loop 
      if self.selected_props: 
       for field in self.selected_props: 
        self.handle_prop(obj, field) 
      self.end_object(obj) 
      if self.first: 
       self.first = False 
     self.end_serialization() 
     return self.getvalue() 

    # added this function 
    def handle_prop(self, obj, field): 
     self._current[field] = getattr(obj, field) 


class ExtPythonSerializer(ExtBaseSerializer, PythonSerializer): 
    pass 


class ExtJsonSerializer(ExtPythonSerializer, JsonSerializer): 
    pass 

उपयोग:

>>> ExtJsonSerializer().serialize(MyModel.objects.all(), fields=['myfield', ...], props=['myprop', ...]) 
+2

पर कोई विशेषता' पहली 'त्रुटि नहीं है यह सही उत्तर है और मेरे लिए अच्छा काम करता है। – Rafay

+0

एक बेहतर संस्करण पोस्ट किया गया। – caot

3

समाधान अच्छी तरह से काम है कि एम Rafay अलीम और Wtower द्वारा प्रस्तावित है, लेकिन यह कोड के बहुत दोहराया गया है।

from django.core.serializers.base import Serializer as BaseSerializer 
from django.core.serializers.python import Serializer as PythonSerializer 
from django.core.serializers.json import Serializer as JsonSerializer 

class ExtBaseSerializer(BaseSerializer): 

    def serialize_property(self, obj): 
     model = type(obj) 
     for field in self.selected_fields: 
      if hasattr(model, field) and type(getattr(model, field)) == property: 
       self.handle_prop(obj, field) 

    def handle_prop(self, obj, field): 
     self._current[field] = getattr(obj, field) 

    def end_object(self, obj): 
     self.serialize_property(obj) 

     super(ExtBaseSerializer, self).end_object(obj) 


class ExtPythonSerializer(ExtBaseSerializer, PythonSerializer): 
    pass 


class ExtJsonSerializer(ExtPythonSerializer, JsonSerializer): 
    pass 

इसका उपयोग कैसे करें:

ExtJsonSerializer().serialize(MyModel.objects.all(), fields=['field_name_1', 'property_1' ...]) 
1

यह एम Rafay अलीम और Wtowers जवाब और caots का एक संयोजन है यहाँ एक improvment है। यह DRY है और आपको केवल सभी क्षेत्रों और प्रोप के बजाय अतिरिक्त प्रोप निर्दिष्ट करता है जैसे कि कैट्स संस्करण में।

from django.core.serializers.json import Serializer as JsonSerializer 
from django.core.serializers.python import Serializer as PythonSerializer 
from django.core.serializers.base import Serializer as BaseSerializer 

class ExtBaseSerializer(BaseSerializer): 
    def serialize(self, queryset, **options): 
     self.selected_props = options.pop('props') 
     return super(ExtBaseSerializer, self).serialize(queryset, **options) 

    def serialize_property(self, obj): 
     model = type(obj) 
     for field in self.selected_props: 
      if hasattr(model, field) and type(getattr(model, field)) == property: 
       self.handle_prop(obj, field) 

    def handle_prop(self, obj, field): 
     self._current[field] = getattr(obj, field) 

    def end_object(self, obj): 
     self.serialize_property(obj) 

     super(ExtBaseSerializer, self).end_object(obj) 

class ExtPythonSerializer(ExtBaseSerializer, PythonSerializer): 
    pass 

class ExtJsonSerializer(ExtPythonSerializer, JsonSerializer): 
    pass 

इसका उपयोग कैसे करें:

ExtJsonSerializer().serialize(MyModel.objects.all(), props=['property_1', ...]) 
संबंधित मुद्दे