|
1 from django.core.management.base import BaseCommand, CommandError |
|
2 from django.contrib.auth.models import User, Group |
|
3 from optparse import make_option |
|
4 from sys import stdout |
|
5 from csv import writer |
|
6 |
|
7 FORMATS = [ |
|
8 'address', |
|
9 'google', |
|
10 'outlook', |
|
11 'linkedin', |
|
12 'vcard', |
|
13 ] |
|
14 |
|
15 def full_name(first_name, last_name, username, **extra): |
|
16 name = u" ".join(n for n in [first_name, last_name] if n) |
|
17 if not name: return username |
|
18 return name |
|
19 |
|
20 class Command(BaseCommand): |
|
21 option_list = BaseCommand.option_list + ( |
|
22 make_option('--group', '-g', action='store', dest='group', default=None, |
|
23 help='Limit to users which are part of the supplied group name'), |
|
24 make_option('--format', '-f', action='store', dest='format', default=FORMATS[0], |
|
25 help="output format. May be one of '" + "', '".join(FORMATS) + "'."), |
|
26 ) |
|
27 |
|
28 help = ("Export user email address list in one of a number of formats.") |
|
29 args = "[output file]" |
|
30 label = 'filename to save to' |
|
31 |
|
32 requires_model_validation = True |
|
33 can_import_settings = True |
|
34 encoding = 'utf-8' # RED_FLAG: add as an option -DougN |
|
35 |
|
36 def handle(self, *args, **options): |
|
37 if len(args) > 1: |
|
38 raise CommandError("extra arguments supplied") |
|
39 group = options['group'] |
|
40 if group and not Group.objects.filter(name=group).count()==1: |
|
41 names = u"', '".join(g['name'] for g in Group.objects.values('name')).encode('utf-8') |
|
42 if names: names = "'" + names + "'." |
|
43 raise CommandError("Unknown group '" + group + "'. Valid group names are: " + names) |
|
44 if len(args) and args[0] != '-': |
|
45 outfile = file(args[0], 'w') |
|
46 else: |
|
47 outfile = stdout |
|
48 |
|
49 qs = User.objects.all().order_by('last_name', 'first_name', 'username', 'email') |
|
50 if group: qs = qs.filter(group__name=group).distinct() |
|
51 qs = qs.values('last_name', 'first_name', 'username', 'email') |
|
52 getattr(self, options['format'])(qs, outfile) |
|
53 |
|
54 def address(self, qs, out): |
|
55 """simple single entry per line in the format of: |
|
56 "full name" <my@address.com>; |
|
57 """ |
|
58 out.write(u"\n".join(u'"%s" <%s>;' % (full_name(**ent), ent['email']) |
|
59 for ent in qs).encode(self.encoding)) |
|
60 out.write("\n") |
|
61 |
|
62 def google(self, qs, out): |
|
63 """CSV format suitable for importing into google GMail |
|
64 """ |
|
65 csvf = writer(out) |
|
66 csvf.writerow(['Name', 'Email']) |
|
67 for ent in qs: |
|
68 csvf.writerow([full_name(**ent).encode(self.encoding), |
|
69 ent['email'].encode(self.encoding)]) |
|
70 |
|
71 def outlook(self, qs, out): |
|
72 """CSV format suitable for importing into outlook |
|
73 """ |
|
74 csvf = writer(out) |
|
75 columns = ['Name','E-mail Address','Notes','E-mail 2 Address','E-mail 3 Address', |
|
76 'Mobile Phone','Pager','Company','Job Title','Home Phone','Home Phone 2', |
|
77 'Home Fax','Home Address','Business Phone','Business Phone 2', |
|
78 'Business Fax','Business Address','Other Phone','Other Fax','Other Address'] |
|
79 csvf.writerow(columns) |
|
80 empty = [''] * (len(columns) - 2) |
|
81 for ent in qs: |
|
82 csvf.writerow([full_name(**ent).encode(self.encoding), |
|
83 ent['email'].encode(self.encoding)] + empty) |
|
84 |
|
85 def linkedin(self, qs, out): |
|
86 """CSV format suitable for importing into linkedin Groups. |
|
87 perfect for pre-approving members of a linkedin group. |
|
88 """ |
|
89 csvf = writer(out) |
|
90 csvf.writerow(['First Name', 'Last Name', 'Email']) |
|
91 for ent in qs: |
|
92 csvf.writerow([ent['first_name'].encode(self.encoding), |
|
93 ent['last_name'].encode(self.encoding), |
|
94 ent['email'].encode(self.encoding)]) |
|
95 |
|
96 def vcard(self, qs, out): |
|
97 try: |
|
98 import vobject |
|
99 except ImportError: |
|
100 print self.style.ERROR_OUTPUT("Please install python-vobject to use the vcard export format.") |
|
101 import sys |
|
102 sys.exit(1) |
|
103 for ent in qs: |
|
104 card = vobject.vCard() |
|
105 card.add('fn').value = full_name(**ent) |
|
106 if not ent['last_name'] and not ent['first_name']: |
|
107 # fallback to fullname, if both first and lastname are not declared |
|
108 card.add('n').value = vobject.vcard.Name(full_name(**ent)) |
|
109 else: |
|
110 card.add('n').value = vobject.vcard.Name(ent['last_name'], ent['first_name']) |
|
111 emailpart = card.add('email') |
|
112 emailpart.value = ent['email'] |
|
113 emailpart.type_param = 'INTERNET' |
|
114 out.write(card.serialize().encode(self.encoding)) |