@@ -33,17 +33,10 @@ def total_ballots(self):
3333 return self .ballot_set .count ()
3434
3535 def total_votes (self ):
36- v = 0
37- for c in self .choice_set .all ():
38- v += c .votes ()
39- return v
36+ return Vote .objects .filter (choice__poll = self ).count ()
4037
4138 def voters (self ):
42- v = []
43- ballots = self .ballot_set .all ()
44- for ballot in ballots :
45- v .append (ballot .user )
46- return v
39+ return list (self .ballot_set .values_list ("user" , flat = True ).distinct ())
4740
4841 def __unicode__ (self ):
4942 return self .question
@@ -56,43 +49,40 @@ def add_choices(self, ids, text_data, link_data):
5649 self .choice_set .create (choice_text = text_data [n ], choice_link = link_data [n ])
5750
5851 def update_choices (self , ids , text_data , link_data ):
59- for u in ids :
60- c = Choice . objects . get ( id = u )
61- setattr ( c , " choice_text" , text_data [u ])
62- if not (c .choice_link is None and len (link_data [u ]) == 0 ):
63- setattr ( c , " choice_link" , link_data [u ])
64- c . save ( )
52+ choices = Choice . objects . filter ( id__in = ids )
53+ for choice in choices :
54+ choice . choice_text = text_data [choice . id ]
55+ if not (choice .choice_link is None and len (link_data [choice . id ]) == 0 ):
56+ choice . choice_link = link_data [choice . id ]
57+ Choice . objects . bulk_update ( choices , [ "choice_text" , "choice_link" ] )
6558
6659 def delete_choices (self , ids ):
67- for d in ids :
68- cho_d = Choice .objects .get (id = d )
69- cho_d .delete ()
70- """
71- Recommended by RelatedManager, but hasn't worked locally
72- self.choice_set.remove(cho_d)
73- """
60+ Choice .objects .filter (id__in = ids , poll = self ).delete ()
7461
7562 def send_vote_invitations (self , emails ):
76- # Get all the email Ids to store in the DB.
77- email_list = []
78- for email in emails .split ("," ):
79- if re .match (r"([^@|\s]+@[^@]+\.[^@|\s]+)" , email .strip ()):
80- email_list .append (email .strip ())
81- email_list = list (set (email_list ))
82-
83- # Add in the vote invitation info, if any.
84- for email in email_list :
85- vi = VoteInvitation (
86- email = email ,
87- sent_date = timezone .now (),
88- poll = self ,
89- key = VoteInvitation .generate_key (),
63+ # Get unique valid email addresses
64+ email_list = {
65+ email .strip ()
66+ for email in emails .split ("," )
67+ if re .match (r"([^@|\s]+@[^@]+\.[^@|\s]+)" , email .strip ())
68+ }
69+
70+ # Create all invitations at once
71+ now = timezone .now ()
72+ invitations = [
73+ VoteInvitation (
74+ email = email , sent_date = now , poll = self , key = VoteInvitation .generate_key ()
9075 )
91- vi .save ()
92- vi .send_email ()
76+ for email in email_list
77+ ]
78+ created_invitations = VoteInvitation .objects .bulk_create (invitations )
79+
80+ # Send emails after creation
81+ for invitation in created_invitations :
82+ invitation .send_email ()
9383
9484 def invited_emails (self ):
95- return [ str ( vi . email ) for vi in self .voteinvitation_set .all ()]
85+ return list ( self .voteinvitation_set .values_list ( "email" , flat = True ))
9686
9787 def add_tags (self , tags ):
9888 for tagtext in tags :
@@ -110,7 +100,19 @@ def delete_tags(self, tags):
110100 self .polltag_set .remove (tag )
111101
112102 def all_tags (self ):
113- return ("," ).join ([str (t .tag_text ) for t in self .polltag_set .all ()])
103+ from django .db .models import CharField , Value
104+ from django .db .models .functions import Concat
105+
106+ return (
107+ self .polltag_set .annotate (
108+ str_tag_text = Cast ("tag_text" , CharField ())
109+ ).aggregate (
110+ tags = Concat ("str_tag_text" , output_field = CharField (), separator = "," )
111+ )[
112+ "tags"
113+ ]
114+ or ""
115+ )
114116
115117 def __str__ (self ):
116118 return self .question
@@ -229,10 +231,20 @@ class PollTag(models.Model):
229231
230232 @classmethod
231233 def topTagsPercent (cls , count ):
232- pollTags = cls .objects .all ()
233- topTags = sorted (pollTags , key = lambda x : x .polls .count (), reverse = True )[:count ]
234- sumTotalPolls = sum ([t .polls .count () for t in topTags ])
235- topTagsDict = {}
236- for t in topTags :
237- topTagsDict [t .tag_text ] = float (t .polls .count ()) / sumTotalPolls * 100
238- return topTagsDict
234+ from django .db .models import Count , F , FloatField
235+ from django .db .models .functions import Cast
236+
237+ # Get top tags with their poll counts
238+ top_tags = cls .objects .annotate (poll_count = Count ("polls" )).order_by (
239+ "-poll_count"
240+ )[:count ]
241+
242+ # Calculate total polls for percentage
243+ total_polls = sum (tag .poll_count for tag in top_tags )
244+
245+ # Calculate percentages
246+ return (
247+ {tag .tag_text : (tag .poll_count / total_polls * 100 ) for tag in top_tags }
248+ if total_polls > 0
249+ else {}
250+ )
0 commit comments