2011-11-12 58 views
1

最近、私はDjangoのさまざまなオブジェクトをJSONに直列化するコードを発見しました。残念ながら、いくつかのタイプのモデルに遭遇すると、コードはAttributeErrorをスローします。ここでDjangoシリアライザエラー: 'NoneType'オブジェクトに '_meta'属性がありません

は、私が診断し、解決しようとしていますエラーおよびトレースバックです:

AttributeError at /serial/ 
'NoneType' object has no attribute '_meta' 
Request Method: GET 
Request URL: http://127.0.0.1:8000/serial/ 
Django Version: 1.2.5 
Exception Type: AttributeError 
Exception Value:  
'NoneType' object has no attribute '_meta' 
Exception Location: /Users/jphill/apps/d_projects/smartgoal/../smartgoal/hq/custom_serializer.py in handle_m2m_field, line 183 
Python Executable: /usr/bin/python 
Python Version: 2.6.7 
Python Path: ['/Users/jphill/apps/d_projects/smartgoal', '/Library/Python/2.6/site-packages/setuptools-0.6c11-py2.6.egg', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python26.zip', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-darwin', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-mac', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/plat-mac/lib-scriptpackages', '/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-tk', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-old', '/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-dynload', '/Library/Python/2.6/site-packages', '/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC'] 
Server time: Fri, 11 Nov 2011 23:08:13 -0500 

Environment: 

Request Method: GET 
Request URL: http://127.0.0.1:8000/serial/ 
Django Version: 1.2.5 
Python Version: 2.6.7 
Installed Applications: 
['django.contrib.auth', 
'django.contrib.contenttypes', 
'django.contrib.sessions', 
'django.contrib.sites', 
'django.contrib.messages', 
'django.contrib.admin', 
'django.contrib.admindocs', 
'hq'] 
Installed Middleware: 
('django.middleware.common.CommonMiddleware', 
'django.contrib.sessions.middleware.SessionMiddleware', 
'django.middleware.csrf.CsrfViewMiddleware', 
'django.contrib.auth.middleware.AuthenticationMiddleware', 
'django.contrib.messages.middleware.MessageMiddleware') 


Traceback: 
File "/Library/Python/2.6/site-packages/django/core/handlers/base.py" in get_response 
    100.      response = callback(request, *callback_args, **callback_kwargs) 
File "/Users/jphill/apps/d_projects/smartgoal/hq/views.py" in serial 
    164.  return json_response_from(Task.objects.all()) 
File "/Users/jphill/apps/d_projects/smartgoal/hq/views.py" in json_response_from 
    88.  return HttpResponse(jsonSerializer.serialize(response,), mimetype='application/json') 
File "/Users/jphill/apps/d_projects/smartgoal/../smartgoal/hq/custom_serializer.py" in serialize 
    34.   self.handle_object(obj) 
File "/Users/jphill/apps/d_projects/smartgoal/../smartgoal/hq/custom_serializer.py" in handle_object 
    75.    self.handle_queryset(object) 
File "/Users/jphill/apps/d_projects/smartgoal/../smartgoal/hq/custom_serializer.py" in handle_queryset 
    138.    self.handle_model(mod) 
File "/Users/jphill/apps/d_projects/smartgoal/../smartgoal/hq/custom_serializer.py" in handle_model 
    128.      self.handle_m2m_field(mod, field) 
File "/Users/jphill/apps/d_projects/smartgoal/../smartgoal/hq/custom_serializer.py" in handle_m2m_field 
    183.   if field.rel.through._meta.auto_created: 

Exception Type: AttributeError at /serial/ 
Exception Value: 'NoneType' object has no attribute '_meta' 

ここでここでシリアライザコード(ここではhttp://www.traddicts.org/webdevelopment/flexible-and-simple-json-serialization-for-django/見つからない鉱山、)

from io import StringIO 
from django.db.models import Model 
from django.db.models.query import QuerySet 
from django.utils.encoding import smart_unicode 
from django.utils.simplejson import dumps 

class UnableToSerializeError(Exception): 
    """ Error for not implemented classes """ 
    def __init__(self, value): 
     self.value = value 
     Exception.__init__(self) 

    def __str__(self): 
     return repr(self.value) 

class JSONSerializer(): 
    boolean_fields = ['BooleanField', 'NullBooleanField'] 
    datetime_fields = ['DatetimeField', 'DateField', 'TimeField'] 
    number_fields = ['IntegerField', 'AutoField', 'DecimalField', 'FloatField', 'PositiveSmallIntegerField'] 


    def serialize(self, obj, **options): 
     self.options = options 

     self.stream = options.pop("stream", StringIO()) 
     self.selectedFields = options.pop("fields", None) 
     self.ignoredFields = options.pop("ignored", None) 
     self.use_natural_keys = options.pop("use_natural_keys", False) 
     self.currentLoc = '' 

     self.level = 0 

     self.start_serialization() 

     self.handle_object(obj) 

     self.end_serialization() 
     return self.getvalue() 

    def get_string_value(self, obj, field): 
     """Convert a field's value to a string.""" 
     return smart_unicode(field.value_to_string(obj)) 

    def start_serialization(self): 
     """Called when serializing of the queryset starts.""" 
     pass 

    def end_serialization(self): 
     """Called when serializing of the queryset ends.""" 
     pass 

    def start_array(self): 
     """Called when serializing of an array starts.""" 
     self.stream.write(u'[') 
    def end_array(self): 
     """Called when serializing of an array ends.""" 
     self.stream.write(u']') 

    def start_object(self): 
     """Called when serializing of an object starts.""" 
     self.stream.write(u'{') 

    def end_object(self): 
     """Called when serializing of an object ends.""" 
     self.stream.write(u'}') 

    def handle_object(self, object): 
     """ Called to handle everything, looks for the correct handling """ 
     if isinstance(object, dict): 
      self.handle_dictionary(object) 
     elif isinstance(object, list): 
      self.handle_list(object) 
     elif isinstance(object, Model): 
      self.handle_model(object) 
     elif isinstance(object, QuerySet): 
      self.handle_queryset(object) 
     elif isinstance(object, bool): 
      self.handle_simple(object) 
     elif isinstance(object, int) or isinstance(object, float) or isinstance(object, long): 
      self.handle_simple(object) 
     elif isinstance(object, basestring): 
      self.handle_simple(object) 
     else: 
      raise UnableToSerializeError(type(object)) 

    def handle_dictionary(self, d): 
     """Called to handle a Dictionary""" 
     i = 0 
     self.start_object() 
     for key, value in d.iteritems(): 
      self.currentLoc += key+'.' 
      #self.stream.write(unicode(self.currentLoc)) 
      i += 1 
      self.handle_simple(key) 
      self.stream.write(u': ') 
      self.handle_object(value) 
      if i != len(d): 
       self.stream.write(u', ') 
      self.currentLoc = self.currentLoc[0:(len(self.currentLoc)-len(key)-1)] 
     self.end_object() 

    def handle_list(self, l): 
     """Called to handle a list""" 
     self.start_array() 

     for value in l: 
      self.handle_object(value) 
      if l.index(value) != len(l) -1: 
       self.stream.write(u', ') 

     self.end_array() 

    def handle_model(self, mod): 
     """Called to handle a django Model""" 
     self.start_object() 

     for field in mod._meta.local_fields: 
      if field.rel is None: 
       if self.selectedFields is None or field.attname in self.selectedFields or field.attname: 
        if self.ignoredFields is None or self.currentLoc + field.attname not in self.ignoredFields: 
         self.handle_field(mod, field) 
      else: 
       if self.selectedFields is None or field.attname[:-3] in self.selectedFields: 
        if self.ignoredFields is None or self.currentLoc + field.attname[:-3] not in self.ignoredFields: 
         self.handle_fk_field(mod, field) 
     for field in mod._meta.many_to_many: 
      if self.selectedFields is None or field.attname in self.selectedFields: 
       if self.ignoredFields is None or self.currentLoc + field.attname not in self.ignoredFields: 
        self.handle_m2m_field(mod, field) 
     self.stream.seek(self.stream.tell()-2) 
     self.end_object() 

    def handle_queryset(self, queryset): 
     """Called to handle a django queryset""" 
     self.start_array() 
     it = 0 
     for mod in queryset: 
      it += 1 
      self.handle_model(mod) 
      if queryset.count() != it: 
       self.stream.write(u', ') 
     self.end_array() 

    def handle_field(self, mod, field): 
     """Called to handle each individual (non-relational) field on an object.""" 
     self.handle_simple(field.name) 
     if field.get_internal_type() in self.boolean_fields: 
      if field.value_to_string(mod) == 'True': 
       self.stream.write(u': true') 
      elif field.value_to_string(mod) == 'False': 
       self.stream.write(u': false') 
      else: 
       self.stream.write(u': undefined') 
     else: 
      self.stream.write(u': ') 
      self.handle_simple(field.value_to_string(mod)) 
     self.stream.write(u', ') 

    def handle_fk_field(self, mod, field): 
     """Called to handle a ForeignKey field.""" 
     related = getattr(mod, field.name) 
     if related is not None: 
      if field.rel.field_name == related._meta.pk.name: 
       # Related to remote object via primary key 
       pk = related._get_pk_val() 
      else: 
       # Related to remote object via other field 
       pk = getattr(related, field.rel.field_name) 
      d = { 
        'pk': pk, 
       } 
      if self.use_natural_keys and hasattr(related, 'natural_key'): 
       d.update({'natural_key': related.natural_key()}) 
      if type(d['pk']) == str and d['pk'].isdigit(): 
       d.update({'pk': int(d['pk'])}) 

      self.handle_simple(field.name) 
      self.stream.write(u': ') 
      self.handle_object(d) 
      self.stream.write(u', ') 

    def handle_m2m_field(self, mod, field): 
     """Called to handle a ManyToManyField.""" 
     if field.rel.through._meta.auto_created: 
      self.handle_simple(field.name) 
      self.stream.write(u': ') 
      self.start_array() 
      hasRelationships = False 
      for relobj in getattr(mod, field.name).iterator(): 
       hasRelationships = True 
       pk = relobj._get_pk_val() 
       d = { 
         'pk': pk, 
        } 
       if self.use_natural_keys and hasattr(relobj, 'natural_key'): 
        d.update({'natural_key': relobj.natural_key()}) 
       if type(d['pk']) == str and d['pk'].isdigit(): 
        d.update({'pk': int(d['pk'])}) 

       self.handle_simple(d) 
       self.stream.write(u', ') 
      if hasRelationships: 
       self.stream.seek(self.stream.tell()-2) 
      self.end_array() 
      self.stream.write(u', ') 

    def handle_simple(self, simple): 
     """ Called to handle values that can be handled via simplejson """ 
     self.stream.write(unicode(dumps(simple))) 

    def getvalue(self): 
     """Return the fully serialized object (or None if the output stream is not seekable).sss """ 
     if callable(getattr(self.stream, 'getvalue', None)): 
      return self.stream.getvalue() 

がモデルIですシリアル化しようとしています:

class Task(models.Model): 
    """ 
    Model used for tracking tasks 
    """ 
    PRIORITY_CHOICES = (
     ('0', 'None'), 
     ('1', 'High'), 
     ('2', 'Medium'), 
     ('3', 'Low'), 
    ) 
    name = models.CharField(max_length=255) 
    completed = models.BooleanField(default=False) 
    hidden = models.BooleanField(default=False) 
    timestamp = models.DateField(auto_now=True) 
    priority = models.CharField(default=0, max_length=1, choices=PRIORITY_CHOICES) 
    creator = models.ForeignKey(User, related_name="created_task") 
    # optional 
    owner = models.ForeignKey(User, related_name="owned_task", blank=True, null=True) 
    goal = models.ForeignKey('Goal', blank=True, null=True) 
    reminder = models.DateTimeField(blank=True, null=True) 
    note = models.TextField(blank=True) 
    started = models.BooleanField(default=False, blank=True) 
    activities = generic.GenericRelation('Activity') 

ここで私はすべてを実行していますviews.py:

def serial(request): 
    return json_response_from(Task.objects.all()) 

def json_response_from(response): 
    jsonSerializer = JSONSerializer() 
    return HttpResponse(jsonSerializer.serialize(response, use_natural_keys=True), mimetype='application/json') 

答えて

3

私の推測では、GenericRelationの問題です。これはまったく新しいフィールド型であり、シリアル化コードが記述されたときに実装されていない可能性があります。

GenericRelationフィールドはManyToMany関係を内部的に使用し、おそらくfield.rel.throughオブジェクトを定義しない方法で使用します。これにより、ケースのエラーが発生します。これを確認するには、いくつかのログを追加して、問題の原因となっているフィールドを確認します。

これを解決するには、GenericRelationsをもっと見るか、サポートするシリアル化コードを変更するか、またはGenericRelationsをサポートする他のシリアル化手法を使用します。 GenericRelationクラスのDjangoのソースコードから

クリップ:

def get_internal_type(self): 
     return "ManyToManyField" 
+0

私はそれはそれだと思います。ありがとうございました! –

関連する問題