2010-04-09 11 views
11

Estoy almacenando información de forma dinámica en la base de datos en función de la solicitud:¿Cómo saber si la columna de un modelo es una clave externa?

// 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']) 

El problema es que request.POST [ 'valor'] a veces contiene la clave principal de un registro extranjero (es decir, un entero), mientras que Django espera el valor de la columna es un objeto de tipo ForeignModel:

No se puede asignar "u'122" ":" ModelA.b "debe ser una instancia" ModelB ".

Ahora, ¿hay una manera elegante de comprobar dinámicamente si b es una columna que contiene claves externas y con qué modelo están vinculadas estas claves? (¿Para poder cargar el registro en el extranjero por su clave principal y asignarlo a ModelA?) O Django no proporciona información como esta al programador, así que realmente tengo que ensuciarme las manos y usar isinstance() en el extranjero. columna clave?

Respuesta

13

Puede utilizar get_field_by_name en los modelos _meta objetar:

 

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 
 

Suponiendo que tenía una clase del modelo MyModel puede utilizar esta así:

 

fk_model = get_fk_model(MyModel, 'fieldname') 
 
+0

¿No se sobrescribirá el 'modelo' de entrada con la asignación' field_object, model_direct, m2m = ... '? – alvas

+0

Supongo, pero nunca se usa de nuevo, así que no es un gran problema. –

0

Explore los campos "ModelChoiceField". ¿Pueden resolver su problema al poner claves foráneas en formularios para usted? en lugar de hacerlo tú mismo.

http://docs.djangoproject.com/en/1.1/ref/forms/fields/#fields-which-handle-relationships

record = forms.ModelChoiceField(queryset=table_obj.objects.all()) 
+0

Gracias, lo que haría si no tiene requisitos especiales: Todos mis "formas" son formas de edición en línea-JS-Powered. Eso hace que sea todo un desafío generarlos con la API de Django, uno que no estoy dispuesto a tomar. – balu

1

I encontré el mismo caso de uso, y la respuesta aceptada no funcionó para mí dir ectly. Estoy usando Django 1.2 si es relevante. En cambio, utilicé el método get_field_by_name de la siguiente manera.

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 

Este es un método para definir dentro de una clase. Para mi caso, lo que necesitaba eran los nombres de los campos ForeignKey. ¡Aclamaciones!

1

simple un trazador de líneas para encontrar todas las relaciones con otras models que existen en un 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] 

encima dará una list de toda la models con su relations.

Ejemplo:

In [9]: relations 
Out[9]: 
[<ManyToOneRel: app1.model1>, 
<ManyToOneRel: app2.model1>, 
<OneToOneRel: app1.model2>, 
<OneToOneRel: app3.model5>, 
<OneToOneRel: app5.model1>] 
Cuestiones relacionadas