¿Cómo puedo obtener dos distintos registros aleatorios utilizando Django? He visto preguntas acerca de cómo conseguir uno, pero tengo que sacar dos registros aleatorios y que deben ser diferentes.

6 Comentarios

  1. 24

    Si se especifica el operador aleatorio en el ORM, estoy bastante seguro de que le dará diferentes resultados al azar ¿no es así?

    MyModel.objects.order_by('?')[:2] # 2 random results.
    • Sí funciona esto. Yo estaba sumando .get() al final de la cual estaba causando el error.
    • Esto puede tener problemas de rendimiento. Consulte Manganeez la respuesta de para obtener más detalles
    • También este tipo de obtención de mayo devuelve los registros duplicados
  2. 97

    La order_by('?')[:2] solución sugerida por otras respuestas es en realidad una extraordinaria mala cosa a hacer para las tablas que tienen un gran número de filas. El resultado es un ORDER BY RAND() consulta SQL. Como ejemplo, he aquí cómo mysql maneja que (la situación no es muy diferente de otras bases de datos). Imagina que tu tabla tiene mil millones de filas:

    1. Para lograr ORDER BY RAND(), se necesita una RAND() columna para ordenar.
    2. Para hacer eso, se necesita una nueva tabla (la tabla existente no tiene ningún tipo de columna).
    3. A hacer eso, mysql crea una nueva tabla temporal con las nuevas columnas y las copias existentes de mil MILLONES de FILAS DE DATOS.
    4. Como lo hace, lo hace como usted lo pidió, y se ejecuta la función rand() para cada fila para llenar ese valor. Sí, he instruido a mysql para GENERAR mil MILLONES de NÚMEROS ALEATORIOS. Que lleva un tiempo. 🙂
    5. Un par de horas/días más tarde, cuando se hace, ahora tiene que ordenar. Sí, he instruido a mysql para CLASIFICAR a los mil MILLONES de FILA, en el PEOR de los CASOS ORDENADOS de la TABLA (el peor de los caso, porque la clave de ordenación es aleatorio).
    6. De unos días/semanas más tarde, cuando se hace, fielmente agarra los dos miseros filas que realmente se necesita y los devuelve para usted. Buen trabajo. 😉

    Nota: sólo para un poco más de salsa, ser conscientes de que mysql inicialmente intentará crear la tabla temporal en la memoria RAM. Cuando está agotado, se pone todo en suspenso para copiar toda la cosa en el disco, por lo que conseguir una cuchilla toque de un I/O cuello de botella para casi todo el proceso.

    Escépticos deberían mirar la consulta generada para confirmar que es ORDER BY RAND() Google para «order by rand()» (con las comillas).

    Una solución mucho mejor es el comercio que uno realmente caro consulta para tres baratos (límite/desplazamiento en lugar de ORDER BY RAND()):

    import random
    last = MyModel.objects.count() - 1
    
    index1 = random.randint(0, last)
    # Here's one simple way to keep even distribution for
    # index2 while still gauranteeing not to match index1.
    index2 = random.randint(0, last - 1)
    if index2 == index1: index2 = last
    
    # This syntax will generate "OFFSET=indexN LIMIT=1" queries
    # so each returns a single record with no extraneous data.
    MyObj1 = MyModel.objects.all()[index1]
    MyObj2 = MyModel.objects.all()[index2]
    • +1 muy agradable explicación y un gran ejemplo! Tener en cuenta en la mayoría de los motores de almacenamiento (nada pero MySQL MyISAM?) se ha de recorrer todo el conjunto de datos para obtener la tabla de count así que esto puede ser bastante caro también. Obtención de registros aleatorios es bastante caro, lo que hay que hacer en general.
    • Sí, estoy tratando de recuperar 1000 registros aleatorios. Este método es brutal. Insostenible realmente.
    • ¿por qué no tratar de conseguir todos mymodel objetos y uso de la len(), como obj = MyModel.objetos.todos() índice = randint(0,len(obj)-1)
    • Lo siento si significaba que como una broma – sólo en caso de: el más grande de la tabla, el peor de la idea de ir a buscar todos los objetos a la vez. Usted realmente no quiere crear una instancia de un mil millones de objetos de manera que se puede seleccionar al azar dos queridos.
    • Quiero decir que las order_by(‘?’) era insostenible, no la solución aquí. Siento ser claro, mi mal.
    • este código dará dos veces el mismo si index1 es el último
    • Yo no lo creo – digo 10 elementos, es decir, 0-9, así, el pasado = 9, y index1 también obtiene 9 por su escenario. Luego index2 = randint(0, 8), por lo que se obtiene un número aleatorio entre 0 y 8 inclusive. Ya que esto excluye a las 9, no es posible que index1 y index2 a ser igual, por lo que queda como está, con 9 y algún número de 0-8, respectivamente.
    • Podría usted hacer algo incluso más inteligente como el hash de un uuid en, digamos, 1000 cubos y luego seleccionar al azar uno de los cubos, y luego hacer una segunda aleatorio para elegir los objetos en el cubo? (Tal vez esto es más inteligente, tal vez no. Pero necesito algo muy eficaces).
    • No estoy seguro de lo que la victoria es para hacer eso. A menos que, por supuesto, su almacenamiento backend está optimizado para este tipo de acceso de alguna manera, en cuyo caso más poder para ya! 🙂
    • Y para conseguir n diferentes números aleatorios, uso random.sample(range(0, last), n).

  3. 8

    Para el futuro de los lectores.

    Obtener la lista de los identificadores de todos los registros:

    my_ids = MyModel.objects.values_list('id', flat=True)
    my_ids = list(my_ids)

    Luego de la selección n aleatoria de números de identificación de todos los anteriores id:

    n = 2
    rand_ids = random.sample(my_ids, n)

    Y obtener registros de estos identificadores:

    random_records = MyModel.objects.filter(id__in=rand_ids)
    • Gracias, esta solución funcionó para mí. Sólo una nota, sin embargo, yo tenía que hacer my_ids = list(my_ids), de lo contrario tengo un TypeError de random.sample. También he implementado una forma de manejar my_ids tener menos registros que mi tamaño de la muestra, haciendo sample_size = min(len(my_ids), 10).
    • tu comentario me salvó, gracias
    • Esta realidad puede ser bastante caro en la transferencia de datos y el uso de la memoria. Devuelve la lista de todos los Id de la tabla, por lo que puede seleccionar 2 (o n). Que puede obtener prohibitivo si la tabla es grande.
  4. 6

    Object.objects.order_by('?')[:2]

    Esto volvería al azar dos-ordenó registros. Usted puede agregar

    distinct()

    si no hay registros con el mismo valor en su conjunto de datos.

  5. 3

    Acerca de muestreo de n valores aleatorios a partir de una secuencia, el azar lib podría ser utilizado,

    random.Random().sample(range(0,last),2) 

    obtendrá 2 muestras al azar de entre los elementos de la secuencia, de 0 a última-1

  6. 0

    HTML:

    from django.db import models
    from random import randint
    from django.db.models.aggregates import Count
    
    
    class ProductManager(models.Manager):
        def random(self, count=5):
            index = randint(0, self.aggregate(count=Count('id'))['count'] - count)
            return self.all()[index:index + count]

    Usted puede obtener diferentes número de objetos.

Dejar respuesta

Please enter your comment!
Please enter your name here