fk_name 'user' не является ForeignKey для ‹class 'satchmo_store.contact.models.Contact'›

Я использую django 1.3.1 и satchmo 0.9.2. Я использовал модель по умолчанию, поставляемую с Satchmo, под названием Contact. Я создал приложение satchmo_mod и файл admin.py.

pip install django==1.3.1
pip install -r http://bitbucket.org/chris1610/satchmo/raw/tip/scripts/requirements.txt
pip install satchmo 0.9.2

django-admin.py startproject fk_test
cd fk_test
python manage.py startapp satchmo_mod

затем создайте admin.py:

from satchmo_store.contact.models import Contact
admin.site.unregister(Contact)
admin.site.register(Contact)

Затем я бегу:

python manage.py runserver

Go to:

127.0.0.1:8000

Получите эту ошибку:

fk_name 'user' is not a ForeignKey to <class 'satchmo_store.contact.models.Contact'>

Я вижу эту ошибку в трассировке стека и начинаю исследовать:

/home/cody/work/martin-instruments/virtual-envs/mi-prod-copy/lib/python2.6/site-packages/django/contrib/admin/validation.py in validate_inline
    fk = _get_foreign_key(parent_model, cls.model, fk_name=cls.fk_name, can_fail=True) ...
▼ Local vars
Variable    Value
parent_model    
<class 'satchmo_store.contact.models.Contact'>
cls 
<class 'satchmo_mod.admin.UserTaxExemptInline'>
parent  
<class 'django.contrib.admin.options.ModelAdmin'>
f   
<django.db.models.fields.related.OneToOneField object at 0x2ec2250>

Короче говоря, когда модель Contact регистрируется снова, все ее параметры _meta не восстанавливаются, насколько я могу судить. См. Сеанс управления оболочкой manage.py ниже:

envs/mi2.0/mi$ ./manage.py shell
Python 2.6.6 (r266:84292, Dec 26 2010, 22:31:48) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from satchmo_mod.admin import UserTaxExemptInline
>>> from satchmo_mod.admin import MyContactOptions
>>> from django.db.models.fields.related import OneToOneField
>>> from satchmo_store.contact.models import Contact
>>> cls = UserTaxExemptInline
>>> parent_model = Contact
>>> parent = MyContactOptions
>>> from django.contrib.admin.validation import get_field
>>> f = get_field(cls, cls.model, cls.model._meta, 'fk_name', cls.fk_name)
>>> print f
<django.db.models.fields.related.OneToOneField object at 0x2c358d0>
>>> dir(f)
['__class__', '__cmp__', '__deepcopy__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slotnames__', '__str__', '__subclasshook__', '__weakref__', '_choices', '_description', '_get_choices', '_get_flatchoices', '_get_val_from_obj', '_pk_trace', '_unique', 'attname', 'auto_created', 'auto_creation_counter', 'bind', 'blank', 'choices', 'clean', 'column', 'contribute_to_class', 'contribute_to_related_class', 'creation_counter', 'db_column', 'db_index', 'db_tablespace', 'db_type', 'default', 'default_error_messages', 'default_validators', 'description', 'do_related_class', 'editable', 'empty_strings_allowed', 'error_messages', 'flatchoices', 'formfield', 'get_attname', 'get_attname_column', 'get_cache_name', 'get_choices', 'get_choices_default', 'get_db_prep_lookup', 'get_db_prep_save', 'get_db_prep_value', 'get_default', 'get_flatchoices', 'get_internal_type', 'get_prep_lookup', 'get_prep_value', 'get_validator_unique_lookup_type', 'has_default', 'help_text', 'max_length', 'model', 'name', 'null', 'opts', 'pre_save', 'primary_key', 'rel', 'related', 'related_query_name', 'run_validators', 'save_form_data', 'serialize', 'set_attributes_from_name', 'set_attributes_from_rel', 'to_python', 'unique', 'unique_for_date', 'unique_for_month', 'unique_for_year', 'validate', 'validators', 'value_from_object', 'value_to_string', 'verbose_name']
>>> from django.db import models
>>> isinstance(f, models.ForeignKey)
True
>>> from django.forms.models import _get_foreign_key
>>> fk = _get_foreign_key(parent_model, cls.model, fk_name=cls.fk_name, can_fail=True)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/cody/work/martin-instruments/virtual-envs/mi2.0/lib/python2.6/site-packages/django/forms/models.py", line 770, in _get_foreign_key
    raise Exception("fk_name '%s' is not a ForeignKey to %s" % (fk_name, parent_model))
Exception: fk_name 'user' is not a ForeignKey to <class 'satchmo_store.contact.models.Contact'>
>>> print parent_model, cls.model, cls.fk_name
<class 'satchmo_store.contact.models.Contact'> <class 'satchmo_mod.models.UserTaxExempt'> user
>>> fk = _get_foreign_key(parent_model, cls.model, fk_name=cls.fk_name, can_fail=True)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/cody/work/martin-instruments/virtual-envs/mi2.0/lib/python2.6/site-packages/django/forms/models.py", line 770, in _get_foreign_key
    raise Exception("fk_name '%s' is not a ForeignKey to %s" % (fk_name, parent_model))
Exception: fk_name 'user' is not a ForeignKey to <class 'satchmo_store.contact.models.Contact'>
>>> print model
Traceback (most recent call last):
  File "<console>", line 1, in <module>
NameError: name 'model' is not defined
>>> print parent_model
<class 'satchmo_store.contact.models.Contact'>
>>> cls.model
<class 'satchmo_mod.models.UserTaxExempt'>
>>> model = cls.model
>>> opts = model._meta
>>> fk_name
Traceback (most recent call last):
  File "<console>", line 1, in <module>
NameError: name 'fk_name' is not defined
>>> fk_name = cls.fk_name
>>> fk_name
'user'
>>> fks_to_parent = [f for f in opts.fields if f.name == fk_name]
>>> print fks_to_parent
[<django.db.models.fields.related.OneToOneField object at 0x2c358d0>]
>>> not isinstance(fk, ForeignKey)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
NameError: name 'fk' is not defined
>>> fk = fks_to_parent[0]
>>> not isinstance(fk, ForeignKey)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
NameError: name 'ForeignKey' is not defined
>>> from django.db.models import ForeignKey
>>> not isinstance(fk, ForeignKey)
False
>>> len(fks_to_parent) == 1
True
>>> not isinstance(fk, ForeignKey) or \
...  768                     (fk.rel.to != parent_model and
... fk.rel.to not in parent_model._meta.get_parent_list())
Traceback (most recent call last):
  File "<console>", line 3, in <module>
TypeError: 'int' object is not callable
>>> not isinstance(fk, ForeignKey) or (fk.rel.to != parent_model and fk.rel.to not in parent_model._meta.get_parent_list())
True
>>> parent_model
<class 'satchmo_store.contact.models.Contact'>
>>> parent_model._meta.get_parent_list()
set([])
>>> fk.rel.to
<class 'django.contrib.auth.models.User'>
>>> fk.rel.to != parent_model
True
>>> fk.rel.to not in parent_model._meta.get_parent_list()
True
>>> fk.rel.to
<class 'django.contrib.auth.models.User'>
>>> fk.rel.to == parent_model
False
>>> parent_model
<class 'satchmo_store.contact.models.Contact'>
>>> fk
<django.db.models.fields.related.OneToOneField object at 0x2c358d0>
>>> fk.rel.to
<class 'django.contrib.auth.models.User'>
>>> # User has to be not equal to Contact
>>> # and fk.rel.to can't be in the parent model's parent list
>>> fk.rel.to
<class 'django.contrib.auth.models.User'>
>>> fk.rel
<django.db.models.fields.related.OneToOneRel object at 0x2c35990>
>>> fk.rel.to != parent_model
True
>>> # OneToOneRel can't be equal to parent_model(Contact) nor can OneToOneRel be in the parent_model(Contact) parent list
>>> Contact._meta.get_parent_list()
set([])
>>> parent_model is Contact
True
>>> fk.rel.to in parent_model._meta.get_parent_list()
False
>>> fk.rel.to != parent_model
True
>>> (fk.rel.to != parent_model and fk.rel.to not in parent_model._meta.get_parent_list())
True
>>> (fk.rel.to != parent_model and fk.rel.to not in parent_model._meta.get_parent_list())
True
>>> (True and False)
False
>>> fk.rel.to != parent_model
True
>>> fk.rel.to.not in parent_model._meta.get_parent_list()
  File "<console>", line 1
    fk.rel.to.not in parent_model._meta.get_parent_list()
                ^
SyntaxError: invalid syntax
>>> fk.rel.to not in parent_model._meta.get_parent_list()
True
>>> fk.rel.to != parent_model
True
>>> fk.rel.to not in parent_model._meta.get_parent_list()
True
>>> fk.rel.to
<class 'django.contrib.auth.models.User'>
>>> parent-model
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'MediaDefiningClass' and 'ModelBase'
>>> parent_model
<class 'satchmo_store.contact.models.Contact'>
>>> fk.rel.to
<class 'django.contrib.auth.models.User'>
>>> parent_model
<class 'satchmo_store.contact.models.Contact'>
>>> parent_model._meta.get_parent_list()
set([])
>>> parent_model.parents
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: type object 'Contact' has no attribute 'parents'
>>> parent_model.options
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: type object 'Contact' has no attribute 'options'
>>> opts
<Options for UserTaxExempt>
>>> parent_model._meta
<Options for Contact>
>>> parent_model._meta.parents
{}
>>> User._meta.parents
Traceback (most recent call last):
  File "<console>", line 1, in <module>
NameError: name 'User' is not defined
>>> from django.contrib.auth.models import User
>>> User._meta.parents
{}
>>> from martin.models import CreditApplication
>>> CreditApplication._meta.parents
{}
>>> User._meta.fields
[<django.db.models.fields.AutoField object at 0x21d45d0>, <django.db.models.fields.CharField object at 0x21d2450>, <django.db.models.fields.CharField object at 0x21d25d0>, <django.db.models.fields.CharField object at 0x21d26d0>, <django.db.models.fields.EmailField object at 0x21d27d0>, <django.db.models.fields.CharField object at 0x21d2950>, <django.db.models.fields.BooleanField object at 0x21d2a90>, <django.db.models.fields.BooleanField object at 0x21d2bd0>, <django.db.models.fields.BooleanField object at 0x21d2d10>, <django.db.models.fields.DateTimeField object at 0x21d2e10>, <django.db.models.fields.DateTimeField object at 0x21d2e90>]
>>> Contact._meta.fields
[<django.db.models.fields.AutoField object at 0x289a510>, <django.db.models.fields.CharField object at 0x2899a90>, <django.db.models.fields.CharField object at 0x2899c10>, <django.db.models.fields.CharField object at 0x2899d10>, <django.db.models.fields.related.ForeignKey object at 0x2899dd0>, <django.db.models.fields.related.ForeignKey object at 0x2899e90>, <django.db.models.fields.related.ForeignKey object at 0x2899f90>, <django.db.models.fields.DateField object at 0x289a0d0>, <django.db.models.fields.EmailField object at 0x289a150>, <django.db.models.fields.TextField object at 0x289a2d0>, <django.db.models.fields.DateField object at 0x289a350>]
>>> Contact._meta.fields[0]
<django.db.models.fields.AutoField object at 0x289a510>
>>> dir(Contact._meta.fields[0])
['__class__', '__cmp__', '__deepcopy__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_choices', '_description', '_get_choices', '_get_flatchoices', '_get_val_from_obj', '_unique', 'attname', 'auto_created', 'auto_creation_counter', 'bind', 'blank', 'choices', 'clean', 'column', 'contribute_to_class', 'creation_counter', 'db_column', 'db_index', 'db_tablespace', 'db_type', 'default', 'default_error_messages', 'default_validators', 'description', 'editable', 'empty_strings_allowed', 'error_messages', 'flatchoices', 'formfield', 'get_attname', 'get_attname_column', 'get_cache_name', 'get_choices', 'get_choices_default', 'get_db_prep_lookup', 'get_db_prep_save', 'get_db_prep_value', 'get_default', 'get_flatchoices', 'get_internal_type', 'get_prep_lookup', 'get_prep_value', 'get_validator_unique_lookup_type', 'has_default', 'help_text', 'max_length', 'model', 'name', 'null', 'pre_save', 'primary_key', 'rel', 'run_validators', 'save_form_data', 'serialize', 'set_attributes_from_name', 'to_python', 'unique', 'unique_for_date', 'unique_for_month', 'unique_for_year', 'validate', 'validators', 'value_from_object', 'value_to_string', 'verbose_name']
>>> Contact._meta.fields[0].model
<class 'satchmo_store.contact.models.Contact'>
>>> Contact._meta.fields[1].model
<class 'satchmo_store.contact.models.Contact'>

ОБНОВЛЕНИЕ. Я сделал исправление, рекомендованное Maccesch. Но, похоже, после отмены регистрации объекта Contact и перерегистрации его с новым встроенным кодом он что-то сделал, чтобы сломать Zinnia:

fk_name 'user' is not a ForeignKey to <class 'zinnia.models.Category'>

ОБНОВЛЕНИЕ: Может, хотите задать новый вопрос, не уверен.

Это код модели и администратора модели:

Models.py

class UserTaxExempt(models.Model):
    user = models.OneToOneField(_User, primary_key=True)
    tax_exempted = models.BooleanField("No taxes would be applied to purchases")

    class Meta:
        verbose_name = _('Tax Exemption')
        verbose_name_plural = _('Tax Exemption') 

    def __unicode__(self):
        if self.tax_exempted:
            return unicode("Purchases are exempted from taxes")
        else:
            return unicode("Purchases are taxed")

admin.py

from satchmo_mod.models import ContactTaxExempt
from satchmo_store.contact.admin import PhoneNumber_Inline, AddressBook_Inline
from satchmo_store.contact.models import Contact

class ContactTaxExemptInline(admin.TabularInline):
    model = ContactTaxExempt
    max_num = 1 
    extra = 1 
    can_delete = False
    fk_name = "user"

class ContactOptions(admin.ModelAdmin):
    list_display = ('last_name', 'first_name')
    list_filter = ['create_date']
    ordering = ['last_name']
    search_fields = ('first_name', 'last_name', 'email')
    related_search_fields = {'user': ('username', 'first_name', 'last_name', 'em
    related_string_functions = {'user': lambda u: u"%s (%s)" % (u.username, u.ge
    inlines = [ContactTaxExemptInline, PhoneNumber_Inline, AddressBook_Inline]

admin.site.unregister(Contact)
admin.site.register(Contact, ContactOptions)

Итак, UserTaxExempt имеет внешний ключ для пользователя, так что не должно ли это работать нормально? Он работает на странице пользователя, поэтому я не понимаю, почему он не работает на странице контактов.


person codygman    schedule 19.06.2012    source источник
comment
Что именно вы пытаетесь сделать и почему это не работает? Единственный раз, когда я вижу ошибку, это когда вы вызываете внутренние функции Django, и я понятия не имею, на что я смотрю в остальной части этого вывода консоли.   -  person Elliott    schedule 21.06.2012
comment
Пытаюсь зарегистрировать простой ModelAdmin. Я вынул modeladmin и просто отменил регистрацию модели, перерегистрировал ее, и это снова выдало мне ошибку! Вывод на консоль - это то, что я копаюсь до функции проверки, используемой для проверки внешних ключей, и просматриваю все значения / и т. Д. Кажется, что _meta.get_parents_list () создается неправильно. Когда я выполняю проверку внешнего ключа в реальных файлах django (плохо, я знаю, но проверяю, работает ли), сайт работает нормально. Очевидно, что это действующий внешний ключ. Делает ли satchmo какие-то странные правки в django, которые все портят?   -  person codygman    schedule 21.06.2012
comment
Как сказал Эллиотт, до сих пор не ясно, что вы на самом деле пытаетесь сделать. Модель Contact в вашем вопросе - это модель от satchmo_store.contact.models? А что вы имеете в виду под регистром простого ModelAdmin? Пожалуйста, обновите свой вопрос и опишите более подробный контекст.   -  person Maccesch    schedule 22.06.2012
comment
Пожалуйста, постарайтесь сделать ваш вопрос более понятным, чтобы мы могли помочь вам с вашей проблемой. Не указывайте только ту ошибку, которую вы получаете. Попробуйте также объяснить, что вы пытаетесь сделать. Если проблема связана с моделью администратора, добавьте эту модель сюда. Добавьте строку, в которой вы отменили регистрацию модели администратора ... дайте нам больше подсказок, чтобы мы могли помочь вам быстрее и лучше   -  person marianobianchi    schedule 23.06.2012
comment
Я не добавлял модельного администратора. Я просто зарегистрировал модель Contact по умолчанию, которая поставляется с satchmo, и зарегистрировал ее снова. Он не регистрируется правильно или что-то в этом роде, потому что функция Contact._meta.get_parent_list () не генерирует должным образом.   -  person codygman    schedule 23.06.2012
comment
Я обновил вопрос и все упростил в одну задачу. Я также предоставил всю необходимую информацию, чтобы воспроизвести проблему самостоятельно.   -  person codygman    schedule 23.06.2012
comment
В вашем INSTALLED_APPS стоит 'satchmo' выше 'satchmo_mod'?   -  person Maccesch    schedule 25.06.2012
comment
Нет satchmo, но satchmo_util и satchmo_store выше satchmo_mod, да.   -  person codygman    schedule 26.06.2012


Ответы (2)


Кажется, проблема в вашем UserTaxExemptInline. Вы не опубликовали, как это выглядит, но я предполагаю, что это выглядит так:

class UserTaxExemptInline(admin.TabularInline):
    model = Contact
    fk_name = "user"

а это должно выглядеть так:

class UserTaxExemptInline(admin.TabularInline):
    model = User
person Maccesch    schedule 26.06.2012
comment
Это по-прежнему верное решение. Может, тебе стоит задать новый вопрос об этой проблеме с циннией? - person Maccesch; 26.06.2012

См. _get_foreign_key в django / forms / models.py.

_get_foreign_key описание:

Finds and returns the ForeignKey from model to parent if there is one
(returns None if can_fail is True and no such field exists). If fk_name is
provided, assume it is the name of the ForeignKey field. Unles can_fail is
True, an exception is raised if there is no ForeignKey from model to
parent_model.

А теперь за исключением:

if fk_name:
        fks_to_parent = [f for f in opts.fields if f.name == fk_name]
        if len(fks_to_parent) == 1:
            fk = fks_to_parent[0]
            if not isinstance(fk, ForeignKey) or \
                    (fk.rel.to != parent_model and
                     fk.rel.to not in parent_model._meta.get_parent_list()):
                raise Exception("fk_name '%s' is not a ForeignKey to %s" % (fk_name, parent_model))

Я предполагаю, что вы неправильно настроили поля или отношения в своей модели.

Я где-то читал о том, как кто-то решил эту проблему, добавив pass в свой класс следующим образом:

class Whatever(x.x):
        pass
person Michael Frederick    schedule 27.06.2012