आप Django में एक मॉडल उदाहरण को कैसे अनुक्रमित करते हैं?


157

मॉडल QuerySet को क्रमबद्ध करने के बारे में बहुत सारे दस्तावेज हैं लेकिन आप JSON को एक मॉडल इंस्टेंस के क्षेत्र में कैसे अनुक्रमित करते हैं?


हालांकि ऐसा लगता है कि आप 1 ऑब्जेक्ट की क्वेरी को क्रमबद्ध कर सकते हैं, आप ऐसा करने के लिए कक्षाओं का उपयोग नहीं कर सकते django.core। कोई विशेष कारण क्वेरी को क्रमबद्ध नहीं करना है?
जैक एम।

1
क्वेरी सीरियलाइज़र ने परिणाम को दो और परतों में लपेटता है, जितना कि यह है। इसलिए आपको data.name के बजाय डेटा [0] .fields.name करना होगा।
जेसन क्रिस्टा

बिल्कुल यही मैने सोचा। मैं उसी मुद्दे में भाग गया जब मैं एक django बैकएंड के लिए GWT इंटरफ़ेस लिख रहा था। लगता है कि डेविड कुछ पर हो सकता है।
जैक एम।

जवाबों:


241

आप आसानी से आवश्यक वस्तु को लपेटने के लिए एक सूची का उपयोग कर सकते हैं और यह सब क्या django serializers को इसे सही ढंग से क्रमबद्ध करने की आवश्यकता है, उदा .:

from django.core import serializers

# assuming obj is a model instance
serialized_obj = serializers.serialize('json', [ obj, ])

9
लेकिन प्रतिक्रिया में आपको क्रमबद्ध ऑब्जेक्ट को प्राप्त करने के लिए JSON ऑब्जेक्ट के शून्य तत्व को अनुक्रमित करना आवश्यक है। बस कुछ ध्यान देना है।
१avor:

10
और रूट ऑब्जेक्ट के साथ सभी संदर्भित ऑब्जेक्ट्स को क्रमबद्ध करने के बारे में कैसे?
पावेलोके

1
क्या आप [0]अपनी अंतिम पंक्ति के अंत में नहीं चाहते हैं , जैसे @DavorLucic का सुझाव दिया गया है? और अपनी सूची शाब्दिक में अल्पविराम के लिए कोई ज़रूरत नहीं है (PEP8 के प्यार के लिए;)।
हॉब्स

देशीकरण के लिए भी एक अतिरिक्त कदम की आवश्यकता होती है; देखें stackoverflow.com/a/29550004/2800876
ज़ैग्स

5
यह मेरे लिए काम नहीं किया। Django फेंकता है AttrorError 'tuple' ऑब्जेक्ट में कोई विशेषता नहीं है '_meta'
adamF

71

यदि आप मॉडल के उदाहरणों की सूची के साथ काम कर रहे हैं, तो आप जो सबसे अच्छा उपयोग कर रहे हैं serializers.serialize(), वह आपकी आवश्यकता को पूरी तरह से पूरा करने वाला है।

हालांकि, अगर आप एक क्रमानुसार करने की कोशिश कर के साथ एक समस्या का सामना कर रहे हैं एक वस्तु है, न कि listवस्तुओं की। इस तरह, अलग-अलग हैक से छुटकारा पाने के लिए, बस Django का उपयोग करें model_to_dict(यदि मैं गलत नहीं हूं, तो इस serializers.serialize()पर भी निर्भर करता है:

from django.forms.models import model_to_dict

# assuming obj is your model instance
dict_obj = model_to_dict( obj )

अब आपको केवल एक सीधे json.dumpsकॉल की जरूरत है ताकि इसे जस का तस किया जा सके:

import json
serialized = json.dumps(dict_obj)

बस! :)


6
यह UUID क्षेत्रों के साथ विफल रहता है, अन्यथा स्पष्ट होना चाहिए
एल्विन

2
datetimeखेतों के साथ विफल रहता है । इस तरह से हल किया, json.loads(serialize('json', [obj]))[0]जबकि धारावाहिक हैdjango.core.serializers.serialize
लाल ज़ादा

43

सरणी आवरण से बचने के लिए, प्रतिक्रिया वापस करने से पहले इसे हटा दें:

import json
from django.core import serializers

def getObject(request, id):
    obj = MyModel.objects.get(pk=id)
    data = serializers.serialize('json', [obj,])
    struct = json.loads(data)
    data = json.dumps(struct[0])
    return HttpResponse(data, mimetype='application/json')

मुझे यह रोचक पोस्ट इस विषय पर भी मिली:

http://timsaylor.com/convert-django-model-instances-to-dictionaries

यह django.forms.models.model_to_dict का उपयोग करता है, जो काम के लिए एकदम सही उपकरण की तरह दिखता है।


9
अगर यह django में किसी एकल मॉडल को क्रमबद्ध करने का सबसे अच्छा तरीका है, तो यह भयानक है क्योंकि किसी को भी जशन को नष्ट करने और इसे वापस प्रसारित करने की आवश्यकता नहीं होनी चाहिए।
हर्बर्ट

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

1
आतंक को छिपाना समस्या नहीं है और शायद यह समाधान भी नहीं है; मुझे आश्चर्य है कि यह django का यह करने का सबसे अच्छा तरीका है।
हर्बर्ट

14

इसके लिए एक अच्छा जवाब है और मुझे आश्चर्य है कि इसका उल्लेख नहीं किया गया है। कुछ पंक्तियों के साथ आप दिनांक, मॉडल, और सब कुछ संभाल सकते हैं।

एक कस्टम एनकोडर बनाएं जो मॉडल को संभाल सकता है:

from django.forms import model_to_dict
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Model

class ExtendedEncoder(DjangoJSONEncoder):

    def default(self, o):

        if isinstance(o, Model):
            return model_to_dict(o)

        return super().default(o)

जब आप json.dumps का उपयोग करते हैं तो इसका उपयोग करें

json.dumps(data, cls=ExtendedEncoder)

अब मॉडल, दिनांक और सब कुछ क्रमबद्ध किया जा सकता है और यह किसी सरणी या क्रमबद्ध और गैर-अधिकृत में नहीं होना चाहिए। आपके पास जो कुछ भी है वह कस्टम है बस defaultविधि में जोड़ा जा सकता है ।

आप इस तरह से Django के मूल JsonResponse का उपयोग कर सकते हैं:

from django.http import JsonResponse

JsonResponse(data, encoder=ExtendedEncoder)
``

3
यह समाधान सरल और सुरुचिपूर्ण है। एनकोडर का उपयोग दोनों तरीकों json.dumpsऔर json.dumpतरीकों के साथ किया जा सकता है । इस तरह से आपको एप्लिकेशन के वर्कफ़्लो को बदलने की आवश्यकता नहीं है क्योंकि आप कस्टम ऑब्जेक्ट्स का उपयोग करते हैं या किसी अन्य विधि कॉल को जोड़ने से पहले json में कनवर्ट करते हैं। बस एनकोडर में अपना रूपांतरण कोड जोड़ें और आप जाने के लिए तैयार हैं।
क्लाउडीयू

11

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

यहाँ मैं क्या कर रहा हूँ:

सबसे पहले, मैं demjsonरूपांतरण के लिए उपयोग करता हूं । यह वही हुआ जो मैंने पहले पाया था, लेकिन यह सबसे अच्छा नहीं हो सकता है। मेरा कार्यान्वयन इसकी विशेषताओं में से एक पर निर्भर करता है, लेकिन अन्य कन्वर्टर्स के साथ समान तरीके होने चाहिए।

दूसरा, json_equivalentउन सभी मॉडलों पर एक विधि लागू करें जिनकी आपको क्रमबद्ध आवश्यकता हो सकती है। यह एक जादू की विधि है demjson, लेकिन यह संभवत: कुछ ऐसा है जो आप इस बारे में सोचना चाहते हैं कि आप किस कार्यान्वयन को चुनते हैं। विचार यह है कि आप एक ऐसी वस्तु लौटाते हैं जो सीधे रूप में परिवर्तनीय होती है json(जैसे कि एक सरणी या शब्दकोश)। यदि आप वास्तव में यह स्वचालित रूप से करना चाहते हैं:

def json_equivalent(self):
    dictionary = {}
    for field in self._meta.get_all_field_names()
        dictionary[field] = self.__getattribute__(field)
    return dictionary

यह आपके लिए तब तक मददगार नहीं होगा जब तक कि आपके पास पूरी तरह से फ्लैट डेटा संरचना न हो ForeignKeys डेटाबेस में संख्या, केवल संख्या और तार आदि)। अन्यथा, आपको इस पद्धति को लागू करने के सही तरीके के बारे में गंभीरता से सोचना चाहिए।

तीसरा, कॉल करें demjson.JSON.encode(instance)और आपके पास जो आप चाहते हैं।


मैंने अभी तक कोड की कोशिश नहीं की है, लेकिन मैं इसमें कुछ त्रुटियां बताना चाहता हूं। यह उदाहरण है ।_meta.get_all_field_names () और गेटअटैब एक फ़ंक्शन है इसलिए इसमें () और नहीं [] होना चाहिए।
जेसन क्रिस्टा

FK के अतिरिक्त, यह डेटाइम फ़ील्ड्स के लिए काम नहीं करेगा (जब तक कि demjson.JSON.encode में जादू न हो)
Skylar Saveland

8

यदि आप पूछ रहे हैं कि किसी मॉडल से किसी एकल ऑब्जेक्ट को कैसे अनुक्रमित किया जाए और आप जानते हैं कि आप क्वेरी में केवल एक ऑब्जेक्ट प्राप्त करने जा रहे हैं (उदाहरण के लिए, ऑब्जेक्ट का उपयोग करते हुए), तो कुछ का उपयोग करें:

import django.core.serializers
import django.http
import models

def jsonExample(request,poll_id):
    s = django.core.serializers.serialize('json',[models.Poll.objects.get(id=poll_id)])
    # s is a string with [] around it, so strip them off
    o=s.strip("[]")
    return django.http.HttpResponse(o, mimetype="application/json")

जो आपको फार्म का कुछ मिलेगा:

{"pk": 1, "model": "polls.poll", "fields": {"pub_date": "2013-06-27T02:29:38.284Z", "question": "What's up?"}}

लेकिन वह सभी वर्ग कोष्ठक को छीन लेगा, न कि केवल बाहर वाले को। बेहतर? "ओ = एस [1: -1]"?
जूलियन

5

मैंने अपने मॉडल में क्रमांकन विधि जोड़कर इस समस्या को हल किया:

def toJSON(self):
    import simplejson
    return simplejson.dumps(dict([(attr, getattr(self, attr)) for attr in [f.name for f in self._meta.fields]]))

यहाँ एक-लाइनर्स के लिए उन लोगों के लिए वर्बोज़ समकक्ष है:

def toJSON(self):
    fields = []
    for field in self._meta.fields:
        fields.append(field.name)

    d = {}
    for attr in fields:
        d[attr] = getattr(self, attr)

    import simplejson
    return simplejson.dumps(d)

_meta.fields मॉडल फ़ील्ड्स की एक आदेशित सूची है जिसे इंस्टेंस से और मॉडल से ही एक्सेस किया जा सकता है।


3
हालाँकि यह विचार पहली बार में अच्छा लग सकता है, फिर भी किसी को यह संकेत देना चाहिए कि इस दृष्टिकोण का उपयोग करने के परिणाम हैं। आप अपने मॉडल में एक विशिष्ट क्रमांकन आउटपुट बांध रहे हैं।
जोनास गीयरगेट

@JonasGeiregat चूंकि यह पद्धति मॉडल-से-मॉडल के आधार पर परिभाषित की गई है, दृष्टिकोण में क्या गलत है? अफसोस की बात यह है कि यह एक ऐसी एकमात्र वस्तु है जो किसी ऐसी वस्तु को लौटाने का एकमात्र तरीका है जिसमें क्षेत्र और उदाहरण की प्राथमिक कुंजी दोनों शामिल हैं।
डोपाट्रमण '

5

इसके लिए यहां मेरा समाधान है, जो आपको JSON को आसानी से अनुकूलित करने के साथ-साथ संबंधित रिकॉर्ड को व्यवस्थित करने की अनुमति देता है

सबसे पहले मॉडल पर एक विधि लागू करें। मैं फोन कर रहा हूं, jsonलेकिन आप जो चाहें उसे कॉल कर सकते हैं, जैसे:

class Car(Model):
    ...
    def json(self):
        return {
            'manufacturer': self.manufacturer.name,
            'model': self.model,
            'colors': [color.json for color in self.colors.all()],
        }

फिर मेरे विचार में:

data = [car.json for car in Car.objects.all()]
return HttpResponse(json.dumps(data), content_type='application/json; charset=UTF-8', status=status)

पायथन 3 में, यह बन जाता हैcar.json()
टी.काउटलकिस

4

सूची का उपयोग करें, यह समस्या को हल करेगा

चरण 1:

 result=YOUR_MODELE_NAME.objects.values('PROP1','PROP2').all();

चरण 2:

 result=list(result)  #after getting data from model convert result to list

चरण 3:

 return HttpResponse(json.dumps(result), content_type = "application/json")

ऐसा लगता है कि यह अभी भी एक वस्तु (नहीं) ऑब्जेक्ट के रूप में एक नग्न वस्तु के रूप में क्रमबद्ध करेगा, जो ओपी के बारे में पूछा गया है। iow, यह नियमित क्रमबद्ध विधि से अलग नहीं है।
जूलियन

1
यह JSON क्रमांकन त्रुटि के साथ विफल हो जाएगा। प्रश्नकाल की वस्तुएं क्रमिक नहीं हैं
डोपाट्रमण

4

क्रमबद्ध और deserialze करने के लिए, निम्नलिखित का उपयोग करें:

from django.core import serializers

serial = serializers.serialize("json", [obj])
...
# .next() pulls the first object out of the generator
# .object retrieves django object the object from the DeserializedObject
obj = next(serializers.deserialize("json", serial)).object

मुझे 'जेनरेटर ऑब्जेक्ट' की कोई विशेषता नहीं मिल रही है। कोई उपाय?
user2880391

1
@ user2880391 मैंने इसे पायथन 3 के लिए अपडेट किया है। क्या यह इसे ठीक करता है?
जग्स

4

.values() एक मॉडल उदाहरण को JSON में बदलने के लिए मुझे क्या चाहिए।

.values ​​() प्रलेखन: https://docs.djangoproject.com/en/3.0/ref/models/querysets/#values

प्रोजेक्ट नामक मॉडल के साथ उदाहरण उपयोग ।

नोट: मैं Django रेस्ट फ्रेमवर्क का उपयोग कर रहा हूं

    @csrf_exempt
    @api_view(["GET"])
    def get_project(request):
        id = request.query_params['id']
        data = Project.objects.filter(id=id).values()
        if len(data) == 0:
            return JsonResponse(status=404, data={'message': 'Project with id {} not found.'.format(id)})
        return JsonResponse(data[0])

मान्य आईडी से परिणाम:

{
    "id": 47,
    "title": "Project Name",
    "description": "",
    "created_at": "2020-01-21T18:13:49.693Z",
}

3

यदि आप एकल मॉडल ऑब्जेक्ट को क्लाइंट की प्रतिक्रिया के रूप में वापस करना चाहते हैं , तो आप यह सरल समाधान कर सकते हैं:

from django.forms.models import model_to_dict
from django.http import JsonResponse

movie = Movie.objects.get(pk=1)
return JsonResponse(model_to_dict(movie))

2

प्रारूप के साथ Django सीरियल का उपयोग करें python,

from django.core import serializers

qs = SomeModel.objects.all()
serialized_obj = serializers.serialize('python', qs)

jsonऔर pythonप्रारूप के बीच क्या अंतर है ?

jsonप्रारूप परिणाम के रूप में वापस आ जाएगी str, जबकि pythonमें परिणाम वापस आ जाएगी या तो listयाOrderedDict


यह बहुत दुर्भाग्यपूर्ण है
JPG

मुझे मिलता है OrderedDict, नहींdict
user66081

1

ऐसा नहीं लगता कि आप किसी उदाहरण को क्रमबद्ध कर सकते हैं, आपको एक वस्तु की एक क्वेरी को क्रमबद्ध करना होगा।

from django.core import serializers
from models import *

def getUser(request):
    return HttpResponse(json(Users.objects.filter(id=88)))

मैं svndjango के रिलीज से बाहर चला गया , इसलिए यह पहले के संस्करणों में नहीं हो सकता है।


1
ville = UneVille.objects.get(nom='lihlihlihlih')
....
blablablab
.......

return HttpResponse(simplejson.dumps(ville.__dict__))

मैं अपनी मिसाल पर वापस लौटता हूं

इसलिए यह {'फ़ील्ड 1': मान, "फ़ील्ड 2": मान, ....} जैसे कुछ लौटाता है


यह टूट जाएगा:TypeError: <django.db.models.base.ModelState object at 0x7f2b3bf62310> is not JSON serializable
Julio Marins

1

इस तरह से कैसे:

def ins2dic(obj):
    SubDic = obj.__dict__
    del SubDic['id']
    del SubDic['_state']
return SubDic

या जो कुछ भी आप नहीं चाहते हैं उसे बाहर करें।


0

इन सभी उत्तरों की तुलना में मैं एक फ्रेमवर्क से जो उम्मीद कर रहा था, उसकी तुलना में थोड़ी हैकरी थी, सबसे आसान तरीका, मुझे लगता है कि यदि आप बाकी ढांचे का उपयोग कर रहे हैं, तो:

rep = YourSerializerClass().to_representation(your_instance)
json.dumps(rep)

यह सीधे Serializer का उपयोग करता है, आपके द्वारा इस पर परिभाषित किए गए क्षेत्रों और साथ ही किसी भी संघ आदि का सम्मान करते हुए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.