Quiero crear una página donde pueda mostrar las propiedades de sus imágenes en una página web.

Actualmente, el modelo de Mi propiedad se ve así (se eliminan algunos códigos):

class Property(models.Model):
    PROPERTY_TYPE = (('Room', 'Room'), ('House', 'House'))
    type = models.CharField(max_length=100, choices=PROPERTY_TYPE)
    title = models.CharField(max_length=100, db_index=True)
    beds = models.IntegerField(null=True, blank=True)
    price = models.IntegerField()
    payment_term = models.CharField(choices=PAYMENT_TERM_CHOICES, max_length=50)

Y modelo de imagen

class Picture(models.Model):
    location = models.CharField(max_length=255)
    owner = models.ForeignKey(User)
    active = models.BooleanField(default=True)
    alt = models.CharField(max_length=100)
    parent_property = models.ForeignKey(Property, null=True)
    timestamp = models.DateTimeField(default=timezone.now)

En mi opinión, obtengo la lista de objetos como este:

room_list = Property.objects.all().filter(type='Room').order_by('timestamp')[6]

Al ejecutar un bucle for a través de la lista room_list aprobada, quiero hacer referencia a ella como

Lista de la habitación de la primera imagen de la imagen

Intenté revisar la documentación oficial de Django sobre las relaciones Uno a Muchos, pero parece que no puedo seguirla.

¿Cómo haría para lograr esto?

1
Dan 4 sep. 2014 a las 00:51

3 respuestas

La mejor respuesta

Aunque puedes usar algo como esto:

{% for room in room_list %}
   <img src="{{ room.picture_set.first }}"/>
{% endfor %}

No lo recomiendo La razón es que, para cada elemento room_list, usted va a la base de datos para el elemento Picture. Entonces, cuando tenga 30 elementos, por ejemplo, bombardeará la base de datos con 31 consultas.

Lo más fácil que puede hacer es agregar otro campo para su Modelo de propiedad, por ejemplo, default_picture, que será FK a la imagen con Ninguno como predeterminado. Después de guardar la imagen, debe completar el ID de esa imagen (qué imagen usa y cómo maneja los registros sin imagen está en su lógica comercial). Luego obtienes los registros de esta manera:

room_list = Property.objects.filter(
    type='Room'
).select_related(
    'default_picture'
).order_by('timestamp')[6]

Esto dará como resultado una sola consulta. Claro que hay otros métodos para lograr lo mismo, pero estos son más complicados.

SUGERENCIA: no necesita realizar un pedido por campo de marca de tiempo (a menos que modifique su valor), pero puede usar la ID tal como se crea en secuencia. Esta es una operación más barata (al menos en Postgres).

Actualización: como sugirió @JamesLin, podría usar algo como esto:

room_list = Property.objects.filter(
    type='Room'
).prefetch_related(
    'picture_set'
)

Esto se traducirá en dos consultas, una para la lista de propiedades y la segunda para todos los registros de imágenes relacionados con elementos de propiedades extraídos (Django los conectará mediante programación). Esto es bastante flojo para el programador, pero tenga en cuenta que está cargando todos los registros de imágenes por propiedad. Pero esta es ciertamente una mejor solución que picture_set y más fácil de implementar que mi primera sugerencia (no significa automáticamente que sea una mejor solución).

1
Bruce 4 sep. 2014 a las 09:38

Simplemente contesta tu pregunta aquí:

{% for room in room_list %}
   <img src="{{ room.picture_set.first }}"/>
{% endfor %}

Luego hay un capítulo completo para optimizarlo.

Por cierto:

Esta consulta solo te dará la séptima casa

room_list = Property.objects.all().filter(type='Room').order_by('timestamp')[6]

Probablemente quieras [:6]

Además, no necesita llamar a .all() antes de .filter()

room_list = Property.objects.filter(type='Room').order_by('timestamp')[:6]
0
James Lin 3 sep. 2014 a las 21:47

room_list.picture_set.all() es cómo puedes acceder al conjunto de imágenes. Para obtener el primero, puede acceder a room_list.picture_set.first(). Versión de plantilla: {{ room_list.picture_set.first }}.

Documentación relevante de Django.

primera documentación

0
rbonick 3 sep. 2014 a las 21:21