Django modelプロローグをjsonにする方法の例


本論文の環境
  • Python 3.6.5
  • Django 2.0.4
  • fix(2018.5.19):最近Djangoのmodel基質がabstractであることがわかったので、元のコードにabstract声明を追加して、誤解を招かないようにします。
    Djangoでは、modelクラスをどのようにjsonに並べたらいいですか?一般的には2 aがあります。
    modelを辞書に変えて、jsonライブラリのdumpsを使ってjsonに変えます。
    第一の方法は多く言わないで、直接公式文書を見に行けばいいです。
    一般的には、政府が提供する方法は、より使いやすく、安定しているはずですが、公式のプログレッシブを使用することには問題が少なくありません。
    フォーマットが醜いです。フォーマットは次の通りです。一言では言い尽くせません。
    
    [
      {
        "pk": "4b678b301dfd8a4e0dad910de3ae245b",
        "model": "sessions.session",
        "fields": {
          "expire_date": "2013-01-16T08:16:59.844Z",
          ...
        }
      }
    ]
    はい、pkとはデフォルトのメインキーのことです。modelとはこのOB jectのmodelタイプのことです。そしてfieldsはobjの各フィールドです。本当に評価が分かりません。
  • はリスト
  • を上手くサポートできません。
  • はいくつかの外鍵(ManyToManyFieldなどを含む)に対してあまり友好的ではないです。
  • は自身のDateFieldに対してもあまり良くサポートされていません。
    公式プロブレザの欠点を数えました。もちろん上のいくつかの点には解決案があります。
    それで私の解決策を出しました。
  • 新しいクラスBasemodelを作成しました。このような種類はオフィシャルのmodel種類django.db.models.Model
  • を継承します。
  • は、BaseModelにおいて、このObjectに関する辞書
  • を生成するための方法を声明している。
  • このOBプロジェクトの辞書を使ってjson
  • を生成します。
    objectの辞書を生成する戦略については、以下の通りである。
  • は、反射によってこのobjectのすべてのフィールド名
  • を取得する。
  • フィールド名に基づいてフィールドfield
  • を取得する。
  • filedのタイプがint、float、strであれば、直接に「フィールド名」でフィールド値を辞書に入れます。
  • フィルドのタイプがdatetimeまたはdateであれば、dateで処理し、辞書
  • に入れる。
  • fieldのタイプがBaseModelであれば、fieldのgetDict方法を呼び出して、そのfieldに対応する辞書を再帰的に取得し、
  • に辞書に入れる。
  • フィルドのタイプはManyToManyタイプで、具体的な草の中で私達はこのfieldのall方法を使ってこのfieldのすべてのobjectを使って、そしてget Dict方法を通じて辞書の中に入れます。
    ソースと使い方
    
    from django.db import models
    import json
    
    
    class BaseModel(models.Model):
      class Meta:
        abstract = True
    
      #   self._meta.fields    ,             
      #   ['name','type']
      def getMtMField(self):
        pass
    
      #      json          
      #   ['password']
      def getIgnoreList(self):
        pass
    
      def isAttrInstance(self, attr, clazz):
        return isinstance(getattr(self, attr), clazz)
    
      def getDict(self):
        fields = []
        for field in self._meta.fields:
          fields.append(field.name)
    
        d = {}
        import datetime
        for attr in fields:
          if isinstance(getattr(self, attr), datetime.datetime):
            d[attr] = getattr(self, attr).strftime('%Y-%m-%d %H:%M:%S')
          elif isinstance(getattr(self, attr), datetime.date):
            d[attr] = getattr(self, attr).strftime('%Y-%m-%d')
          #     datetime   
          elif isinstance(getattr(self, attr), BaseModel):
            d[attr] = getattr(self, attr).getDict()
          #     BaseModel  dict
          elif self.isAttrInstance(attr, int) or self.isAttrInstance(attr, float) \
              or self.isAttrInstance(attr, str):
            d[attr] = getattr(self, attr)
          # else:
          #   d[attr] = getattr(self, attr)
    
        mAttr = self.getMtMField()
        if mAttr is not None:
          for m in mAttr:
            if hasattr(self, m):
              attlist = getattr(self, m).all()
              l = []
              for attr in attlist:
                if isinstance(attr, BaseModel):
                  l.append(attr.getDict())
                else:
                  dic = attr.__dict__
                  if '_state' in dic:
                    dic.pop('_state')
                  l.append(dic)
              d[m] = l
        #   ManyToMany      _meat.fields,       getMtMFiled       
        if 'basemodel_ptr' in d:
          d.pop('basemodel_ptr')
    
        ignoreList = self.getIgnoreList()
        if ignoreList is not None:
          for m in ignoreList:
            if d.get(m) is not None:
              d.pop(m)
        #         
        return d
    
      def toJSON(self):
        import json
        return json.dumps(self.getDict(), ensure_ascii=False).encode('utf-8').decode()
    
    
    使用方法:
    modelsのすべてのクラスはBasemodelクラスを継承して、このようなtoJSON()メソッドを呼び出すだけでいいです。
    注意してください。なぜか、self.u。meta.fieldsにはManyToManyFieldフィールドが含まれていないので、getMt MField方法を書き換える必要があります。例は以下の通りです
    
    class Book(BaseModel):
      name = models.CharField(max_length=50)
      authors = models.ManyToManyField(Author)
      publish = models.ForeignKey(Publisher, on_delete=models.SET_NULL, blank=True, null=True)
      page = models.IntegerField(default=0) #   
      introduction = models.CharField(max_length=500)
      bookType = models.ManyToManyField(BookType, null=True, blank=True)
      bookTag = models.ManyToManyField(BookTag, null=True, blank=True)
      evaluation = models.FloatField()
      coverUrl = models.CharField(max_length=100, null=True, blank=True)
    
      def getMtMField(self):
        return ['bookType', 'bookTag']
    
    
    結果:
    
    {
      "id":4,
      "name":"Django      ",
      "page":123,
      "introduction":"introduction",
      "evaluation":1,
      "bookType":[
        {
          "id":1,
          "name":"  "
        }
      ],
      "bookTag":[
        {
          "id":2,
          "name":"tag"
        }
      ]
    }
    
    後記
    ソースは引用されています。すなわち、getDictメソッドの最初のforサイクルですが、元のリンクを探すのがおっくうで、ご了承ください。
  • 本人はpython新米で、コードは多く規範に合わないところがあって、諒解を期待します。
  • コードは優れていませんが、助けてあげたいです。
  • 以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。