มีเอกสารจำนวนมากเกี่ยวกับวิธีการทำให้อนุกรม QuerySet เป็นแบบอนุกรม แต่คุณจะทำอนุกรมให้ JSON เป็นเขตข้อมูลของ Model Instance ได้อย่างไร
มีเอกสารจำนวนมากเกี่ยวกับวิธีการทำให้อนุกรม QuerySet เป็นแบบอนุกรม แต่คุณจะทำอนุกรมให้ JSON เป็นเขตข้อมูลของ Model Instance ได้อย่างไร
คำตอบ:
คุณสามารถใช้รายการเพื่อห่อวัตถุที่ต้องการและนั่นคือสิ่งที่ django serializers จำเป็นต้องทำให้เป็นอนุกรมอย่างถูกต้องเช่น:
from django.core import serializers
# assuming obj is a model instance
serialized_obj = serializers.serialize('json', [ obj, ])
[0]
ที่จุดสิ้นสุดของบรรทัดสุดท้ายของคุณเช่น @DavorLucic ที่แนะนำ? และไม่จำเป็นต้องใช้เครื่องหมายจุลภาคต่อท้ายในรายการตัวอักษรของคุณ (สำหรับความรักของ PEP8;)
หากคุณกำลังจัดการกับรายการของอินสแตนซ์รุ่นที่ดีที่สุดที่คุณสามารถทำได้คือใช้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
โทรหาหนึ่งหมายเลขโดยตรงเพื่อทำให้เป็นอนุกรมเพื่อ json:
import json
serialized = json.dumps(dict_obj)
แค่นั้นแหละ! :)
datetime
เขตข้อมูล แก้ไขด้วยวิธีนี้json.loads(serialize('json', [obj]))[0]
ในขณะที่ serializer คือdjango.core.serializers.serialize
เพื่อหลีกเลี่ยง wrapper อาร์เรย์ให้ลบออกก่อนที่คุณจะตอบกลับ:
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 ซึ่งดูเหมือนว่าเป็นเครื่องมือที่สมบูรณ์แบบสำหรับงาน
มีคำตอบที่ดีสำหรับเรื่องนี้และฉันประหลาดใจที่ไม่ได้พูดถึง ด้วยสองสามบรรทัดคุณสามารถจัดการวันที่รุ่นและทุกอย่างอื่นได้
สร้างตัวเข้ารหัสแบบกำหนดเองที่สามารถจัดการกับโมเดลได้:
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
เมธอดได้
คุณสามารถใช้ JsonResponse ของ Django ได้ด้วยวิธีนี้:
from django.http import JsonResponse
JsonResponse(data, encoder=ExtendedEncoder)
``
json.dumps
และjson.dump
วิธีการ วิธีนี้คุณไม่จำเป็นต้องเปลี่ยนเวิร์กโฟลว์ของแอปพลิเคชันเนื่องจากคุณใช้วัตถุที่กำหนดเองหรือเพิ่มการเรียกใช้เมธอดอื่นก่อนที่จะแปลงเป็น json เพียงเพิ่มรหัสการแปลงของคุณในโปรแกรมเปลี่ยนไฟล์และคุณก็พร้อมที่จะไป
ดูเหมือนสิ่งที่คุณถามเกี่ยวกับการทำให้โครงสร้างข้อมูลของอินสแตนซ์ของ Django เป็นอนุกรมสำหรับการทำงานร่วมกัน ผู้โพสต์อื่น ๆ นั้นถูกต้อง: หากคุณต้องการให้แบบฟอร์มต่อเนื่องนั้นใช้กับแอพพลิเคชั่นหลามที่สามารถสืบค้นฐานข้อมูลผ่าน API ของ 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)
และคุณมีสิ่งที่คุณต้องการ
หากคุณกำลังถามวิธีการทำให้เป็นอนุกรมวัตถุเดียวจากแบบจำลองและคุณรู้ว่าคุณจะได้รับหนึ่งวัตถุในชุดการสืบค้น (ตัวอย่างเช่นการใช้ objects.get) จากนั้นใช้สิ่งต่อไปนี้:
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?"}}
ฉันแก้ไขปัญหานี้โดยการเพิ่มวิธีการทำให้เป็นอนุกรมในโมเดลของฉัน:
def toJSON(self):
import simplejson
return simplejson.dumps(dict([(attr, getattr(self, attr)) for attr in [f.name for f in self._meta.fields]]))
นี่คือ verbose ที่เทียบเท่ากับสิ่งที่เกลียดชังผู้หนึ่งตอร์ปิโด:
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
คือรายการที่เรียงลำดับแล้วของฟิลด์โมเดลซึ่งสามารถเข้าถึงได้จากอินสแตนซ์และจากโมเดลเอง
นี่คือโซลูชันของฉันสำหรับสิ่งนี้ซึ่งช่วยให้คุณสามารถปรับแต่ง 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)
car.json()
ใช้รายการมันจะแก้ปัญหา
ขั้นตอนที่ 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")
ในการทำให้เป็นอันดับและปล่อยให้ใช้ต่อไปนี้:
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
.values()
คือสิ่งที่ฉันต้องการในการแปลงอินสแตนซ์โมเดลเป็น JSON
.values () เอกสารประกอบ: https://docs.djangoproject.com/en/3.0/ref/models/querysets/#values
ตัวอย่างการใช้งานที่มีรูปแบบที่เรียกว่าโครงการ
หมายเหตุ: ฉันใช้ Django Rest Framework
@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",
}
หากคุณต้องการส่งคืนโมเดลวัตถุเดียวเป็นการตอบสนอง jsonไปยังไคลเอนต์คุณสามารถทำวิธีแก้ปัญหาง่ายๆนี้ได้:
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))
python
รูปแบบfrom django.core import serializers
qs = SomeModel.objects.all()
serialized_obj = serializers.serialize('python', qs)
json
และpython
รูปแบบคืออะไรjson
รูปแบบจะกลับมาเป็นผลstr
ในขณะที่python
จะกลับผลทั้งในlist
หรือOrderedDict
OrderedDict
ไม่ใช่dict
ดูเหมือนว่าคุณจะไม่สามารถทำให้เป็นอินสแตนซ์เป็นอนุกรมได้คุณต้องทำให้เป็น QuerySet ของวัตถุหนึ่งชิ้น
from django.core import serializers
from models import *
def getUser(request):
return HttpResponse(json(Users.objects.filter(id=88)))
ฉันหมดsvn
รุ่นของ django ดังนั้นนี่อาจไม่ใช่เวอร์ชั่นก่อนหน้า
ville = UneVille.objects.get(nom='lihlihlihlih')
....
blablablab
.......
return HttpResponse(simplejson.dumps(ville.__dict__))
ฉันกลับคำสั่งอินสแตนซ์ของฉัน
ดังนั้นจึงส่งกลับบางสิ่งเช่น {'field1': value, "field2": value, .... }
TypeError: <django.db.models.base.ModelState object at 0x7f2b3bf62310> is not JSON serializable
วิธีการเกี่ยวกับวิธีนี้:
def ins2dic(obj):
SubDic = obj.__dict__
del SubDic['id']
del SubDic['_state']
return SubDic
หรือยกเว้นสิ่งที่คุณไม่ต้องการ
คำตอบทั้งหมดเหล่านี้ค่อนข้างแฮ็คเล็กน้อยเมื่อเทียบกับสิ่งที่ฉันคาดหวังจากกรอบวิธีที่ง่ายที่สุดที่ฉันคิดว่าถ้าคุณใช้กรอบงานที่เหลือ:
rep = YourSerializerClass().to_representation(your_instance)
json.dumps(rep)
สิ่งนี้ใช้ Serializer โดยตรงเคารพฟิลด์ที่คุณกำหนดไว้เช่นเดียวกับการเชื่อมโยงใด ๆ ฯลฯ
django.core
การทำเช่นนี้ มีเหตุผลใดที่จะไม่ใช้ทำให้ชุดแบบสอบถามเป็นอนุกรมหรือไม่