Obtenga datos en muchas relaciones en una sola fila

Estos son mis modelos

Cuadro de equipo

class Team(CommonModel):
    ****Other Fields****
    name = models.CharField()
    game = models.ManyToManyField(Game, through='Team_Game')

Mapper Table

class Team_Game(CommonModel):
    game = models.ForeignKey(Game, on_delete=models.CASCADE)
    team = models.ForeignKey(Team, on_delete=models.CASCADE)
    status = models.SmallIntegerField(default=1)
    class Meta:
        db_table = 'team_game'

Cuadro de juegos

class Game(CommonModel):
    name = models.CharField(max_length=128, blank=False, null=False, unique=True)
    status = models.SmallIntegerField(default=1)

Quiero recuperar equipo con id 1 y juego asociado con él Datos esperados: team.name, other_team_cols, [game_id1, game_id2]

Query:

team_data = Team.objects.filter(id=1).values('id', 'name', 'game__name')

Producto:

[
    {
        "id": "1",
        "name": 'abc',
        "game__name": "game1"
    },
    {
        "_packageID": "1",
        "name": "def",
        "game__name": "game2"
    }
]

Producto previsto:

{
        "id": "1",
        "name": 'abc',
        "game__name": ["gam1", "gam2"]
}

Pregunta hecha hace 3 años, 4 meses, 29 días - Por devdynamo


3 Respuestas:

  • Declare un array iterate el bucle y almacenar los valores de game__nameProducto

    team_data=[
        {
            "id": "1",
            "name": "abc",
            "game__name": "game1"
        },
        {
            "_packageID": "1",
            "names": "def",
            "game__name": "game2"
        }
    ]
    arr=[]
    
    for report in team_data :
        
        arr.append(report["game__name"])
    print(arr)
    

    Respondida el Dec 17, 2020 a las 18:50 - por logicluminary

    Votos positivos: 0 | Votos negativos: 0

  • Para obtener los datos en una sola fila con los juegos asociados al equipo, puedes seguir estos pasos:

    • Utiliza `values` en la consulta para obtener un diccionario en lugar de una lista de objetos.
    • Anexa la anotación `Prefetch` al campo `game`.
    • Utiliza la función `annotate` para agrupar los nombres de los juegos en una lista dentro de la misma fila.

    Aquí tienes una forma de ajustar la consulta para lograr esto:

    python
    from django.db.models import Prefetch, F, Value
    from django.db.models.functions import Concat
    
    team_data = Team.objects.filter(id=1).values('id', 'name').annotate(
        game_names=Concat(
            'game__name',
            output_field=CharField(),
            delimiter=Value(', '),
        )
    )
    
    

    La variable team_data ahora contendrá la información del equipo con los nombres de los juegos asociados en una lista

    Con esto, deberías obtener un resultado similar al siguiente:

    python
    {
        "id": "1",
        "name": 'abc',
        "game_names": ["game1", "game2"]
    }
    

    Espero que esta solución sea útil para ti. ¡Déjame saber si necesitas más ayuda!

    Respondida el Dec 18, 2020 a las 18:52 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Puedes utilizar la anotación de agrupación para lograr el resultado deseado:

    python
    from django.db.models import F, Func, Value
    
    team_data = Team.objects.filter(id=1).annotate(
        game_names=Func(F('game__name'), function='GROUP_CONCAT')
    ).values('id', 'name', 'game_names')
    

    Esto creará una nueva columna calculada llamada game_names que contiene una lista concatenada de todos los nombres de juegos asociados con el equipo. El resultado será similar a lo siguiente:

    
    [
        {
            "id": "1",
            "name": 'abc',
            "game_names": "game1, game2"
        }
    ]
    

    Respondida el Dec 18, 2020 a las 18:55 - por Gemini

    Votos positivos: 0 | Votos negativos: 0