Django Model nesnesini, tüm alanları olduğu gibi dikecek şekilde dönüştürün


258

Nasıl bir Django Model nesnesi tüm alanları ile bir dikteye dönüştürür ? İdeal olarak yabancı anahtarları ve alanları içerir editable=False.

Açıklayayım. Diyelim ki aşağıdaki gibi bir Django modelim var:

from django.db import models

class OtherModel(models.Model): pass

class SomeModel(models.Model):
    normal_value = models.IntegerField()
    readonly_value = models.IntegerField(editable=False)
    auto_now_add = models.DateTimeField(auto_now_add=True)
    foreign_key = models.ForeignKey(OtherModel, related_name="ref1")
    many_to_many = models.ManyToManyField(OtherModel, related_name="ref2")

Terminalde aşağıdakileri yaptım:

other_model = OtherModel()
other_model.save()
instance = SomeModel()
instance.normal_value = 1
instance.readonly_value = 2
instance.foreign_key = other_model
instance.save()
instance.many_to_many.add(other_model)
instance.save()

Bunu aşağıdaki sözlüğe dönüştürmek istiyorum:

{'auto_now_add': datetime.datetime(2015, 3, 16, 21, 34, 14, 926738, tzinfo=<UTC>),
 'foreign_key': 1,
 'id': 1,
 'many_to_many': [1],
 'normal_value': 1,
 'readonly_value': 2}

Tatmin edici cevapları olmayan sorular:

Django: Bir Modelin tüm nesnelerini tek bir sözlüğe dönüştürme

Django Model nesnelerini nasıl sözlüğe çevirebilir ve yabancı anahtarlarına sahip olabilirim?


1
denilen bir yöntemi bildirebilir to_dictve istediğiniz gibi işleyebilirsiniz.
karthikr

@karthikr evet, yapabilirim. Soru, böyle bir yöntemin nasıl oluşturulacağıdır. Modelin tüm alanlarından manuel olarak sözlük oluşturmak uygun bir cevap değildir.
Zags

Django Rest Framework, Tastypie veya Piston gibi mevcut bir ReST kitaplığından yararlanacaktım çünkü hepsi django model örneklerini serileştirme için ilkellere dönüştürmek için mekanizmalar sağlıyor. Nasıl olduğunu merak ediyorsanız, kodlarına bakabilirsiniz, ancak çoğunlukla modelin_meta ilişkili alanları bulmak ve örnek üzerindeki değerlerini almak için tanımlarını gözden .
Kevin Stone

Yanıtlar:


527

Bir örneği sözlüğe dönüştürmenin birçok yolu vardır, değişen derecelerde köşe vaka işleme ve istenen sonuca yakınlık.


1. instance.__dict__

instance.__dict__

hangisi geri döner

{'_foreign_key_cache': <OtherModel: OtherModel object>,
 '_state': <django.db.models.base.ModelState at 0x7ff0993f6908>,
 'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
 'foreign_key_id': 2,
 'id': 1,
 'normal_value': 1,
 'readonly_value': 2}

Bu çok basit, ama eksik many_to_many, foreign_keyyanlış adlandırılmış ve içinde istenmeyen iki ekstra şey var.


2. model_to_dict

from django.forms.models import model_to_dict
model_to_dict(instance)

hangisi geri döner

{'foreign_key': 2,
 'id': 1,
 'many_to_many': [<OtherModel: OtherModel object>],
 'normal_value': 1}

Bu sadece many_to_many düzenlenemeyen , ancak düzenlenemeyen alanlar eksik.


3. model_to_dict(..., fields=...)

from django.forms.models import model_to_dict
model_to_dict(instance, fields=[field.name for field in instance._meta.fields])

hangisi geri döner

{'foreign_key': 2, 'id': 1, 'normal_value': 1}

Bu kesinlikle standarttan daha kötü model_to_dict çağrıdan .


4. query_set.values()

SomeModel.objects.filter(id=instance.id).values()[0]

hangisi geri döner

{'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
 'foreign_key_id': 2,
 'id': 1,
 'normal_value': 1,
 'readonly_value': 2}

Bu, instance.__dict__ek alanlar olmadan aynı çıktıdır . foreign_key_idhala yanlış ve many_to_manyhala eksik.


5. Özel Fonksiyon

Django'nun kodu model_to_dictcevabın çoğuna sahipti. Düzenlenemeyen alanları açıkça kaldırdı, bu nedenle bu kontrolü kaldırmak ve yabancı anahtarların kimliğini birçok alana almak, istendiği gibi davranan aşağıdaki kodla sonuçlanır:

from itertools import chain

def to_dict(instance):
    opts = instance._meta
    data = {}
    for f in chain(opts.concrete_fields, opts.private_fields):
        data[f.name] = f.value_from_object(instance)
    for f in opts.many_to_many:
        data[f.name] = [i.id for i in f.value_from_object(instance)]
    return data

Bu en karmaşık seçenek olsa da, çağrı yapmak to_dict(instance)bize tam olarak istenen sonucu verir:

{'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
 'foreign_key': 2,
 'id': 1,
 'many_to_many': [2],
 'normal_value': 1,
 'readonly_value': 2}

6. Serileştiricileri Kullan

Django Rest Framework'ün ModelSerialzer'ı bir modelden otomatik olarak bir serileştirici oluşturmanıza izin verir.

from rest_framework import serializers
class SomeModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = SomeModel
        fields = "__all__"

SomeModelSerializer(instance).data

İadeler

{'auto_now_add': '2018-12-20T21:34:29.494827Z',
 'foreign_key': 2,
 'id': 1,
 'many_to_many': [2],
 'normal_value': 1,
 'readonly_value': 2}

Bu neredeyse özel işlev kadar iyidir, ancak auto_now_add datetime nesnesi yerine bir dizedir.


Bonus Turu: daha iyi model baskısı

Daha iyi bir python komut satırı görüntüsüne sahip bir django modeli istiyorsanız, modellerinizin alt sınıfı olmasını sağlayın:

from django.db import models
from itertools import chain

class PrintableModel(models.Model):
    def __repr__(self):
        return str(self.to_dict())

    def to_dict(instance):
        opts = instance._meta
        data = {}
        for f in chain(opts.concrete_fields, opts.private_fields):
            data[f.name] = f.value_from_object(instance)
        for f in opts.many_to_many:
            data[f.name] = [i.id for i in f.value_from_object(instance)]
        return data

    class Meta:
        abstract = True

Örneğin, modellerimizi böyle tanımlarsak:

class OtherModel(PrintableModel): pass

class SomeModel(PrintableModel):
    normal_value = models.IntegerField()
    readonly_value = models.IntegerField(editable=False)
    auto_now_add = models.DateTimeField(auto_now_add=True)
    foreign_key = models.ForeignKey(OtherModel, related_name="ref1")
    many_to_many = models.ManyToManyField(OtherModel, related_name="ref2")

SomeModel.objects.first()Şimdi çağrı yapmak şöyle çıktı verir:

{'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
 'foreign_key': 2,
 'id': 1,
 'many_to_many': [2],
 'normal_value': 1,
 'readonly_value': 2}

2
Bu cevap için teşekkürler! isinstanceÇözüm # 5 (ve bonus) içindeki testi olarak değiştirebilirsiniz if f.many_to_many.
20'de dhobbs

1
@dhobbs Ben Django'nın kapalı bu kodu modellenmiş model_to_dicthangi kullandığı kod, isinstance. Neden bu seçimi yaptıklarından emin değilim ( many_to_manybunun daha sonraki bir sürümde tanıtılması gibi) için iyi bir neden olabilir
Zags

@propertyalanları da döndürür mü?
18'de angrysumit

1
Acaba bu yöntemler açıklamalı / birleştirilmiş alanlara nasıl davranır?
mehmet

Yaptığım bir şey get_FOO_display için kontrol ve aslında orada herhangi bir değer yerine bu değeri döndürmektir.
Bobort

9

Sonuç almak için düzgün bir çözüm buldum:

Bir model nesneniz olduğunu varsayalım o :

Sadece ara:

type(o).objects.filter(pk=o.pk).values().first()

10
Bu sadece
cevabımda

7

@Zags çözümü muhteşem oldu!

Yine de, JSON dostu yapmak için datefields için bir koşul eklemek istiyorum.

Bonus Turu

Daha iyi bir python komut satırı görüntüsüne sahip bir django modeli istiyorsanız, modellerinizin alt sınıfını aşağıdaki sınıflara getirin:

from django.db import models
from django.db.models.fields.related import ManyToManyField

class PrintableModel(models.Model):
    def __repr__(self):
        return str(self.to_dict())

    def to_dict(self):
        opts = self._meta
        data = {}
        for f in opts.concrete_fields + opts.many_to_many:
            if isinstance(f, ManyToManyField):
                if self.pk is None:
                    data[f.name] = []
                else:
                    data[f.name] = list(f.value_from_object(self).values_list('pk', flat=True))
            elif isinstance(f, DateTimeField):
                if f.value_from_object(self) is not None:
                    data[f.name] = f.value_from_object(self).timestamp()
            else:
                data[f.name] = None
            else:
                data[f.name] = f.value_from_object(self)
        return data

    class Meta:
        abstract = True

Örneğin, modellerimizi böyle tanımlarsak:

class OtherModel(PrintableModel): pass

class SomeModel(PrintableModel):
    value = models.IntegerField()
    value2 = models.IntegerField(editable=False)
    created = models.DateTimeField(auto_now_add=True)
    reference1 = models.ForeignKey(OtherModel, related_name="ref1")
    reference2 = models.ManyToManyField(OtherModel, related_name="ref2")

SomeModel.objects.first()Şimdi çağrı yapmak şöyle çıktı verir:

{'created': 1426552454.926738,
'value': 1, 'value2': 2, 'reference1': 1, u'id': 1, 'reference2': [1]}

JSON'a ve JSON'dan dönüştürmek istiyorsanız, Django Rest Framework'e bakmalı veya şöyle bir şey kullanmalısınız: stackoverflow.com/a/22238613/2800876
Zags

Elbette! Ancak kodunuzdaki bu küçük değişiklik büyük kolaylık sağlıyor!
Diego Freitas Coelho

4

En basit yol,

  1. Sorgunuz Model.Objects.get () ise:

    get (), tek bir örnek döndürür __dict__;

    model_dict = Model.Objects.get().__dict__

  2. için filtre () / Tüm ():

    all () / filter () , örnek listesini döndürür, böylece values()nesne listesini almak için kullanabilirsiniz .

    model_values ​​= Model.Objects.all (). değerler ()


4

sadece vars(obj)nesnenin tüm değerlerini ifade eder

>>> obj_attrs = vars(obj)
>>> obj_attrs
 {'_file_data_cache': <FileData: Data>,
  '_state': <django.db.models.base.ModelState at 0x7f5c6733bad0>,
  'aggregator_id': 24,
  'amount': 5.0,
  'biller_id': 23,
  'datetime': datetime.datetime(2018, 1, 31, 18, 43, 58, 933277, tzinfo=<UTC>),
  'file_data_id': 797719,
 }

Bunu da ekleyebilirsiniz

>>> keys = obj_attrs.keys()
>>> temp = [obj_attrs.pop(key) if key.startswith('_') else None for key in keys]
>>> del temp
>>> obj_attrs
   {
    'aggregator_id': 24,
    'amount': 5.0,
    'biller_id': 23,
    'datetime': datetime.datetime(2018, 1, 31, 18, 43, 58, 933277, tzinfo=<UTC>),
    'file_data_id': 797719,
   }

3

Güncelleme

@Zags tarafından gönderilen daha yeni toplu cevap, kendiminkinden daha eksiksiz ve zariftir. Lütfen bunun yerine bu cevaba bakınız.

orijinal

@Karthiker gibi kendi to_dict yönteminizi tanımlamak istiyorsanız, bu sadece bu sorunu bir set problemine indirir.

>>># Returns a set of all keys excluding editable = False keys
>>>dict = model_to_dict(instance)
>>>dict

{u'id': 1L, 'reference1': 1L, 'reference2': [1L], 'value': 1}


>>># Returns a set of editable = False keys, misnamed foreign keys, and normal keys
>>>otherDict = SomeModel.objects.filter(id=instance.id).values()[0]
>>>otherDict

{'created': datetime.datetime(2014, 2, 21, 4, 38, 51, tzinfo=<UTC>),
 u'id': 1L,
 'reference1_id': 1L,
 'value': 1L,
 'value2': 2L}

Yanlış etiketlenmiş yabancı anahtarları otherDict'ten kaldırmamız gerekiyor .

Bunu yapmak için, içinde alt çizgi olanlar hariç her öğeye sahip yeni bir sözlük yapan bir döngü kullanabiliriz. Ya da, zamandan kazanmak için, bunları sadece orijinal diksiyona ekleyebiliriz, çünkü sözlükler sadece başlık altında ayarlanır.

>>>for item in otherDict.items():
...    if "_" not in item[0]:
...            dict.update({item[0]:item[1]})
...
>>>

Böylece şu dikte kalıyoruz :

>>>dict
{'created': datetime.datetime(2014, 2, 21, 4, 38, 51, tzinfo=<UTC>),
 u'id': 1L,
 'reference1': 1L,
 'reference2': [1L],
 'value': 1,
 'value2': 2L}

Ve bunu geri ver.

Aşağı yönde, düzenlenebilir = yanlış alan adlarınızda alt çizgi kullanamazsınız. Yukarı tarafta, bu, kullanıcı tarafından oluşturulan alanların alt çizgi içermediği herhangi bir alan kümesi için çalışır.

Bunu yapmanın en iyi yolu bu değildir, ancak daha doğrudan bir yöntem bulunana kadar geçici bir çözüm olarak çalışabilir.

Aşağıdaki örnek için dict, model_to_dict temel alınarak oluşturulacak ve otherDict ise filtrenin değer yöntemi ile oluşturulacaktır. Bunu modellerin kendileriyle yapardım, ancak makinemin diğer modeli kabul etmesini sağlayamıyorum.

>>> import datetime
>>> dict = {u'id': 1, 'reference1': 1, 'reference2': [1], 'value': 1}
>>> otherDict = {'created': datetime.datetime(2014, 2, 21, 4, 38, 51), u'id': 1, 'reference1_id': 1, 'value': 1, 'value2': 2}
>>> for item in otherDict.items():
...     if "_" not in item[0]:
...             dict.update({item[0]:item[1]})
...
>>> dict
{'reference1': 1, 'created': datetime.datetime(2014, 2, 21, 4, 38, 51), 'value2': 2, 'value': 1, 'id': 1, 'reference2': [1]}
>>>

Bu sizi sorunuzun cevabının kaba bir basketbol sahasına koymalı, umarım.


1
reBurada ne kullanmaya çalıştığınızdan emin değilim . Anahtarları altçizgileriyle filtrelemekse, bu ne doğru kod ne de doğru davranıştır. veritabanındaki re.match("_", "reference1_id")döndürme Noneve meşru sütunların adlarında alt çizgi olabilir.
Zags

re.match ("_", "reference1_id") Hiçbiri döndürmez, şöyle olmalıydı: re.match (". * _. *", "reference1_id")
Gadget

Kötü örneği kaldırmak ve daha iyi bir örnek eklemek için bazı değişiklikler yaptım. Ayrıca bazı şeyleri değiştirerek bunun tüm modellerin bir alt kümesi için geçici bir çözüm olacağını ifade ettim. editable=falseAlanlarında alt çizgi olan modeller için ne yapacağınız hakkında hiçbir fikrim yok . Sadece daha fazla kanon çözümü sağlanana kadar birlikte çalışabileceğiniz bir şey sağlamaya çalışıyordum.
Gadget

Belki de bu durumda kullanmak "_" in stringyerine re.
Zags

Evet, bunu yapmanın çok daha kolay bir yolu olurdu. Bu şekilde kullanmak benim başıma gelmemişti, ama şimdi gayet mantıklı. Bunun inyerine kullanılacak cevabı değiştirdim re.
Gadget

2

Burada bir sürü ilginç çözüm var. Benim çözümüm, dikte bir anlayışla modelime bir as_dict yöntemi eklemekti.

def as_dict(self):
    return dict((f.name, getattr(self, f.name)) for f in self._meta.fields)

Bonus olarak, bir sorgu üzerinde bir liste kavrayışı ile eşleştirilmiş bu çözüm, modellerinizi başka bir kütüphaneye aktarmak istiyorsanız güzel bir çözüm sağlar. Örneğin, modellerinizi panda veri çerçevesine dökmek:

pandas_awesomeness = pd.DataFrame([m.as_dict() for m in SomeModel.objects.all()])

1
Bu, dizeler ve ints gibi değer alanları için iyi çalışır, ancak yabancı anahtarlarla ilgili bazı problemler ve daha birçok alanla ilgili daha fazla sorun yaşayacaktır
Zags

Çok iyi bir nokta! Özellikle çoktan çoğa. Bu durumları uygun bir şekilde ele almak için bazı şartlar koymak ya da bu çözümü basit modellerle sınırlamak ister. Teşekkürler.
t1m0

1

(yorum yapmak istemiyordu)

Tamam, bu türlere gerçekten bağlı değil. Buradaki orijinal soruyu yanlış anlamış olabilirim, bu durumda beni affet. Serliazers.py oluşturursanız, orada meta sınıfları olan sınıflar yaratırsınız.

Class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = modelName
        fields =('csv','of','fields')

Sonra görünüm sınıfındaki verileri aldığınızda şunları yapabilirsiniz:

model_data - Model.objects.filter(...)
serializer = MyModelSerializer(model_data, many=True)
return Response({'data': serilaizer.data}, status=status.HTTP_200_OK)

Oldukça fazla yerlerde çok şey var ve güzel JSON JSONRenderer üzerinden döner.

Dediğim gibi bu DjangoRestFramework izniyle bu yüzden buna değer.


1

Daha kolay yol, sadece pprintPython'da bulunan kullanmaktır

import pprint
item = MyDjangoModel.objects.get(name = 'foo')
pprint.pprint(item.__dict__, indent = 4)

Bu, şuna benzer bir çıktı sağlar, json.dumps(..., indent = 4)ancak model örneğinize gömülebilecek garip veri türlerini doğru bir şekilde işler ModelStateveUUID vb

Python 3.7 üzerinde test edildi


0

Belki bu sana yardım eder. Bu, pek çok ilişkiyi gizlemeyebilir, ancak modelinizi json formatında göndermek istediğinizde oldukça kullanışlı olabilir.

def serial_model(modelobj):
  opts = modelobj._meta.fields
  modeldict = model_to_dict(modelobj)
  for m in opts:
    if m.is_relation:
        foreignkey = getattr(modelobj, m.name)
        if foreignkey:
            try:
                modeldict[m.name] = serial_model(foreignkey)
            except:
                pass
  return modeldict

0

Şimdiye kadar gördüğünüz en iyi çözüm.

Django.db.models.Model örneğini ve ilgili tüm ForeignKey, ManyToManyField ve @Property işlev alanlarını dikteye dönüştürün.

"""
Convert django.db.models.Model instance and all related ForeignKey, ManyToManyField and @property function fields into dict.
Usage:
    class MyDjangoModel(... PrintableModel):
        to_dict_fields = (...)
        to_dict_exclude = (...)
        ...
    a_dict = [inst.to_dict(fields=..., exclude=...) for inst in MyDjangoModel.objects.all()]
"""
import typing

import django.core.exceptions
import django.db.models
import django.forms.models


def get_decorators_dir(cls, exclude: typing.Optional[set]=None) -> set:
    """
    Ref: /programming/4930414/how-can-i-introspect-properties-and-model-fields-in-django
    :param exclude: set or None
    :param cls:
    :return: a set of decorators
    """
    default_exclude = {"pk", "objects"}
    if not exclude:
        exclude = default_exclude
    else:
        exclude = exclude.union(default_exclude)

    return set([name for name in dir(cls) if name not in exclude and isinstance(getattr(cls, name), property)])


class PrintableModel(django.db.models.Model):

    class Meta:
        abstract = True

    def __repr__(self):
        return str(self.to_dict())

    def to_dict(self, fields: typing.Optional[typing.Iterable]=None, exclude: typing.Optional[typing.Iterable]=None):
        opts = self._meta
        data = {}

        # support fields filters and excludes
        if not fields:
            fields = set()
        else:
            fields = set(fields)
        default_fields = getattr(self, "to_dict_fields", set())
        fields = fields.union(default_fields)

        if not exclude:
            exclude = set()
        else:
            exclude = set(exclude)
        default_exclude = getattr(self, "to_dict_exclude", set())
        exclude = exclude.union(default_exclude)

        # support syntax "field__childField__..."
        self_fields = set()
        child_fields = dict()
        if fields:
            for i in fields:
                splits = i.split("__")
                if len(splits) == 1:
                    self_fields.add(splits[0])
                else:
                    self_fields.add(splits[0])

                    field_name = splits[0]
                    child_fields.setdefault(field_name, set())
                    child_fields[field_name].add("__".join(splits[1:]))

        self_exclude = set()
        child_exclude = dict()
        if exclude:
            for i in exclude:
                splits = i.split("__")
                if len(splits) == 1:
                    self_exclude.add(splits[0])
                else:
                    field_name = splits[0]
                    if field_name not in child_exclude:
                        child_exclude[field_name] = set()
                    child_exclude[field_name].add("__".join(splits[1:]))

        for f in opts.concrete_fields + opts.many_to_many:
            if self_fields and f.name not in self_fields:
                continue
            if self_exclude and f.name in self_exclude:
                continue

            if isinstance(f, django.db.models.ManyToManyField):
                if self.pk is None:
                    data[f.name] = []
                else:
                    result = []
                    m2m_inst = f.value_from_object(self)
                    for obj in m2m_inst:
                        if isinstance(PrintableModel, obj) and hasattr(obj, "to_dict"):
                            d = obj.to_dict(
                                fields=child_fields.get(f.name),
                                exclude=child_exclude.get(f.name),
                            )
                        else:
                            d = django.forms.models.model_to_dict(
                                obj,
                                fields=child_fields.get(f.name),
                                exclude=child_exclude.get(f.name)
                            )
                        result.append(d)
                    data[f.name] = result
            elif isinstance(f, django.db.models.ForeignKey):
                if self.pk is None:
                    data[f.name] = []
                else:
                    data[f.name] = None
                    try:
                        foreign_inst = getattr(self, f.name)
                    except django.core.exceptions.ObjectDoesNotExist:
                        pass
                    else:
                        if isinstance(foreign_inst, PrintableModel) and hasattr(foreign_inst, "to_dict"):
                            data[f.name] = foreign_inst.to_dict(
                                fields=child_fields.get(f.name),
                                exclude=child_exclude.get(f.name)
                            )
                        elif foreign_inst is not None:
                            data[f.name] = django.forms.models.model_to_dict(
                                foreign_inst,
                                fields=child_fields.get(f.name),
                                exclude=child_exclude.get(f.name),
                            )

            elif isinstance(f, (django.db.models.DateTimeField, django.db.models.DateField)):
                v = f.value_from_object(self)
                if v is not None:
                    data[f.name] = v.isoformat()
                else:
                    data[f.name] = None
            else:
                data[f.name] = f.value_from_object(self)

        # support @property decorator functions
        decorator_names = get_decorators_dir(self.__class__)
        for name in decorator_names:
            if self_fields and name not in self_fields:
                continue
            if self_exclude and name in self_exclude:
                continue

            value = getattr(self, name)
            if isinstance(value, PrintableModel) and hasattr(value, "to_dict"):
                data[name] = value.to_dict(
                    fields=child_fields.get(name),
                    exclude=child_exclude.get(name)
                )
            elif hasattr(value, "_meta"):
                # make sure it is a instance of django.db.models.fields.Field
                data[name] = django.forms.models.model_to_dict(
                    value,
                    fields=child_fields.get(name),
                    exclude=child_exclude.get(name),
                )
            elif isinstance(value, (set, )):
                data[name] = list(value)
            else:
                data[name] = value

        return data

https://gist.github.com/shuge/f543dc2094a3183f69488df2bfb51a52


0

@Zags gelen cevap kapsamlı ve yeterli ama # 5 yöntemi (ki en iyi bir IMO) bir hata atar, bu yüzden yardımcı işlevini geliştirdi.

OP, many_to_manyalanları bir nesne listesi yerine birincil anahtarlar listesine dönüştürmek istediğinden , dönüş değerini artık JSON serileştirilebilir hale getirdim - datetimenesneleri strve many_to_manynesnelerini bir kimlik listesine dönüştürerek .

import datetime

def ModelToDict(instance):
    '''
    Returns a dictionary object containing complete field-value pairs of the given instance

    Convertion rules:

        datetime.date --> str
        many_to_many --> list of id's

    '''

    concrete_fields = instance._meta.concrete_fields
    m2m_fields = instance._meta.many_to_many
    data = {}

    for field in concrete_fields:
        key = field.name
        value = field.value_from_object(instance)
        if type(value) == datetime.datetime:
            value = str(field.value_from_object(instance))
        data[key] = value

    for field in m2m_fields:
        key = field.name
        value = field.value_from_object(instance)
        data[key] = [rel.id for rel in value]

    return data

Aldığınız hata nedir? Cevabı güncellemekten mutluluk duyuyorum
Zags

Şu anda döngülerin işlevselliği concrete_fieldsve m2m_fieldsözdeş görünmek, bu yüzden m2m_fieldsdöngü burada yanlış bir uygulama var varsayalım.
Daniel Himmelstein

@Zags hatası AttributeError: 'list' object has no attribute 'values_list' arkasındaki nedeni bulamadığım . Django 2.1.1 kullanıyorum
Armin Hemati Nik

@ daniel-himmelstein işaret ettiğiniz için teşekkür ederim, kodu düzelttim. özdeş döngülerin nedeni yerel kodumda farklı işlemler gerçekleştirmekten kaynaklanıyordu ve SO cevabı için optimize etmeyi unuttum.
Armin Hemati Nik

@ArminHemati Django, uygulamasının field.value_from_objectve bunun sonucunda değiştirildi model_to_dict. Cevabımın 5. bölümünü bunu yansıtacak şekilde güncelledim.
Zags
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.