Как узнать, является ли столбец модели внешним ключом?
Я динамически сохраняю информацию в базе данных в зависимости от запроса:
// table, id and column are provided by the request
table_obj = getattr(models, table)
record = table_obj.objects.get(pk=id)
setattr(record, column, request.POST['value'])
Проблема заключается в том, что request.POST ['value'] иногда содержит первичный ключ иностранной записи (т.е. целое число), тогда как Django ожидает, что значение столбца будет объектом типа ForeignModel:
Невозможно назначить "u'122": "ModelA.b" должен быть экземпляром "ModelB".
Теперь, есть ли элегантный способ динамически проверить, является ли b столбцом, содержащим внешние ключи и с какой моделью связаны эти ключи? (Чтобы я мог загружать чужую запись с помощью первичного ключа и назначать его ModelA?) Или не Django предоставляет такую информацию программисту, поэтому мне действительно нужно загрязнять руки и использовать isinstance() ключевой столбец?
Ответы
Ответ 1
Вы можете использовать get_field_by_name на объектах _meta models:
from django.db.models import ForeignKey
def get_fk_model(model, fieldname):
'''returns None if not foreignkey, otherswise the relevant model'''
field_object, model, direct, m2m = model._meta.get_field_by_name(fieldname)
if not m2m and direct and isinstance(field_object, ForeignKey):
return field_object.rel.to
return None
Предполагая, что у вас есть модельный класс MyModel, вы должны использовать это следующим образом:
fk_model = get_fk_model(MyModel, 'fieldname')
Ответ 2
Я столкнулся с одним и тем же вариантом использования, и принятый ответ не работал у меня напрямую. Я использую Django 1.2, если это уместно. Вместо этого я использовал метод get_field_by_name
следующим образом.
def get_foreign_keys(self):
foreign_keys = []
for field in self._meta.fields:
if isinstance(self._meta.get_field_by_name(field.name)[0], models.ForeignKey):
foreign_keys.append(field.name)
if not foreign_keys:
return None
return foreign_keys
Этот метод определяет внутри класса. Для моего случая мне нужны имена полей ForeignKey. Ура!
Ответ 3
Простой один лайнер, чтобы найти все отношения с другими models
, которые существуют в model
:
In [8]: relations = [f for f in Model._meta.get_fields() if (f.one_to_many or f.one_to_one) and f.auto_created]
Выше будет дано list
всего models
с их relations
.
Пример:
In [9]: relations
Out[9]:
[<ManyToOneRel: app1.model1>,
<ManyToOneRel: app2.model1>,
<OneToOneRel: app1.model2>,
<OneToOneRel: app3.model5>,
<OneToOneRel: app5.model1>]
Ответ 4
Изучите поля "ModelChoiceField". Могут ли они решить вашу проблему, вводя внешние ключи в формы для вас; вместо того, чтобы делать это самостоятельно.
http://docs.djangoproject.com/en/1.1/ref/forms/fields/#fields-which-handle-relationships
record = forms.ModelChoiceField(queryset=table_obj.objects.all())