Monday, July 29, 2013

Re: Django throws an exception when I add data from admin interface

Thanks for your reply, you are right.

On Saturday, July 27, 2013 12:21:07 AM UTC+8, Tom Evans wrote:
On Fri, Jul 26, 2013 at 4:22 PM, Yu Yang <yy20...@gmail.com> wrote:
> It is a blog app, I have created a Article model and Tag model. when I add
> data to Article table from Admin interface, the data is stored to database,
> but if I click the link to change the entry, it throws an exception "string
> indices must be integers, not str", the traceback is as follows:
> Environment:
>
>
> Request Method: GET
> Request URL: http://localhost:8000/admin/blog/article/1/
>
> Django Version: 1.5.1
> Python Version: 2.7.3
> Installed Applications:
> ('django.contrib.auth',
>  'django.contrib.contenttypes',
>  'django.contrib.sessions',
>  'django.contrib.sites',
>  'django.contrib.messages',
>  'django.contrib.staticfiles',
>  'django.contrib.admin',
>  'blog')
> 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
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/core/handlers/base.py"
> in get_response
>   115.                         response = callback(request, *callback_args,
> **callback_kwargs)
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/contrib/admin/options.py"
> in wrapper
>   372.                 return self.admin_site.admin_view(view)(*args,
> **kwargs)
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/utils/decorators.py"
> in _wrapped_view
>   91.                     response = view_func(request, *args, **kwargs)
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/views/decorators/cache.py"
> in _wrapped_view_func
>   89.         response = view_func(request, *args, **kwargs)
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/contrib/admin/sites.py"
> in inner
>   202.             return view(request, *args, **kwargs)
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/utils/decorators.py"
> in _wrapper
>   25.             return bound_func(*args, **kwargs)
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/utils/decorators.py"
> in _wrapped_view
>   91.                     response = view_func(request, *args, **kwargs)
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/utils/decorators.py"
> in bound_func
>   21.                 return func(self, *args2, **kwargs2)
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/db/transaction.py"
> in inner
>   223.                 return func(*args, **kwargs)
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/contrib/admin/options.py"
> in change_view
>   1112.             form = ModelForm(instance=obj)
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/forms/models.py"
> in __init__
>   244.             object_data = model_to_dict(instance, opts.fields,
> opts.exclude)
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/forms/models.py"
> in model_to_dict
>   129.                 data[f.name] =
> list(f.value_from_object(instance).values_list('pk', flat=True))
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/db/models/fields/related.py"
> in value_from_object
>   1333.         return getattr(obj, self.attname).all()
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/db/models/manager.py"
> in all
>   128.         return self.get_query_set()
> File
> "/home/yangyu/.virtualenvs/django-blog/local/lib/python2.7/site-packages/django/db/models/fields/related.py"
> in get_query_set
>   612.                 return
> self.instance._prefetched_objects_cache[self.prefetch_cache_name]
>
> Exception Type: TypeError at /admin/blog/article/1/
> Exception Value: string indices must be integers, not str
>
>
> the code of Article model and Tag model is as follows:
>
>
> class Tag(models.Model):
>     name = models.CharField(max_length=50, unique=True, verbose_name='标签')
>     slug = models.SlugField()
>
>     def __unicode__(self):
>         return self.name
>
>     class Meta:
>         verbose_name = '标签'
>         verbose_name_plural = '标签'
>
>     @models.permalink
>     def get_absolute_url(self):
>         return ('blog_tag', (), {'idx': self.id, 'slug': self.slug})
>
>
> # Create your models here.
> class Article(models.Model):
>     """
>     the model for blog article
>     """
>     STATUS_CHOICE = (
>         (1, '编辑'),
>         (2, '完成'),
>         (3, '失效'),
>     )
>     title = models.CharField(max_length=100, verbose_name='标题')
>     slug = models.SlugField(max_length=100)
>     content = models.TextField(verbose_name='内容')
>     created_time = models.DateTimeField(auto_now_add=True,
> verbose_name="创建时间")
>     modified_time = models.DateTimeField(default=datetime.now,
>                                          verbose_name="修改时间")
>     tags = models.ManyToManyField(Tag, verbose_name='标签')
>     category = models.ForeignKey('Category', blank=True, null=True,
> verbose_name='分类')
>     always_top = models.BooleanField(default=False, verbose_name='置顶')
>     author = models.CharField(max_length=40, verbose_name='作者')
>     status = models.IntegerField(choices=STATUS_CHOICE,
>                                  default=1, verbose_name='状态')
>
>     @models.permalink
>     def get_absolute_url(self):
>         return ('blog_article', (), {'idx': self.id, 'slug': self.slug})
>
>     def __getattr__(self, name):
>         """
>         add two attributes(summary, visible_comments) to the object
>         Arguments:
>         - `name`:
>         """
>         if name == 'summary':
>             return util.get_summary(self.content)
>         else:
>             return ''

This __getattr__ method is utterly bogus.

With this method, every attempt to get an attribute of this instance
either returns something special if the attribute is named 'summary',
but most importantly, **it returns an empty string for EVERYTHING
else**, regardless of anything, whether the attribute exists or not.

I imagine at some point something in django is looking at an attribute
which should be None, or raise an AttributeError, but it doesn't, it
returns an empty string. It then uses this bogus empty string to try
and index into a string.

I imagine removing the ManyToManyField bypasses the code that does this.

Cheers

Tom

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

No comments:

Post a Comment