Ryan
Ryan

Reputation: 427

Looping through to create a tuple

I'm attempting to implement the mass mail send out.

Here is the mass mail doc: Just a link to the Django Docs

In order to achieve this I need create this tuple:

datatuple = (
    ('Subject', 'Message.', '[email protected]', ['[email protected]']),
    ('Subject', 'Message.', '[email protected]', ['[email protected]']),
)

I query the ORM for some recipients details. Then I would imagine there's some looping involved, each time adding another recipient to the tuple. All elements of the message are the same except for username and email.

So far I have:

recipients = notification.objects.all().values_list('username','email')
# this returns [(u'John', u'[email protected]'), (u'Jane', u'[email protected]')]
for recipient in recipients:    
     to = recipient[1]               #access the email
     subject = "my big tuple loop"
     dear = recipient[0]              #access the name  
     message = "This concerns tuples!"
     #### add each recipient to datatuple
     send_mass_mail(datatuple)

I've been trying something along the lines of this : SO- tuple from a string and a list of strings

Upvotes: 3

Views: 2297

Answers (2)

craigts
craigts

Reputation: 3077

Just a little bit of cleanup needed here:

1) actually build the tuple in the loop (this is a bit tricky since you need the extra comma to ensure that a tuple is appended and not the values from the tuple)

2) move the send_mass_mail call outside the loop

This should be working code:

recipients = notification.objects.all().values_list('username','email')
# this returns [(u'John', u'[email protected]'), (u'Jane', u'[email protected]')]
datatuple = []
for recipient in recipients:    
    to = recipient[1]               #access the email
    subject = "my big tuple loop"
    dear = recipient[0]              #access the name  
    message = "This concerns tuples!"
    #### add each recipient to datatuple
    datatuple.append((subject, message, "[email protected]", [to,]),)
send_mass_mail(tuple(datatuple))

EDIT: jpmc26's technique is definitely more efficient, and if you're planning to have a large email list to send to you should use that. Most likely you should use whichever code makes the most sense to you personally so that when your requirements change you can easily understand how to update.

Upvotes: 1

jpmc26
jpmc26

Reputation: 29934

If I understand correctly, this is pretty simple with a comprehension.

emails = [
    (u'Subject', u'Message.', u'[email protected]', [address])
    for name, address in recipients
]
send_mass_mail(emails)

Note that we leverage Python's ability to unpack tuples into a set of named variables. For each element of recipients, we assign its zeroth element to name and its first element to address. So in the first iteration, name is u'John' and address is u'[email protected]'.

If you need to vary the 'Message.' based on the name, you can use string formatting or any other formatting/templating mechanism of your choice to generate the message:

emails = [
    (u'Subject', u'Dear {}, Message.'.format(name), u'[email protected]', [address])
    for name, address in recipients
]

Since the above are list comprehensions, they result in emails being a list. If you really need this to be a tuple instead of a list, that's easy, too:

emails = tuple(
    (u'Subject', u'Message.', u'[email protected]', [address])
    for name, address in recipients
)

For this one, we're actually passing a generator object into the tuple constructor. This has the performance benefits of using a generator without the overhead of creating an intermediate list. You can do that pretty much anywhere in Python where an iterable argument is accepted.

Upvotes: 4

Related Questions