Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

195
Views
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 answers
Answer question

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!