Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

202
Vistas
Hacer que Django ORM obtenga propiedades automáticamente

Digamos que tengo un modelo de publicación como este:

 class Post(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) text_content = models.CharField() @property def comment_count(self): return self.comments.count()

Digamos que necesito obtener todos los datos para la publicación con ID 3. Sé que puedo recuperar al usuario junto con la publicación en una consulta, haciendo Post.objects.select_related('user').get(pk=3) , permitiéndome guardar una consulta. Sin embargo, ¿hay alguna manera de obtener automáticamente comment_count también?

Sé que podría usar Post.objects.annotate(comment_count=Count('comments')) (que requerirá que elimine la propiedad o cambie el nombre de la anotación, ya que habría un AttributeError ), sin embargo, ¿es posible hacer que el ORM haga esa parte automáticamente, ya que la propiedad está declarada en el modelo?

Aunque podría simplemente agregar el .annotate , esto puede volverse muy tedioso cuando hay varias propiedades y claves externas que deben buscarse en varios lugares.

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Tal vez esta no sea una solución perfecta para usted, pero puede encontrar algo similar que funcione. Puede agregar un administrador de objetos personalizado, consulte los documentos

Entonces podría agregar un método como with_comment_count() . O si siempre desea anotar, puede modificar el conjunto de consultas inicial .

 class PostManager(models.Manager): def with_comment_count(self): return self.annotate( comment_count=Count('comments') ) # Or this to always annotate def get_queryset(self): return super().get_queryset().annotate( comment_count=Count('comments') ) class Post(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) text_content = models.CharField() objects = PostManager()

Entonces podrías consultar así.

 post = Post.objects.get(pk=1).with_comment_count() post.comment_count
over 4 years ago · Santiago Trujillo Denunciar

0

¡Gracias a Felix Eklöf logré hacerlo funcionar! Como se especifica en la pregunta, esto fue en el caso en el que había varias propiedades/claves externas que necesitaban captación previa y, como tal, se necesitaba la capacidad de "encadenar" la captación previa. Esto no es posible encadenando métodos de PostManager , ya que no devuelven un PostManager sino un QuerySet , sin embargo, se me ocurrió una función que almacena en caché todo lo que se le pide que almacene en caché de una vez, evitando la necesidad de encadenar métodos:

 class PostManager(models.Manager): def caching(self, *args): query = self.all() if 'views' in args: query = query.annotate(view_count=Count('views')) if 'comments' in args: query = query.annotate(comment_count=Count('comments')) if 'user' in args: query = query.select_related('user') if 'archives' in args: query = query.prefetch_related('archives') return query class Post(models.Model): objects = PostManager() ... # caching can then be added by doing, this, for instance: Post.objects.caching('views', 'user', 'archives').get(id=3)

Tenga en cuenta que para que esto funcione, también tuve que cambiar @property a @cached_property , lo que permitió que el ORM reemplazara el valor y permitiera el almacenamiento en caché adecuado con el mismo nombre.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda