es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Agrupación de los nombres de los campos del modelo en Django.

Tengo una vista detallada compleja donde se renderiza dinámicamente una gran cantidad de datos variados. Mi modelo tiene cientos de campos, muchos de los cuales están relacionados entre sí. Me gustaría poder agrupar varios de estos campos para realizar consultas. ¿Existe alguna manera de hacer esto?

Para seleccionar campos específicos y agruparlos, mi enfoque actual ha sido usar extensiones de palabras para los nombres de campo que sean comunes para cada grupo. Por ejemplo, los nombres de los campos como:

ampicillin = models.CharField(...)
ciprofloxacin = models.CharField(...)
...

se convierten en:

ampicillin_antimicro = models.CharField(...)
ciprofloxacin_antimicro = models.CharField(...)
...

La idea es luego crear una lista de nombres de campo y acceder a grupos específicos de campos utilizando una búsqueda de subcadenas. ¿Cómo puedo hacer esto? A continuación, se presenta un resumen de mis intentos y problemas hasta ahora.

Usando _meta

Puedo acceder a la información de nombre de campo de modelo sin procesar usando _meta:

all_fields = []
for field in MyModel._meta.fields:
    all_fields.append(field)

Esto da una lista como:

[<django.db.models.fields.CharField: ampicillin_antimicro>, 
<django.db.models.fields.CharField: ciprofloxacin_antimicro>, ...]

Pero no he podido encontrar cómo extraer la información que necesito de esto.

Usando meta y field.get_attname_column()[0]

Puedo crear una lista de objetos de nombre de campo como cadenas:

field_names = []
for field in MyModel._meta.fields:
    newfield = field.get_attname_column()[0]
    field_names.append(newfield)

Esto da como resultado una lista adjunta field_names:

['ampicillin_antimicro', 'ciprofloxacin_antimicro', ...]

Agregar una búsqueda de subcadenas me permite obtener el subconjunto de nombres de campo que deseo. Por ejemplo, al usar la cadena de búsqueda “antimic”:

field_names = []
search_string = "antimic"
for field in Bacteria._meta.fields:
    newfield = field.get_attname_column()[0]
    if search_string in newfield:
        field_names.append(newfield)

Queda aislado los nombres de campo que contienen la “extensión de palabra de grupo” correctamente. Todo bien, excepto que ya no puedo acceder al valor real de los nombres de campo, solo el nombre del campo en sí. Cuando la lista se itera en la plantilla, solo se devuelve el nombre del campo.

<li>
    {% if field_names %}
    <i style="color: blue;"><b>A</b>ntibiotic tolerance:</i>
    {% for f in field_names %}
    {{f|default_if_none:''}}
    {% endfor %}
    {% endif %}
</li>

Usando tuplas y diccionarios

Si transformo la lista en tuPLE Y DICTo y trato de usar el diccionario resultante:

field_names = []
field_names_dict = dict(zip(field_names, field_names))
field_names_tuple = tuple(field_names_dict)
for key, val in field_names_tuple.items():
    if val is not None:
        field_names.append(val)

Sigo obteniendo el nombre como resultado, no el valor.

Diccionarios codificados en duro

Hasta ahora, lo único que funciona es codificar en duro un diccionario específico para cada consulta en la vista detallada:

model = Model.objects.all()
antibiotics = []
antibiotics_dict = {'amp': model.ampicillin_antimicro, 
          'cipro': model.ciprofloxacin_antimicro, ...}
for key, val in antibiotics_dict.items():
    if val is not None:
        antibiotics.append(val)

Aunque esto funciona bien, se complica cuando los diccionarios son grandes y no me gusta la idea de codificar en duro los pares clave-valor. Siento que estoy muy cerca de una solución, pero obviamente me falta algo porque soy un novato en la codificación. ¿Alguien puede ayudarme? ¡Saludos!

La solución de Shelvington

Siguiendo la sugerencia del Sr. Shelvington, he modificado el código de la siguiente manera:

search_string = "antimic"
field_names = [f.name for f in Bacteria._meta.get_fields() 
    if search_string in f.name]
prelist = get_object_or_404(Bacteria.objects.values(*field_names), slug=slug)
for key, val in prelist.items():
    if val is not None:
        antibiotics = prelist

Tenga en cuenta que solo hay dos variables (la subcadena y “antibiotics”). El código es reutilizable para subcadenas y creación de diccionarios adicionales. Luego, cambié la plantilla para que se ajustara:

<li>
    {% if antibiotics %}
    <i style="color: blue;"><b>A</b>ntibiotic tolerance:</i>
    {% for key, val in antibiotics.items %}
    {{ val }}
    {% endfor %}
    {% endif %}
</li>

Nota adicional: he iterado sobre el diccionario dentro de la vista para que el título del texto HTML desaparezca si no se encuentran valores para la iteración.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Sí, existe una forma de agrupar campos para realizar consultas. Un enfoque es utilizar una extensión de palabra común para los nombres de campo dentro de un grupo y después crear una lista de nombres de campo en la vista basada en una búsqueda de subcadena. La lista resultante se puede convertir en un diccionario, con las llaves siendo los nombres de campo y los valores siendo los valores reales de los campos. Este diccionario luego se puede pasar al contexto y renderizar en la plantilla mediante la iteración. Una forma más eficiente de obtener la lista de nombres de campo es mediante el atributo _meta del modelo para obtener los nombres de campo y luego filtrar según la búsqueda de subcadena utilizando una comprensión de lista. La lista resultante de nombres de campo luego se puede pasar a un método values() para el modelo, el cual devuelve una consulta que contiene solo los campos seleccionados. Esta consulta se puede convertir en un diccionario que se puede pasar al contexto y renderizar en la plantilla.

Comments are closed.