Admin view give a Value Error: Cannot assign "'Intelligence'": "CharacterAttributeLink.attribute" must be a "Attribute" instance

Admin view give a Value Error: Cannot assign "'Intelligence'": "CharacterAttributeLink.attribute" must be a "Attribute" instance

我的管理页面目前给我这个:

ValueError at /admin/characters/mage/add/ 
Cannot assign "'Intelligence'": "CharacterAttributeLink.attribute" must be a "Attribute" instance.

看看我的 models.py:

class Skill(models.Model):
    name = models.CharField(max_length=50, choices=SKILL_CHOICES)

class Attribute(models.Model):
    name = models.CharField(max_length=50, choices=ATTRIBUTE_CHOICES)

class SkillLink(models.Model):
    skill = models.ForeignKey('Skill', choices=SKILL_CHOICES)
    class Meta:
        abstract = True

class AttributeLink(models.Model):
    attribute = models.ForeignKey('Attribute', choices=ATTRIBUTE_CHOICES)
    class Meta:
        abstract = True  

class Spell(models.Model):
    name = models.CharField(max_length=50)
    vulgar = models.BooleanField(default=False)
    # All spells have a primary arcana, and 0-Many secondary arcana.
    # Each spell's arcanum have different rating. E.g. Fate 1, Prime 1
    #non-optional arcana in addition to the main arcana
    # arcana that are not needed to cast the spell
    arcana = models.ManyToManyField('Arcana', choices=ARCANUM_CHOICES, through='SpellArcanumLink', 
        related_name='spell_by_arcanum')
    @property
    def primary_arcana(self):
        return self.arcana.filter(type="primary")
    @property
    def secondary_arcana(self):
        return self.arcana.filter(type="secondary")
    @property
    def optional_arcana(self):
        return self.arcana.filter(type="optional")

    # All spells have a 'Attribute+Skill+Primary arcana' pool for casting
    skill = models.ManyToManyField('Skill', choices=SKILL_CHOICES, related_name='spell_by_skill',
        through='SpellSkillLink')
    attribute = models.ManyToManyField('Attribute', choices=ATTRIBUTE_CHOICES, 
        related_name='spell_by_attribute', through='SpellAttributeLink')
    @property
    def rote_skill(self):
        return self.skill.filter(type="rote") if self.contested else None
    @property
    def rote_attribute(self):
        return self.attribute.filter(type="rote") if self.contested else None
    # Mages can own spells
    mage = models.ManyToManyField('Mage', related_name='spell_by_mage', through='SpellMageLink')
    # Optional contested skill check, e.g. 'Attribute+Skill+Primary arcana vs Attribute+Skill'
    contested = models.BooleanField(default=False)
    @property
    def contested_attribute(self):
        return self.attribute.filter(type="contested") if self.contested else None
    @property
    def contested_skill(self):
        return self.skill.filter(type="contested") if self.contested else None
    # Optional attribute to subtract from casting dicepool, 
    # e.g. 'Attribute+Skill+Primary arcana-Resist Attribute'
    resisted = models.BooleanField(default=False)
    @property
    def resisted_attribute(self):
        return self.attribute.filter(type="resisted") if self.resisted else None
    # Spells come from books
    book_ref = GenericRelation('BookReference', null=True, blank=True)

class SpellAttributeLink(SpellLink, AttributeLink):
    type = models.CharField(max_length=32, 
        choices=(('resisted', 'resisted'), ('contested', 'contested'), ('rote', 'rote'))
        )

class SpellSkillLink(SpellLink, SkillLink):
    type = models.CharField(max_length=32,
        choices=(('contested', 'contested'), ('rote', 'rote')), default='Rote'
        )

这个应该够了

还有我的admin.py

from django.contrib import admin
from django.contrib.contenttypes import admin as genericAdmin

class ExtraAttributeInline(admin.StackedInline):
    model = SpellAttributeLink
    extra = 1
    can_delete = False

class ExtraSkillInline(admin.StackedInline):
    model = SpellSkillLink
    extra = 1
    can_delete = False

class ExtraSpellArcanaInline(admin.TabularInline):
    model = SpellArcanumLink
    extra = 1

class SpellInline(admin.TabularInline):
    model = Spell.mage.through  

class SpellAdmin(admin.ModelAdmin):
    inlines = [ExtraAttributeInline, ExtraSkillInline, ExtraSpellArcanaInline, BookReferenceInline]

# Register your models here.
admin.site.register(Mage, MageAdmin)
admin.site.register(Skill)
admin.site.register(Attribute)
admin.site.register(Arcana)
admin.site.register(Spell, SpellAdmin)

我不明白为什么尝试在 CharacterAttributeLink.attribute 上分配智力是个问题。智力有问题

这是我的踪迹:

Environment:


Request Method: POST
Request URL: http://localhost:8000/admin/characters/spell/add/?_to_field=id&_popup=1

Django Version: 1.7.1
Python Version: 3.4.2
Installed Applications:
('autocomplete_light',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'characters')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware')


Traceback:
File "C:\Python34\lib\site-packages\django\core\handlers\base.py" in get_response
  111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Python34\lib\site-packages\django\contrib\admin\options.py" in wrapper
  584.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "C:\Python34\lib\site-packages\django\utils\decorators.py" in _wrapped_view
  105.                     response = view_func(request, *args, **kwargs)
File "C:\Python34\lib\site-packages\django\views\decorators\cache.py" in _wrapped_view_func
  52.         response = view_func(request, *args, **kwargs)
File "C:\Python34\lib\site-packages\django\contrib\admin\sites.py" in inner
  204.             return view(request, *args, **kwargs)
File "C:\Python34\lib\site-packages\django\contrib\admin\options.py" in add_view
  1454.         return self.changeform_view(request, None, form_url, extra_context)
File "C:\Python34\lib\site-packages\django\utils\decorators.py" in _wrapper
  29.             return bound_func(*args, **kwargs)
File "C:\Python34\lib\site-packages\django\utils\decorators.py" in _wrapped_view
  105.                     response = view_func(request, *args, **kwargs)
File "C:\Python34\lib\site-packages\django\utils\decorators.py" in bound_func
  25.                 return func.__get__(self, type(self))(*args2, **kwargs2)
File "C:\Python34\lib\site-packages\django\db\transaction.py" in inner
  394.                 return func(*args, **kwargs)
File "C:\Python34\lib\site-packages\django\contrib\admin\options.py" in changeform_view
  1404.             if all_valid(formsets) and form_validated:
File "C:\Python34\lib\site-packages\django\forms\formsets.py" in all_valid
  438.         if not formset.is_valid():
File "C:\Python34\lib\site-packages\django\forms\formsets.py" in is_valid
  303.         self.errors
File "C:\Python34\lib\site-packages\django\forms\formsets.py" in errors
  277.             self.full_clean()
File "C:\Python34\lib\site-packages\django\forms\formsets.py" in full_clean
  326.             self._errors.append(form.errors)
File "C:\Python34\lib\site-packages\django\forms\forms.py" in errors
  154.             self.full_clean()
File "C:\Python34\lib\site-packages\django\forms\forms.py" in full_clean
  355.         self._post_clean()
File "C:\Python34\lib\site-packages\django\forms\models.py" in _post_clean
  408.         self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
File "C:\Python34\lib\site-packages\django\forms\models.py" in construct_instance
  60.             f.save_form_data(instance, cleaned_data[f.name])
File "C:\Python34\lib\site-packages\django\db\models\fields\__init__.py" in save_form_data
  804.         setattr(instance, self.name, data)
File "C:\Python34\lib\site-packages\django\db\models\fields\related.py" in __set__
  597.                     self.field.rel.to._meta.object_name,

Exception Type: ValueError at /admin/characters/spell/add/
Exception Value: Cannot assign "'Intelligence'": "SpellAttributeLink.attribute" must be a "Attribute" instance.

我做错了什么?!

仅将 choices 放在字符字段上:

class Attribute(models.Model):
    name = models.CharField(max_length=50, choices=ATTRIBUTE_CHOICES)

告诉 Django 只为您提供从字符串元组中选择众多选项之一的选项。

class AttributeLink(models.Model):
    attribute = models.ForeignKey('Attribute', choices=ATTRIBUTE_CHOICES)

告诉 Django 属性对象只能是字符串元组中的众多选择之一。 type(attribute) != type(String)