2015-03-30 5 views
0

Я пытаюсь работать с моделью Django, созданной из базы данных mysql, которая имеет составные внешние ключи.Получить и установить ForeignKey прямо в Django

Мой models.py выглядит следующим образом.

class Make(models.Model): 
    idmake = models.IntegerField(primary_key=True) 
    make = models.CharField(max_length=20L, unique=True, blank=True) 
    def __unicode__(self): 
     return self.make  
    class Meta: 
     db_table = 'make' 

class Models(models.Model): 
    idmodels = models.IntegerField(primary_key=True, unique=True) 
    make = models.ForeignKey(Make, db_column='make', to_field='make') 
    model = models.CharField(max_length=45L, unique=True) 
    resource_type = models.CharField(max_length=7L) 
    def __unicode__(self): 
     return self.model  
    class Meta: 
     db_table = 'models' 

class Systems(models.Model): 
    idsystems = models.IntegerField(primary_key=True, unique=True) 
    make = models.ForeignKey(Models, null=True, db_column='make', blank=True, related_name='system_make') 
    model = models.ForeignKey(Models, null=True, db_column='model', to_field = 'model', blank=True, related_name='system_model') 
    serial_num = models.CharField(max_length=45L, blank=True) 
    service_tag = models.CharField(max_length=45L, blank=True) 
    mac = models.CharField(max_length=45L, unique=True) 

Теперь, когда я пытаюсь получить доступ к make поле системы я получаю ValueError.

>>> s = Systems.objects.get(pk=1) 
>>> s.model 
<Models: model11> 
>>> s.model.make 
<Make: make1> 
>>> s.make 
    Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "/usr/lib/python2.7/site-packages/django/db/models/fields/related.py", line 384, in __get__ 
     rel_obj = qs.get(**params) 
    File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 395, in get 
     clone = self.filter(*args, **kwargs) 
    File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 669, in filter 
     return self._filter_or_exclude(False, *args, **kwargs) 
    File "/usr/lib/python2.7/site-packages/django/db/models/query.py", line 687, in _filter_or_exclude 
     clone.query.add_q(Q(*args, **kwargs)) 
    File "/usr/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1271, in add_q 
     can_reuse=used_aliases, force_having=force_having) 
    File "/usr/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1202, in add_filter 
     connector) 
    File "/usr/lib/python2.7/site-packages/django/db/models/sql/where.py", line 71, in add 
     value = obj.prepare(lookup_type, value) 
    File "/usr/lib/python2.7/site-packages/django/db/models/sql/where.py", line 339, in prepare 
     return self.field.get_prep_lookup(lookup_type, value) 
    File "/usr/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 1003, in get_prep_lookup 
     return super(IntegerField, self).get_prep_lookup(lookup_type, value) 
    File "/usr/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 322, in get_prep_lookup 
     return self.get_prep_value(value) 
    File "/usr/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 997, in get_prep_value 
     return int(value) 
    ValueError: invalid literal for int() with base 10: 'make1' 

Мне не разрешено изменять таблицы и отношения в базе данных. Я очень новичок в Django, и я не могу понять, что является правильным решением для этой проблемы. В принципе, я хотел бы иметь возможность получить и установить поле make модели Systems. Может ли кто-нибудь направить меня на то, как я должен это делать? Мои первоначальные мысли заключались в том, что мне нужно было создать настраиваемое поле ForeignKey.

ответ

0

Я подозреваю, что ваши коды не соответствуют вашей схеме БД. В этой строке:

make = models.ForeignKey(Models, null=True, db_column='make', blank=True, related_name='system_make') 

Models должен быть Make, не так ли? А ваш Systems.model содержит to_field = 'model', вы отправили сообщение to_field='make' на Systems.make? Я предлагаю вам сбросить всю БД, запустите syncdb и снова создайте тестовые данные. Затем проверьте, не происходит ли ошибка.

еще несколько советов для вашего кода:

  • как ваш определенный to_field = 'model' и to_field='make', вы бы лучше рассмотреть добавить db_index=True для make и model полей. В противном случае производительность запроса может быть плохой, если ваш набор данных является большим

  • Если вы собираетесь установить Make.make и Models.model, чтобы быть уникальными и проиндексированными, они, по-видимому, квалифицируются как первичный ключ. Нужны ли в вашем случае idmake и idmodels?

  • primary_key=True гарантирует уникальность. unique=True является излишним

  • Конверсии Django использует уникальную форму для определения модели. I.e., использовать ModelSystem, а не ModelsSystems. Кроме того, обычно мы используем id, а не idmake, idmodels. Это только конверсии, до вас

+0

Спасибо за ваш ответ @ZZY. Я не совсем понимаю, что вы подразумеваете под «Модели», как предполагается, «Make»? В таблице 'Models' поле' make' является внешним ключом и связано с полем 'make' таблицы' Make'. В 'System.make' у меня не может быть' to_field = 'make'', потому что 'make' не уникален в' Models'. В 'Модели',' make' и 'model' уникальны вместе. – Sanket

+0

Я думал, что 'System.make' на самом деле указывает на модель' Make' – ZZY

+1

Если вам нужно «make» и «model» уникально вместе, в 'class Meta', определите' unique_together = («make», «model») '. [Doc] (https://docs.djangoproject.com/en/1.7/ref/models/options/#unique-together) – ZZY

0

Я обнаружил ответ скорее случайно. Хотел бы поделиться тем, кто сталкивается с подобной проблемой. Чтобы получить доступ к make непосредственно из Systems

>>> s = Systems.objects.get(pk=1) 
>>> s.model 
<Models: model11> 
>>> s.model.make 
<Make: make1> 
>>> s.make_id 
u'make1' 

Чтобы установить make непосредственно из Systems объекта

>>> s.make_id = Models.objects.get(model='model21').make.make 
>>> s.save() 
>>> s.make_id 
u'make2' 

быть предупрежден. Это не будет работать, если метод get моделей возвращает несколько или без объектов модели.Например, если мой Models стол был как:

enter image description here

затем

>>>> Models.objects.get(model='unknown').make.make 
Traceback (most recent call last): 
.... 
MultipleObjectsReturned: get() returned more than one Models -- it returned 2! 
>>> Models.objects.get(model='not known').make.make 
Traceback (most recent call last): 
.... 
DoesNotExist: Models matching query does not exist. 

Я упал программист должен быть осторожным об этих вещах.

EDIT От комментариев @ZZY к этому ответу и на его собственный ответ

class Models(models.Model): 
    idmodels = models.IntegerField(primary_key=True, unique=True) 
    make = models.ForeignKey(Make, db_column='make', to_field='make') 
    model = models.CharField(max_length=45L, unique=True) 
    resource_type = models.CharField(max_length=7L) 
    def __unicode__(self): 
     return self.model  
    class Meta: 
     db_table = 'models' 
     unique_together = ("make", "model") 

А также, поскольку model поле Models уникален, сценарий описанный мной не должно происходить в правильной таблице

+1

'objects.get' предназначен для возврата уникального результата. 'MultipleObjectsReturned' и' DoNotExist' работают точно так, как ожидалось в этом случае. Если в таблице есть несколько записей с одинаковым значением запроса, и вы хотите получить первый, используйте 'objects.filter (model = '...'). First()' [Doc] (https: // docs. djangoproject.com/en/1.7/ref/models/querysets/#first). И в вашем определении «Модели» поля 'model' уникальны. Таким образом, ваша БД не должна иметь дублирующее значение – ZZY

Смежные вопросы