在本地机器上,应用程序运行良好(使用 sqlite db)。但是当部署在 Heroku (postgresql db) 上时,它会导致以下错误
column "data" specified more than once
LINE 1: ...object_object_id", "timestamp", "public", "data", "data")
更新:我认为这JSONField(blank=True, null=True).contribute_to_class(Action, 'data')
是两次创建列的行——但这仅发生在 Heroku 上使用 postresql 数据库的已部署程序上。如果我注释掉这一行,该列将被创建 0 次。我还尝试更改data
为以考虑保留名称mydata
的可能性-但指定两次的相同问题。data
"mydata"
追溯
File "/app/.heroku/python/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "/app/nutmeg/spiceapp/views.py" in upload
1188. functions.saveFileinS3(tmpdir,formtoadd,request)
File "/app/nutmeg/spiceapp/functions.py" in saveFileinS3
296. action.send(request.user, verb='Added', part_id = new_model.id, name =modelname, type=filetype, format = format, manufacturer = manufacturer)
File "/app/.heroku/python/lib/python2.7/site-packages/django/dispatch/dispatcher.py" in send
172. response = receiver(signal=self, sender=sender, **named)
File "/app/nutmeg/apps/actstream/actions.py" in action_handler
111. newaction.save()
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/base.py" in save
463. self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/base.py" in save_base
551. result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/manager.py" in _insert
203. return insert_query(self.model, objs, fields, **kwargs)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/query.py" in insert_query
1576. return query.get_compiler(using=using).execute_sql(return_id)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
910. cursor.execute(sql, params)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/util.py" in execute
40. return self.cursor.execute(sql, params)
File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py" in execute
52. return self.cursor.execute(query, args)
Exception Type: DatabaseError at /parts/upload/
Exception Value: column "data" specified more than once
LINE 1: ...object_object_id", "timestamp", "public", "data", "data") VA...
models.py
from django.db import models
from django.core.urlresolvers import reverse
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import ugettext as _
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
try:
from django.utils import timezone
now = timezone.now
except ImportError:
from datetime import datetime
now = datetime.now
from actstream import settings as actstream_settings
from actstream.signals import action
from actstream.actions import action_handler
from actstream.managers import FollowManager
class Follow(models.Model):
"""
Lets a user follow the activities of any specific actor
"""
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.CharField(max_length=255)
follow_object = generic.GenericForeignKey()
actor_only = models.BooleanField("Only follow actions where the object is "
"the target.", default=True)
started = models.DateTimeField(default=now)
objects = FollowManager()
class Meta:
unique_together = ('user', 'content_type', 'object_id')
def __unicode__(self):
return u'%s -> %s' % (self.user, self.follow_object)
class Action(models.Model):
"""
Action model describing the actor acting out a verb (on an optional
target).
Nomenclature based on http://activitystrea.ms/specs/atom/1.0/
Generalized Format::
<actor> <verb> <time>
<actor> <verb> <target> <time>
<actor> <verb> <action_object> <target> <time>
Examples::
<justquick> <reached level 60> <1 minute ago>
<brosner> <commented on> <pinax/pinax> <2 hours ago>
<washingtontimes> <started follow> <justquick> <8 minutes ago>
<mitsuhiko> <closed> <issue 70> on <mitsuhiko/flask> <about 2 hours ago>
Unicode Representation::
justquick reached level 60 1 minute ago
mitsuhiko closed issue 70 on mitsuhiko/flask 3 hours ago
HTML Representation::
<a href="http://oebfare.com/">brosner</a> commented on <a href="http://github.com/pinax/pinax">pinax/pinax</a> 2 hours ago
"""
actor_content_type = models.ForeignKey(ContentType, related_name='actor')
actor_object_id = models.CharField(max_length=255)
actor = generic.GenericForeignKey('actor_content_type', 'actor_object_id')
verb = models.CharField(max_length=255)
description = models.TextField(blank=True, null=True)
target_content_type = models.ForeignKey(ContentType, related_name='target',
blank=True, null=True)
target_object_id = models.CharField(max_length=255, blank=True, null=True)
target = generic.GenericForeignKey('target_content_type',
'target_object_id')
action_object_content_type = models.ForeignKey(ContentType,
related_name='action_object', blank=True, null=True)
action_object_object_id = models.CharField(max_length=255, blank=True,
null=True)
action_object = generic.GenericForeignKey('action_object_content_type',
'action_object_object_id')
timestamp = models.DateTimeField(default=now)
public = models.BooleanField(default=True)
objects = actstream_settings.get_action_manager()
class Meta:
ordering = ('-timestamp', )
def __unicode__(self):
ctx = {
'actor': self.actor,
'verb': self.verb,
'action_object': self.action_object,
'target': self.target,
'timesince': self.timesince()
}
if self.target:
if self.action_object:
return _('%(actor)s %(verb)s %(action_object)s on %(target)s %(timesince)s ago') % ctx
return _('%(actor)s %(verb)s %(target)s %(timesince)s ago') % ctx
if self.action_object:
return _('%(actor)s %(verb)s %(action_object)s %(timesince)s ago') % ctx
return _('%(actor)s %(verb)s %(timesince)s ago') % ctx
def actor_url(self):
"""
Returns the URL to the ``actstream_actor`` view for the current actor.
"""
return reverse('actstream_actor', None,
(self.actor_content_type.pk, self.actor_object_id))
def target_url(self):
"""
Returns the URL to the ``actstream_actor`` view for the current target.
"""
return reverse('actstream_actor', None,
(self.target_content_type.pk, self.target_object_id))
def action_object_url(self):
"""
Returns the URL to the ``actstream_action_object`` view for the current action object
"""
return reverse('actstream_actor', None,
(self.action_object_content_type.pk, self.action_object_object_id))
def timesince(self, now=None):
"""
Shortcut for the ``django.utils.timesince.timesince`` function of the
current timestamp.
"""
from django.utils.timesince import timesince as timesince_
return timesince_(self.timestamp, now)
@models.permalink
def get_absolute_url(self):
return ('actstream.views.detail', [self.pk])
# convenient accessors
actor_stream = Action.objects.actor
action_object_stream = Action.objects.action_object
target_stream = Action.objects.target
user_stream = Action.objects.user
model_stream = Action.objects.model_actions
followers = Follow.objects.followers
following = Follow.objects.following
def setup_generic_relations():
"""
Set up GenericRelations for actionable models.
"""
for model in actstream_settings.get_models().values():
if not model:
continue
for field in ('actor', 'target', 'action_object'):
attr = '%s_actions' % field
if isinstance(getattr(model, attr, None),
generic.ReverseGenericRelatedObjectsDescriptor):
break
generic.GenericRelation(Action,
content_type_field='%s_content_type' % field,
object_id_field='%s_object_id' % field,
related_name='actions_with_%s_%s_as_%s' % (
model._meta.app_label, model._meta.module_name, field),
).contribute_to_class(model, attr)
# @@@ I'm not entirely sure why this works
setattr(Action, 'actions_with_%s_%s_as_%s' % (
model._meta.app_label, model._meta.module_name, field), None)
setup_generic_relations()
if actstream_settings.USE_JSONFIELD:
try:
from jsonfield.fields import JSONField
except ImportError:
raise ImproperlyConfigured('You must have django-jsonfield installed '
'if you wish to use a JSONField on your actions')
JSONField(blank=True, null=True).contribute_to_class(Action, 'data')
# connect the signal
action.connect(action_handler, dispatch_uid='actstream.models')