Mercurial > public > sg101
comparison gpp/legacy/management/commands/import_old_users.py @ 290:64c188a9d31f
Adding a legacy app to contain management commands to convert the old data to the new database format. This first commit has the import_old_users command.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Fri, 24 Dec 2010 05:28:58 +0000 |
parents | |
children | a6357f2bcbbc |
comparison
equal
deleted
inserted
replaced
289:0dd8989abef2 | 290:64c188a9d31f |
---|---|
1 """ | |
2 import_old_users.py - For importing users from SG101 1.0 as csv files. | |
3 """ | |
4 from __future__ import with_statement | |
5 import csv | |
6 import optparse | |
7 import re | |
8 import sys | |
9 from datetime import datetime | |
10 | |
11 import postmarkup | |
12 | |
13 from django.core.management.base import LabelCommand, CommandError | |
14 from django.contrib.auth.models import User | |
15 | |
16 import bio.models | |
17 from legacy.phpbb import unphpbb | |
18 from legacy.html2md import MarkdownWriter | |
19 | |
20 TIME_ZONES = { | |
21 '-5': 'US/Eastern', | |
22 '-6': 'US/Central', | |
23 '-7': 'US/Mountain', | |
24 '-8': 'US/Pacific', | |
25 } | |
26 USERNAME_RE = re.compile(r'^[\w.@+-]+$') | |
27 USERNAME_LEN = (1, 30) # min & max length values | |
28 | |
29 | |
30 def _valid_username(username): | |
31 """ | |
32 Return true if the username is valid. | |
33 """ | |
34 return (USERNAME_LEN[0] <= len(username) <= USERNAME_LEN[1] and | |
35 USERNAME_RE.match(username)) | |
36 | |
37 | |
38 def _break_name(name): | |
39 """ | |
40 Break name into a first and last name. | |
41 Return a 2-tuple of first_name, last_name. | |
42 """ | |
43 parts = name.split() | |
44 n = len(parts) | |
45 if n == 0: | |
46 t = '', '' | |
47 elif n == 1: | |
48 t = parts[0], '' | |
49 else: | |
50 t = ' '.join(parts[:-1]), parts[-1] | |
51 return t[0][:USERNAME_LEN[1]], t[1][:USERNAME_LEN[1]] | |
52 | |
53 | |
54 class Command(LabelCommand): | |
55 args = '<filename filename ...>' | |
56 help = 'Imports users from the old database in CSV format' | |
57 option_list = LabelCommand.option_list + ( | |
58 optparse.make_option("-s", "--super-user", | |
59 help="Make the user with this name a superuser"), | |
60 optparse.make_option("-a", "--anon-user", | |
61 help="Make the user with this name the anonymous user " | |
62 "[default: Anonymous]"), | |
63 optparse.make_option("-p", "--progress", action="store_true", | |
64 help="Output a . after every 20 users to show progress"), | |
65 ) | |
66 bb_parser = postmarkup.create(use_pygments=False, annotate_links=False) | |
67 md_writer = MarkdownWriter() | |
68 | |
69 def handle_label(self, filename, **options): | |
70 """ | |
71 Process each line in the CSV file given by filename by | |
72 creating a new user and profile. | |
73 | |
74 """ | |
75 self.superuser = options.get('super_user') | |
76 self.anonymous = options.get('anon_user') | |
77 if self.anonymous is None: | |
78 self.anonymous = 'Anonymous' | |
79 self.show_progress = options.get('progress') | |
80 | |
81 if self.superuser == self.anonymous: | |
82 raise CommandError("super-user name should not match anon-user") | |
83 | |
84 try: | |
85 with open(filename, "rb") as f: | |
86 self.reader = csv.DictReader(f) | |
87 num_rows = 0 | |
88 try: | |
89 for row in self.reader: | |
90 self.process_row(row) | |
91 num_rows += 1 | |
92 if num_rows % 20 == 0: | |
93 sys.stdout.write('.') | |
94 sys.stdout.flush() | |
95 except csv.Error, e: | |
96 raise CommandError("CSV error: %s %s %s" % ( | |
97 filename, self.reader.line_num, e)) | |
98 | |
99 print | |
100 | |
101 except IOError: | |
102 raise CommandError("Could not open file: %s" % filename) | |
103 | |
104 def process_row(self, row): | |
105 """ | |
106 Process one row from the CSV file: create a user and user profile for | |
107 the row and save it in the database. | |
108 | |
109 """ | |
110 row = dict((k, v if v != 'NULL' else '') for k, v in row.iteritems()) | |
111 | |
112 if not _valid_username(row['username']): | |
113 print "Skipping import of %s; invalid username" % row['username'] | |
114 return | |
115 | |
116 n = User.objects.filter(username=row['username']).count() | |
117 if n > 0: | |
118 print "Skipping import of %s; user already exists" % row['username'] | |
119 return | |
120 | |
121 first_name, last_name = _break_name(row['name']) | |
122 is_superuser = self.superuser == row['username'] | |
123 is_anonymous = self.anonymous == row['username'] | |
124 | |
125 u = User(id=int(row['user_id']), | |
126 username=row['username'], | |
127 first_name=first_name, | |
128 last_name=last_name, | |
129 email=row['user_email'], | |
130 password=row['user_password'] if row['user_password'] else None, | |
131 is_staff=is_superuser, | |
132 is_active=True if not is_anonymous else False, | |
133 is_superuser=is_superuser, | |
134 last_login=datetime.fromtimestamp(int(row['user_lastvisit'])), | |
135 date_joined=datetime.strptime(row['user_regdate'], "%b %d, %Y")) | |
136 | |
137 if is_anonymous: | |
138 u.set_unusable_password() | |
139 | |
140 u.save() | |
141 | |
142 p = u.get_profile() | |
143 p.location = row['user_from'] | |
144 p.occupation = row['user_occ'] | |
145 p.interests = row['user_interests'] | |
146 p.profile_text = u'' | |
147 p.hide_email = True if row['user_viewemail'] != '1' else False | |
148 p.signature = self.to_markdown(row['user_sig']) if row['user_sig'] else u'' | |
149 p.time_zone = TIME_ZONES.get(row['user_timezone'], 'US/Pacific') | |
150 p.use_24_time = False | |
151 p.forum_post_count = int(row['user_posts']) | |
152 p.status = bio.models.STA_ACTIVE if p.forum_post_count > 10 else bio.models.STA_STRANGER | |
153 p.status_date = datetime.now() | |
154 p.update_date = p.status_date | |
155 p.save() | |
156 | |
157 def to_html(self, s): | |
158 return self.bb_parser.render_to_html(unphpbb(s), cosmetic_replace=False) | |
159 | |
160 def to_markdown(self, s): | |
161 self.md_writer.reset() | |
162 self.md_writer.feed(self.to_html(s)) | |
163 return self.md_writer.markdown() |