Commit 156aa73a85a79c34c6e013862bbce59a49d0d15b
Committed by
Marcio Mazza
1 parent
556e3b9c
Exists in
master
and in
39 other branches
Moving stuff around
Showing
74 changed files
with
2958 additions
and
2958 deletions
Show diff stats
colab/api/__init__.py
colab/api/handlers.py
@@ -1,103 +0,0 @@ | @@ -1,103 +0,0 @@ | ||
1 | - | ||
2 | -from django.core.cache import cache | ||
3 | -from django.db import IntegrityError | ||
4 | -from django.core.exceptions import ObjectDoesNotExist | ||
5 | -from django.contrib.auth.decorators import login_required | ||
6 | - | ||
7 | -from piston.utils import rc | ||
8 | -from piston.handler import BaseHandler | ||
9 | - | ||
10 | -from colab import solrutils | ||
11 | -from colab.super_archives.models import Message, PageHit | ||
12 | - | ||
13 | - | ||
14 | -class VoteHandler(BaseHandler): | ||
15 | - allowed_methods = ('GET', 'POST', 'DELETE') | ||
16 | - | ||
17 | - def create(self, request, message_id): | ||
18 | - if not request.user.is_authenticated(): | ||
19 | - return rc.FORBIDDEN | ||
20 | - | ||
21 | - try: | ||
22 | - Message.objects.get(id=message_id).vote(request.user) | ||
23 | - except IntegrityError: | ||
24 | - return rc.DUPLICATE_ENTRY | ||
25 | - | ||
26 | - return rc.CREATED | ||
27 | - | ||
28 | - def read(self, request, message_id): | ||
29 | - return Message.objects.get(id=message_id).votes_count() | ||
30 | - | ||
31 | - def delete(self, request, message_id): | ||
32 | - if not request.user.is_authenticated(): | ||
33 | - return rc.FORBIDDEN | ||
34 | - | ||
35 | - try: | ||
36 | - Message.objects.get(id=message_id).unvote(request.user) | ||
37 | - except ObjectDoesNotExist: | ||
38 | - return rc.NOT_HERE | ||
39 | - | ||
40 | - return rc.DELETED | ||
41 | - | ||
42 | - | ||
43 | -class CountHandler(BaseHandler): | ||
44 | - allowed_methods = ('POST') | ||
45 | - | ||
46 | - def create(self, request): | ||
47 | - """Add one page view for the given url""" | ||
48 | - | ||
49 | - # If missing the path_info argument we can't do anything | ||
50 | - path_info = request.POST.get('path_info') | ||
51 | - if not path_info: | ||
52 | - return rc.BAD_REQUEST | ||
53 | - | ||
54 | - # Here we cache the user's IP to ensure that the same | ||
55 | - # IP won't hit the same page again for while | ||
56 | - ip_addr = request.META.get('REMOTE_ADDR') | ||
57 | - page_hits_cache = cache.get('page_hits', {}) | ||
58 | - duplicate = page_hits_cache.get(path_info, {}).get(ip_addr) | ||
59 | - | ||
60 | - if duplicate: | ||
61 | - return rc.DUPLICATE_ENTRY | ||
62 | - else: | ||
63 | - page_hits_cache.update({path_info: {ip_addr: True }}) | ||
64 | - cache.set('page_hits', page_hits_cache) | ||
65 | - | ||
66 | - # Everything ok, so just increment the page count | ||
67 | - page_hit = PageHit.objects.get_or_create(url_path=path_info)[0] | ||
68 | - page_hit.hit_count += 1 | ||
69 | - page_hit.save() | ||
70 | - | ||
71 | - return rc.CREATED | ||
72 | - | ||
73 | -class SearchHandler(BaseHandler): | ||
74 | - allowed_methods = ('GET', ) | ||
75 | - | ||
76 | - def read(self, request): | ||
77 | - query = request.GET.get('q') | ||
78 | - page = request.GET.get('p', 1) | ||
79 | - results_per_page = request.GET.get('n', 50) | ||
80 | - order = request.GET.get('o') | ||
81 | - | ||
82 | - if not query: | ||
83 | - return 'Query cannot be empty.' | ||
84 | - else: | ||
85 | - query = query.encode('utf-8') | ||
86 | - | ||
87 | - try: | ||
88 | - n = int(results_per_page) | ||
89 | - except ValueError: | ||
90 | - n = 10 | ||
91 | - | ||
92 | - if 1 > n > 500: | ||
93 | - n = 1 | ||
94 | - | ||
95 | - try: | ||
96 | - page = int(page) | ||
97 | - except ValueError: | ||
98 | - page = 1 | ||
99 | - | ||
100 | - if page < 1: | ||
101 | - page = 1 | ||
102 | - | ||
103 | - return solrutils.select(query, results_per_page, page, order) |
colab/api/urls.py
@@ -1,16 +0,0 @@ | @@ -1,16 +0,0 @@ | ||
1 | -from django.conf.urls.defaults import patterns, include, url | ||
2 | - | ||
3 | -from piston.resource import Resource | ||
4 | - | ||
5 | -from colab.api.handlers import VoteHandler, CountHandler, SearchHandler | ||
6 | - | ||
7 | - | ||
8 | -vote_handler = Resource(VoteHandler) | ||
9 | -count_handler = Resource(CountHandler) | ||
10 | -search_handler = Resource(SearchHandler) | ||
11 | - | ||
12 | -urlpatterns = patterns('', | ||
13 | - url(r'message/(?P<message_id>\d+)/vote$', vote_handler), | ||
14 | - url(r'hit/$', count_handler), | ||
15 | - url(r'search/$', search_handler), | ||
16 | -) |
colab/rss/__init__.py
colab/rss/feeds.py
@@ -1,78 +0,0 @@ | @@ -1,78 +0,0 @@ | ||
1 | -#!/usr/bin/env python | ||
2 | -# encoding: utf-8 | ||
3 | - | ||
4 | -from django.contrib.syndication.views import Feed | ||
5 | -from django.utils.translation import ugettext as _ | ||
6 | - | ||
7 | -from colab.super_archives.models import Thread | ||
8 | -from colab.super_archives import queries | ||
9 | -from colab import solrutils | ||
10 | - | ||
11 | -class LatestThreadsFeeds(Feed): | ||
12 | - title = _(u'Latest Discussions') | ||
13 | - link = '/rss/threads/latest/' | ||
14 | - | ||
15 | - def items(self): | ||
16 | - return queries.get_latest_threads()[:20] | ||
17 | - | ||
18 | - def item_link(self, item): | ||
19 | - return item.latest_message.url | ||
20 | - | ||
21 | - def item_title(self, item): | ||
22 | - title = '[' + item.mailinglist.name + '] ' | ||
23 | - title += item.latest_message.subject_clean | ||
24 | - return title | ||
25 | - | ||
26 | - def item_description(self, item): | ||
27 | - return item.latest_message.body | ||
28 | - | ||
29 | - | ||
30 | -class HottestThreadsFeeds(Feed): | ||
31 | - title = _(u'Discussions Most Relevance') | ||
32 | - link = '/rss/threads/hottest/' | ||
33 | - | ||
34 | - def items(self): | ||
35 | - return queries.get_hottest_threads()[:20] | ||
36 | - | ||
37 | - def item_link(self, item): | ||
38 | - return item.latest_message.url | ||
39 | - | ||
40 | - def item_title(self, item): | ||
41 | - title = '[' + item.mailinglist.name + '] ' | ||
42 | - title += item.latest_message.subject_clean | ||
43 | - return title | ||
44 | - | ||
45 | - def item_description(self, item): | ||
46 | - return item.latest_message.body | ||
47 | - | ||
48 | - | ||
49 | -class LatestColabFeeds(Feed): | ||
50 | - title = _(u'Latest collaborations') | ||
51 | - link = '/rss/colab/latest/' | ||
52 | - | ||
53 | - def items(self): | ||
54 | - items = solrutils.get_latest_collaborations(20) | ||
55 | - return items | ||
56 | - | ||
57 | - def item_title(self, item): | ||
58 | - type_ = item.get('Type') + ': ' | ||
59 | - mailinglist = item.get('mailinglist') | ||
60 | - | ||
61 | - if mailinglist: | ||
62 | - prefix = type_ + mailinglist + ' - ' | ||
63 | - else: | ||
64 | - prefix = type_ | ||
65 | - | ||
66 | - return prefix + item.get('Title') | ||
67 | - | ||
68 | - def item_description(self, item): | ||
69 | - return item.get('Description') | ||
70 | - | ||
71 | - def item_link(self, item): | ||
72 | - if item.get('Type') != 'thread': | ||
73 | - url = item.get('url') | ||
74 | - else: | ||
75 | - url = 'http://colab.interlegis.leg.br' | ||
76 | - url += item.get('url') | ||
77 | - return url | ||
78 | - |
colab/rss/urls.py
@@ -1,9 +0,0 @@ | @@ -1,9 +0,0 @@ | ||
1 | -from django.conf.urls.defaults import patterns, url | ||
2 | -import feeds | ||
3 | - | ||
4 | -urlpatterns = patterns('', | ||
5 | - url(r'threads/latest/$', feeds.LatestThreadsFeeds(), name='rss_latest_threads'), | ||
6 | - url(r'colab/latest/$', feeds.LatestColabFeeds(), name='rss_latest_colab'), | ||
7 | - url(r'threads/hottest/$', feeds.HottestThreadsFeeds(), name='rss_hottest_threads'), | ||
8 | -) | ||
9 | - |
colab/super_archives/__init__.py
colab/super_archives/admin.py
@@ -1,54 +0,0 @@ | @@ -1,54 +0,0 @@ | ||
1 | - | ||
2 | -from django.contrib import admin | ||
3 | -from colab.super_archives.models import Message, Thread, UserProfile | ||
4 | - | ||
5 | -class MessageAdmin(admin.ModelAdmin): | ||
6 | - list_filter = ('spam', 'thread__mailinglist', 'received_time', ) | ||
7 | - search_fields = ( | ||
8 | - 'id', | ||
9 | - 'subject', | ||
10 | - 'subject_clean', | ||
11 | - 'body', | ||
12 | - 'from_address__real_name', | ||
13 | - 'from_address__address', | ||
14 | - 'from_address__user__first_name', | ||
15 | - 'from_address__user__last_name', | ||
16 | - 'from_address__user__username', | ||
17 | - ) | ||
18 | - readonly_fields = ('thread', 'from_address', 'mailinglist') | ||
19 | - | ||
20 | - | ||
21 | -class ThreadAdmin(admin.ModelAdmin): | ||
22 | - list_filter = ('spam', 'mailinglist', 'message__received_time',) | ||
23 | - search_fields = ( | ||
24 | - 'id', | ||
25 | - 'subject_token', | ||
26 | - 'message__subject', | ||
27 | - 'message__subject_clean', | ||
28 | - 'message__from_address__real_name', | ||
29 | - 'message__from_address__address', | ||
30 | - 'message__from_address__user__first_name', | ||
31 | - 'message__from_address__user__last_name', | ||
32 | - 'message__from_address__user__username', | ||
33 | - ) | ||
34 | - | ||
35 | - readonly_fields = ( | ||
36 | - 'mailinglist', | ||
37 | - 'subject_token', | ||
38 | - 'latest_message', | ||
39 | - 'score', | ||
40 | - ) | ||
41 | - | ||
42 | - fields = ( | ||
43 | - 'mailinglist', | ||
44 | - 'subject_token', | ||
45 | - 'latest_message', | ||
46 | - 'score', | ||
47 | - 'spam', | ||
48 | - ) | ||
49 | - | ||
50 | - | ||
51 | -admin.site.register(UserProfile) | ||
52 | -admin.site.register(Thread, ThreadAdmin) | ||
53 | -admin.site.register(Message, MessageAdmin) | ||
54 | - |
colab/super_archives/fixtures/initial_data.json
colab/super_archives/forms.py
@@ -1,66 +0,0 @@ | @@ -1,66 +0,0 @@ | ||
1 | -# -*- coding: utf-8 -*- | ||
2 | - | ||
3 | -from django import forms | ||
4 | -from django.core.exceptions import ValidationError | ||
5 | -from django.contrib.auth.models import User | ||
6 | -from django.contrib.auth.forms import UserCreationForm as UserCreationForm_ | ||
7 | -from django.utils.translation import ugettext_lazy as _ | ||
8 | - | ||
9 | -from colab.super_archives.models import MailingList | ||
10 | -from colab.super_archives.validators import UniqueValidator | ||
11 | - | ||
12 | -# XXX: I know that this code does not look nice AT ALL. | ||
13 | -# probably it should be implemented using formsets instead of | ||
14 | -# the hack below. Feel free to improve it! :) | ||
15 | - | ||
16 | -# User fields | ||
17 | -username_field = UserCreationForm_().fields.get(u'username') | ||
18 | -first_name_field = forms.CharField(max_length=30, label=_(u'Name')) | ||
19 | -last_name_field = forms.CharField(max_length=30, label=_(u'Last name')) | ||
20 | -email_field = forms.EmailField(validators=[UniqueValidator(User, 'email')]) | ||
21 | - | ||
22 | -# UserProfile fields | ||
23 | -institution_field = forms.CharField(max_length=120, label=_(u'Institution'), | ||
24 | - required=False) | ||
25 | -role_field = forms.CharField(max_length=60, label=_(u'Function'), required=False) | ||
26 | -twitter_field = forms.URLField(label=_(u'Twitter'), required=False) | ||
27 | -facebook_field = forms.URLField(label=_(u'Facebook'), required=False) | ||
28 | -google_talk_field = forms.EmailField(label=_(u'Google Talk'), required=False) | ||
29 | -webpage_field = forms.URLField(label=_(u'Personal Website/Blog'), required=False) | ||
30 | - | ||
31 | -all_lists = MailingList.objects.all() | ||
32 | -lists_names = [] | ||
33 | -for list_ in all_lists: | ||
34 | - choice = (list_.name, list_.name) | ||
35 | - lists_names.append(choice) | ||
36 | - | ||
37 | -lists_field = forms.MultipleChoiceField( | ||
38 | - label=u'Listas', | ||
39 | - required=False, | ||
40 | - widget=forms.CheckboxSelectMultiple, | ||
41 | - choices=lists_names | ||
42 | -) | ||
43 | - | ||
44 | - | ||
45 | -class UserCreationForm(UserCreationForm_): | ||
46 | - first_name = first_name_field | ||
47 | - last_name = last_name_field | ||
48 | - email = email_field | ||
49 | - institution = institution_field | ||
50 | - role = role_field | ||
51 | - twitter = twitter_field | ||
52 | - facebook = facebook_field | ||
53 | - google_talk = google_talk_field | ||
54 | - webpage = webpage_field | ||
55 | - lists = lists_field | ||
56 | - | ||
57 | - | ||
58 | -class UserUpdateForm(forms.Form): | ||
59 | - username = username_field | ||
60 | - username.required = False | ||
61 | - institution = institution_field | ||
62 | - role = role_field | ||
63 | - twitter = twitter_field | ||
64 | - facebook = facebook_field | ||
65 | - google_talk = google_talk_field | ||
66 | - webpage = webpage_field |
colab/super_archives/management/__init__.py
colab/super_archives/management/commands/__init__.py
colab/super_archives/management/commands/import_emails.py
@@ -1,258 +0,0 @@ | @@ -1,258 +0,0 @@ | ||
1 | -#!/usr/bin/env python | ||
2 | -# -*- encoding: utf-8 -*- | ||
3 | - | ||
4 | -"""Import emails from a mailman storage to the django database.""" | ||
5 | - | ||
6 | -import os | ||
7 | -import re | ||
8 | -import sys | ||
9 | -import mailbox | ||
10 | -from optparse import make_option | ||
11 | - | ||
12 | -from django.db import transaction | ||
13 | -from django.template.defaultfilters import slugify | ||
14 | -from django.core.management.base import BaseCommand, CommandError | ||
15 | - | ||
16 | -from colab.super_archives.models import MailingList, Message, \ | ||
17 | - Thread, EmailAddress | ||
18 | -from colab.super_archives.management.commands.message import Message as \ | ||
19 | - CustomMessage | ||
20 | - | ||
21 | - | ||
22 | -class Command(BaseCommand, object): | ||
23 | - """Get emails from mailman archives and import them in the django db. """ | ||
24 | - | ||
25 | - help = __doc__ | ||
26 | - | ||
27 | - default_archives_path = '/var/lib/mailman/archives/private' | ||
28 | - RE_SUBJECT_CLEAN = re.compile('((re|res|fw|fwd|en|enc):)|\[.*?\]', | ||
29 | - re.IGNORECASE) | ||
30 | - THREAD_CACHE = {} | ||
31 | - EMAIL_ADDR_CACHE = {} | ||
32 | - | ||
33 | - # A new command line option to get the dump file to parse. | ||
34 | - option_list = BaseCommand.option_list + ( | ||
35 | - make_option('--archives_path', | ||
36 | - dest='archives_path', | ||
37 | - help='Path of email archives to be imported. (default: %s)' % | ||
38 | - default_archives_path, | ||
39 | - default=default_archives_path), | ||
40 | - | ||
41 | - make_option('--exclude-list', | ||
42 | - dest='exclude_lists', | ||
43 | - help=("Mailing list that won't be imported. It can be used many" | ||
44 | - "times for more than one list."), | ||
45 | - action='append', | ||
46 | - default=None), | ||
47 | - | ||
48 | - make_option('--all', | ||
49 | - dest='all', | ||
50 | - help='Import all messages (default: False)', | ||
51 | - action="store_true", | ||
52 | - default=False), | ||
53 | - ) | ||
54 | - | ||
55 | - def __init__(self, *args, **kwargs): | ||
56 | - super(Command, self).__init__(*args, **kwargs) | ||
57 | - | ||
58 | - def log(self, msg, error=False): | ||
59 | - """Log message helper.""" | ||
60 | - output = self.stdout | ||
61 | - if error: | ||
62 | - output = self.stderr | ||
63 | - | ||
64 | - output.write(msg) | ||
65 | - output.write('\n') | ||
66 | - | ||
67 | - def parse_emails(self, email_filename, index=0): | ||
68 | - """Generator function that parse and extract emails from the file | ||
69 | - `email_filename` starting from the position `index`. | ||
70 | - | ||
71 | - Yield: An instance of `mailbox.mboxMessage` for each email in the | ||
72 | - file. | ||
73 | - | ||
74 | - """ | ||
75 | - self.log("Parsing email dump: %s." % email_filename) | ||
76 | - mbox = mailbox.mbox(email_filename, factory=CustomMessage) | ||
77 | - | ||
78 | - # Get each email from mbox file | ||
79 | - # | ||
80 | - # The following implementation was used because the object | ||
81 | - # mbox does not support slicing. Converting the object to a | ||
82 | - # tuple (as represented in the code down here) was a valid | ||
83 | - # option but its performance was too poor. | ||
84 | - # | ||
85 | - #for message in tuple(mbox)[index:]: | ||
86 | - # yield message | ||
87 | - # | ||
88 | - key = index | ||
89 | - while mbox.has_key(key): | ||
90 | - key += 1 | ||
91 | - yield key-1, mbox[key-1] | ||
92 | - | ||
93 | - def get_emails(self, mailinglist_dir, all, exclude_lists): | ||
94 | - """Generator function that get the emails from each mailing | ||
95 | - list dump dirctory. If `all` is set to True all the emails in the | ||
96 | - mbox will be imported if not it will just resume from the last | ||
97 | - message previously imported. The lists set in `exclude_lists` | ||
98 | - won't be imported. | ||
99 | - | ||
100 | - Yield: A tuple in the form: (mailing list name, email message). | ||
101 | - | ||
102 | - """ | ||
103 | - self.log("Getting emails dumps from: %s" % mailinglist_dir) | ||
104 | - | ||
105 | - # Get the list of directories ending with .mbox | ||
106 | - mailing_lists_mboxes = (mbox for mbox in os.listdir(mailinglist_dir) | ||
107 | - if mbox.endswith('.mbox')) | ||
108 | - | ||
109 | - # Get messages from each mbox | ||
110 | - for mbox in mailing_lists_mboxes: | ||
111 | - mbox_path = os.path.join(mailinglist_dir, mbox, mbox) | ||
112 | - mailinglist_name = mbox.split('.')[0] | ||
113 | - | ||
114 | - # Check if the mailinglist is set not to be imported | ||
115 | - if exclude_lists and mailinglist_name in exclude_lists: | ||
116 | - continue | ||
117 | - | ||
118 | - # Find the index of the last imported message | ||
119 | - if all: | ||
120 | - n_msgs = 0 | ||
121 | - else: | ||
122 | - try: | ||
123 | - mailinglist = MailingList.objects.get( | ||
124 | - name=mailinglist_name) | ||
125 | - n_msgs = mailinglist.last_imported_index | ||
126 | - except MailingList.DoesNotExist: | ||
127 | - n_msgs = 0 | ||
128 | - | ||
129 | - for index, msg in self.parse_emails(mbox_path, n_msgs): | ||
130 | - yield mailinglist_name, msg, index | ||
131 | - | ||
132 | - def get_thread(self, email, mailinglist): | ||
133 | - """Group messages by thread looking for similar subjects""" | ||
134 | - | ||
135 | - subject_slug = slugify(email.subject_clean) | ||
136 | - thread = self.THREAD_CACHE.get(subject_slug, {}).get(mailinglist.id) | ||
137 | - if thread is None: | ||
138 | - thread = Thread.objects.get_or_create( | ||
139 | - mailinglist=mailinglist, | ||
140 | - subject_token=subject_slug | ||
141 | - )[0] | ||
142 | - | ||
143 | - if self.THREAD_CACHE.get(subject_slug) is None: | ||
144 | - self.THREAD_CACHE[subject_slug] = dict() | ||
145 | - self.THREAD_CACHE[subject_slug][mailinglist.id] = thread | ||
146 | - | ||
147 | - thread.latest_message = email | ||
148 | - thread.save() | ||
149 | - return thread | ||
150 | - | ||
151 | - def save_email(self, list_name, email_msg, index): | ||
152 | - """Save email message into the database.""" | ||
153 | - | ||
154 | - # Update last imported message into the DB | ||
155 | - mailinglist, created = MailingList.objects.get_or_create(name=list_name) | ||
156 | - mailinglist.last_imported_index = index | ||
157 | - | ||
158 | - if created: | ||
159 | - # if the mailinglist is newly created it's sure that the message | ||
160 | - # is not in the DB yet. | ||
161 | - self.create_email(mailinglist, email_msg) | ||
162 | - | ||
163 | - else: | ||
164 | - # If the message is already at the database don't do anything | ||
165 | - try: | ||
166 | - messages = Message.objects.get( | ||
167 | - message_id=email_msg.get('Message-ID'), | ||
168 | - thread__mailinglist=mailinglist | ||
169 | - ) | ||
170 | - | ||
171 | - except Message.DoesNotExist: | ||
172 | - self.create_email(mailinglist, email_msg) | ||
173 | - | ||
174 | - mailinglist.save() | ||
175 | - | ||
176 | - def create_email(self, mailinglist, email_msg): | ||
177 | - | ||
178 | - real_name, from_ = email_msg.get_from_addr() | ||
179 | - | ||
180 | - email_addr = self.EMAIL_ADDR_CACHE.get(from_) | ||
181 | - if email_addr is None: | ||
182 | - email_addr = EmailAddress.objects.get_or_create( | ||
183 | - address=from_)[0] | ||
184 | - self.EMAIL_ADDR_CACHE[from_] = email_addr | ||
185 | - | ||
186 | - if not email_addr.real_name and real_name: | ||
187 | - email_addr.real_name = real_name[:64] | ||
188 | - email_addr.save() | ||
189 | - | ||
190 | - subject = email_msg.get_subject() | ||
191 | - | ||
192 | - email = Message.objects.create( | ||
193 | - message_id=email_msg.get('Message-ID'), | ||
194 | - from_address=email_addr, | ||
195 | - subject=subject, | ||
196 | - subject_clean=self.RE_SUBJECT_CLEAN.sub('', subject).strip(), | ||
197 | - body=email_msg.get_body(), | ||
198 | - received_time=email_msg.get_received_datetime(), | ||
199 | - ) | ||
200 | - email.thread = self.get_thread(email, mailinglist) | ||
201 | - email.save() | ||
202 | - | ||
203 | - @transaction.commit_manually | ||
204 | - def import_emails(self, archives_path, all, exclude_lists=None): | ||
205 | - """Get emails from the filesystem from the `archives_path` | ||
206 | - and store them into the database. If `all` is set to True all | ||
207 | - the filesystem storage will be imported otherwise the | ||
208 | - importation will resume from the last message previously | ||
209 | - imported. The lists set in `exclude_lists` won't be imported. | ||
210 | - | ||
211 | - """ | ||
212 | - | ||
213 | - count = 0 | ||
214 | - email_generator = self.get_emails(archives_path, all, exclude_lists) | ||
215 | - for mailinglist_name, msg, index in email_generator: | ||
216 | - try: | ||
217 | - self.save_email(mailinglist_name, msg, index) | ||
218 | - except: | ||
219 | - # This anti-pattern is needed to avoid the transations to | ||
220 | - # get stuck in case of errors. | ||
221 | - transaction.rollback() | ||
222 | - raise | ||
223 | - | ||
224 | - count += 1 | ||
225 | - if count % 1000 == 0: | ||
226 | - transaction.commit() | ||
227 | - | ||
228 | - transaction.commit() | ||
229 | - | ||
230 | - def handle(self, *args, **options): | ||
231 | - """Main command method.""" | ||
232 | - | ||
233 | - lock_file = '/var/lock/colab/import_emails.lock' | ||
234 | - | ||
235 | - # Already running, so quit | ||
236 | - if os.path.exists(lock_file): | ||
237 | - self.log(("This script is already running. (If your are sure it's " | ||
238 | - "not please delete the lock file in %s')") % lock_file) | ||
239 | - sys.exit(0) | ||
240 | - | ||
241 | - if not os.path.exists(os.path.dirname(lock_file)): | ||
242 | - os.mkdir(os.path.dirname(lock_file), 0755) | ||
243 | - | ||
244 | - run_lock = file(lock_file, 'w') | ||
245 | - run_lock.close() | ||
246 | - | ||
247 | - archives_path = options.get('archives_path') | ||
248 | - self.log('Using archives_path `%s`' % self.default_archives_path) | ||
249 | - | ||
250 | - if not os.path.exists(archives_path): | ||
251 | - raise CommandError('archives_path (%s) does not exist' % | ||
252 | - archives_path) | ||
253 | - | ||
254 | - self.import_emails(archives_path, | ||
255 | - options.get('all'), options.get('exclude_lists')) | ||
256 | - | ||
257 | - os.remove(lock_file) | ||
258 | - |
colab/super_archives/management/commands/message.py
@@ -1,101 +0,0 @@ | @@ -1,101 +0,0 @@ | ||
1 | - | ||
2 | -import re | ||
3 | -import pytz | ||
4 | -import email | ||
5 | -import codecs | ||
6 | -import mailbox | ||
7 | -import datetime | ||
8 | -from email.iterators import typed_subpart_iterator | ||
9 | - | ||
10 | -import chardet | ||
11 | - | ||
12 | - | ||
13 | -def get_charset(message, default='ASCII'): | ||
14 | - """Get the message charset""" | ||
15 | - | ||
16 | - charset = message.get_content_charset() | ||
17 | - | ||
18 | - if not charset: | ||
19 | - charset = message.get_charset() | ||
20 | - | ||
21 | - if not charset: | ||
22 | - charset = default | ||
23 | - | ||
24 | - try: | ||
25 | - codecs.lookup(charset) | ||
26 | - except LookupError: | ||
27 | - charset = default | ||
28 | - | ||
29 | - return charset | ||
30 | - | ||
31 | - | ||
32 | -class Message(mailbox.mboxMessage): | ||
33 | - | ||
34 | - RECEIVED_DELIMITER = re.compile('\n|;') | ||
35 | - | ||
36 | - def get_subject(self): | ||
37 | - subject = email.header.decode_header(self['Subject']) | ||
38 | - | ||
39 | - if isinstance(subject, list): | ||
40 | - new_subject = u'' | ||
41 | - for text_part, encoding in subject: | ||
42 | - if not encoding: | ||
43 | - encoding = get_charset(self) | ||
44 | - | ||
45 | - try: | ||
46 | - new_subject += unicode(text_part, encoding) | ||
47 | - except (UnicodeDecodeError, LookupError): | ||
48 | - try: | ||
49 | - new_subject += unicode(text_part, get_charset(self)) | ||
50 | - except (UnicodeDecodeError, LookupError): | ||
51 | - encoding = chardet.detect(text_part)['encoding'] | ||
52 | - new_subject += unicode(text_part, encoding) | ||
53 | - | ||
54 | - return ''.join(new_subject) | ||
55 | - | ||
56 | - def get_body(self): | ||
57 | - """Get the body of the email message""" | ||
58 | - | ||
59 | - if self.is_multipart(): | ||
60 | - #get the plain text version only | ||
61 | - text_parts = [part | ||
62 | - for part in typed_subpart_iterator(self, | ||
63 | - 'text', | ||
64 | - 'plain')] | ||
65 | - body = [] | ||
66 | - for part in text_parts: | ||
67 | - charset = get_charset(part, get_charset(self)) | ||
68 | - body.append(unicode(part.get_payload(decode=True), | ||
69 | - charset, | ||
70 | - "replace")) | ||
71 | - | ||
72 | - return u"\n".join(body).strip() | ||
73 | - | ||
74 | - else: # if it is not multipart, the payload will be a string | ||
75 | - # representing the message body | ||
76 | - body = unicode(self.get_payload(decode=True), | ||
77 | - get_charset(self), | ||
78 | - "replace") | ||
79 | - return body.strip() | ||
80 | - | ||
81 | - def get_received_datetime(self): | ||
82 | - # The time received should always be the last element | ||
83 | - # in the `Received` attribute from the message headers | ||
84 | - received_header = self.RECEIVED_DELIMITER.split(self['Received']) | ||
85 | - received_time_header = received_header[-1].strip() | ||
86 | - | ||
87 | - date_tuple = email.utils.parsedate_tz(received_time_header) | ||
88 | - utc_timestamp = email.utils.mktime_tz(date_tuple) | ||
89 | - utc_datetime = datetime.datetime.fromtimestamp(utc_timestamp, | ||
90 | - pytz.utc) | ||
91 | - | ||
92 | - return utc_datetime | ||
93 | - | ||
94 | - def get_from_addr(self): | ||
95 | - real_name_raw, from_ = email.utils.parseaddr(self['From']) | ||
96 | - real_name_str, encoding = email.header.decode_header(real_name_raw)[0] | ||
97 | - if not encoding: | ||
98 | - encoding = 'ascii' | ||
99 | - | ||
100 | - real_name = unicode(real_name_str, encoding, errors='replace') | ||
101 | - return real_name, from_ |
colab/super_archives/migrations/0001_initial.py
@@ -1,255 +0,0 @@ | @@ -1,255 +0,0 @@ | ||
1 | -# encoding: utf-8 | ||
2 | -import datetime | ||
3 | -from south.db import db | ||
4 | -from south.v2 import SchemaMigration | ||
5 | -from django.db import models | ||
6 | - | ||
7 | -class Migration(SchemaMigration): | ||
8 | - | ||
9 | - def forwards(self, orm): | ||
10 | - | ||
11 | - # Adding model 'PageHit' | ||
12 | - db.create_table('super_archives_pagehit', ( | ||
13 | - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
14 | - ('url_path', self.gf('django.db.models.fields.CharField')(unique=True, max_length=2048, db_index=True)), | ||
15 | - ('hit_count', self.gf('django.db.models.fields.IntegerField')(default=0)), | ||
16 | - )) | ||
17 | - db.send_create_signal('super_archives', ['PageHit']) | ||
18 | - | ||
19 | - # Adding model 'EmailAddress' | ||
20 | - db.create_table('super_archives_emailaddress', ( | ||
21 | - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
22 | - ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='emails', null=True, to=orm['auth.User'])), | ||
23 | - ('address', self.gf('django.db.models.fields.EmailField')(unique=True, max_length=75)), | ||
24 | - ('real_name', self.gf('django.db.models.fields.CharField')(max_length=64, blank=True)), | ||
25 | - ('md5', self.gf('django.db.models.fields.CharField')(max_length=32, null=True)), | ||
26 | - )) | ||
27 | - db.send_create_signal('super_archives', ['EmailAddress']) | ||
28 | - | ||
29 | - # Adding model 'UserProfile' | ||
30 | - db.create_table('super_archives_userprofile', ( | ||
31 | - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
32 | - ('user', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True)), | ||
33 | - ('institution', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), | ||
34 | - ('role', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), | ||
35 | - ('twitter', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), | ||
36 | - ('facebook', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), | ||
37 | - ('google_talk', self.gf('django.db.models.fields.EmailField')(max_length=75, null=True)), | ||
38 | - ('webpage', self.gf('django.db.models.fields.CharField')(max_length=256)), | ||
39 | - )) | ||
40 | - db.send_create_signal('super_archives', ['UserProfile']) | ||
41 | - | ||
42 | - # Adding model 'MailingList' | ||
43 | - db.create_table('super_archives_mailinglist', ( | ||
44 | - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
45 | - ('name', self.gf('django.db.models.fields.CharField')(max_length=80)), | ||
46 | - ('email', self.gf('django.db.models.fields.EmailField')(max_length=75)), | ||
47 | - ('description', self.gf('django.db.models.fields.TextField')()), | ||
48 | - ('logo', self.gf('django.db.models.fields.files.FileField')(max_length=100)), | ||
49 | - ('last_imported_index', self.gf('django.db.models.fields.IntegerField')(default=0)), | ||
50 | - )) | ||
51 | - db.send_create_signal('super_archives', ['MailingList']) | ||
52 | - | ||
53 | - # Adding model 'MailingListMembership' | ||
54 | - db.create_table('super_archives_mailinglistmembership', ( | ||
55 | - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
56 | - ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), | ||
57 | - ('mailinglist', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.MailingList'])), | ||
58 | - )) | ||
59 | - db.send_create_signal('super_archives', ['MailingListMembership']) | ||
60 | - | ||
61 | - # Adding model 'Thread' | ||
62 | - db.create_table('super_archives_thread', ( | ||
63 | - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
64 | - ('subject_token', self.gf('django.db.models.fields.CharField')(max_length=512)), | ||
65 | - ('mailinglist', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.MailingList'])), | ||
66 | - ('latest_message', self.gf('django.db.models.fields.related.OneToOneField')(related_name='+', unique=True, null=True, to=orm['super_archives.Message'])), | ||
67 | - )) | ||
68 | - db.send_create_signal('super_archives', ['Thread']) | ||
69 | - | ||
70 | - # Adding unique constraint on 'Thread', fields ['subject_token', 'mailinglist'] | ||
71 | - db.create_unique('super_archives_thread', ['subject_token', 'mailinglist_id']) | ||
72 | - | ||
73 | - # Adding model 'Vote' | ||
74 | - db.create_table('super_archives_vote', ( | ||
75 | - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
76 | - ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), | ||
77 | - ('message', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.Message'])), | ||
78 | - )) | ||
79 | - db.send_create_signal('super_archives', ['Vote']) | ||
80 | - | ||
81 | - # Adding unique constraint on 'Vote', fields ['user', 'message'] | ||
82 | - db.create_unique('super_archives_vote', ['user_id', 'message_id']) | ||
83 | - | ||
84 | - # Adding model 'Message' | ||
85 | - db.create_table('super_archives_message', ( | ||
86 | - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
87 | - ('from_address', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.EmailAddress'])), | ||
88 | - ('mailinglist', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.MailingList'])), | ||
89 | - ('thread', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.Thread'], null=True)), | ||
90 | - ('subject', self.gf('django.db.models.fields.CharField')(max_length=512)), | ||
91 | - ('subject_clean', self.gf('django.db.models.fields.CharField')(max_length=512)), | ||
92 | - ('body', self.gf('django.db.models.fields.TextField')(default='')), | ||
93 | - ('received_time', self.gf('django.db.models.fields.DateTimeField')()), | ||
94 | - ('message_id', self.gf('django.db.models.fields.CharField')(max_length=512)), | ||
95 | - )) | ||
96 | - db.send_create_signal('super_archives', ['Message']) | ||
97 | - | ||
98 | - # Adding model 'MessageMetadata' | ||
99 | - db.create_table('super_archives_messagemetadata', ( | ||
100 | - ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
101 | - ('Message', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.Message'])), | ||
102 | - ('name', self.gf('django.db.models.fields.CharField')(max_length=512)), | ||
103 | - ('value', self.gf('django.db.models.fields.TextField')()), | ||
104 | - )) | ||
105 | - db.send_create_signal('super_archives', ['MessageMetadata']) | ||
106 | - | ||
107 | - | ||
108 | - def backwards(self, orm): | ||
109 | - | ||
110 | - # Removing unique constraint on 'Vote', fields ['user', 'message'] | ||
111 | - db.delete_unique('super_archives_vote', ['user_id', 'message_id']) | ||
112 | - | ||
113 | - # Removing unique constraint on 'Thread', fields ['subject_token', 'mailinglist'] | ||
114 | - db.delete_unique('super_archives_thread', ['subject_token', 'mailinglist_id']) | ||
115 | - | ||
116 | - # Deleting model 'PageHit' | ||
117 | - db.delete_table('super_archives_pagehit') | ||
118 | - | ||
119 | - # Deleting model 'EmailAddress' | ||
120 | - db.delete_table('super_archives_emailaddress') | ||
121 | - | ||
122 | - # Deleting model 'UserProfile' | ||
123 | - db.delete_table('super_archives_userprofile') | ||
124 | - | ||
125 | - # Deleting model 'MailingList' | ||
126 | - db.delete_table('super_archives_mailinglist') | ||
127 | - | ||
128 | - # Deleting model 'MailingListMembership' | ||
129 | - db.delete_table('super_archives_mailinglistmembership') | ||
130 | - | ||
131 | - # Deleting model 'Thread' | ||
132 | - db.delete_table('super_archives_thread') | ||
133 | - | ||
134 | - # Deleting model 'Vote' | ||
135 | - db.delete_table('super_archives_vote') | ||
136 | - | ||
137 | - # Deleting model 'Message' | ||
138 | - db.delete_table('super_archives_message') | ||
139 | - | ||
140 | - # Deleting model 'MessageMetadata' | ||
141 | - db.delete_table('super_archives_messagemetadata') | ||
142 | - | ||
143 | - | ||
144 | - models = { | ||
145 | - 'auth.group': { | ||
146 | - 'Meta': {'object_name': 'Group'}, | ||
147 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
148 | - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
149 | - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
150 | - }, | ||
151 | - 'auth.permission': { | ||
152 | - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
153 | - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
154 | - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
155 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
156 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
157 | - }, | ||
158 | - 'auth.user': { | ||
159 | - 'Meta': {'object_name': 'User'}, | ||
160 | - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
161 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
162 | - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
163 | - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
164 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
165 | - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
166 | - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
167 | - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
168 | - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
169 | - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
170 | - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
171 | - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
172 | - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
173 | - }, | ||
174 | - 'contenttypes.contenttype': { | ||
175 | - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
176 | - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
177 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
178 | - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
179 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
180 | - }, | ||
181 | - 'super_archives.emailaddress': { | ||
182 | - 'Meta': {'object_name': 'EmailAddress'}, | ||
183 | - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
184 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
185 | - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
186 | - 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
187 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
188 | - }, | ||
189 | - 'super_archives.mailinglist': { | ||
190 | - 'Meta': {'object_name': 'MailingList'}, | ||
191 | - 'description': ('django.db.models.fields.TextField', [], {}), | ||
192 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
193 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
194 | - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
195 | - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
196 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
197 | - }, | ||
198 | - 'super_archives.mailinglistmembership': { | ||
199 | - 'Meta': {'object_name': 'MailingListMembership'}, | ||
200 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
201 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
202 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
203 | - }, | ||
204 | - 'super_archives.message': { | ||
205 | - 'Meta': {'object_name': 'Message'}, | ||
206 | - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
207 | - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
208 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
209 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
210 | - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
211 | - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
212 | - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
213 | - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
214 | - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
215 | - }, | ||
216 | - 'super_archives.messagemetadata': { | ||
217 | - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
218 | - 'Meta': {'object_name': 'MessageMetadata'}, | ||
219 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
220 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
221 | - 'value': ('django.db.models.fields.TextField', [], {}) | ||
222 | - }, | ||
223 | - 'super_archives.pagehit': { | ||
224 | - 'Meta': {'object_name': 'PageHit'}, | ||
225 | - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
226 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
227 | - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
228 | - }, | ||
229 | - 'super_archives.thread': { | ||
230 | - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
231 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
232 | - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
233 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
234 | - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
235 | - }, | ||
236 | - 'super_archives.userprofile': { | ||
237 | - 'Meta': {'object_name': 'UserProfile'}, | ||
238 | - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
239 | - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
240 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
241 | - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
242 | - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
243 | - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
244 | - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
245 | - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
246 | - }, | ||
247 | - 'super_archives.vote': { | ||
248 | - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
249 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
250 | - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
251 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
252 | - } | ||
253 | - } | ||
254 | - | ||
255 | - complete_apps = ['super_archives'] |
colab/super_archives/migrations/0002_auto__add_field_userprofile_verification_hash.py
@@ -1,133 +0,0 @@ | @@ -1,133 +0,0 @@ | ||
1 | -# encoding: utf-8 | ||
2 | -import datetime | ||
3 | -from south.db import db | ||
4 | -from south.v2 import SchemaMigration | ||
5 | -from django.db import models | ||
6 | - | ||
7 | -class Migration(SchemaMigration): | ||
8 | - | ||
9 | - def forwards(self, orm): | ||
10 | - | ||
11 | - # Adding field 'UserProfile.verification_hash' | ||
12 | - db.add_column('super_archives_userprofile', 'verification_hash', self.gf('django.db.models.fields.CharField')(max_length=32, null=True), keep_default=False) | ||
13 | - | ||
14 | - | ||
15 | - def backwards(self, orm): | ||
16 | - | ||
17 | - # Deleting field 'UserProfile.verification_hash' | ||
18 | - db.delete_column('super_archives_userprofile', 'verification_hash') | ||
19 | - | ||
20 | - | ||
21 | - models = { | ||
22 | - 'auth.group': { | ||
23 | - 'Meta': {'object_name': 'Group'}, | ||
24 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | - }, | ||
28 | - 'auth.permission': { | ||
29 | - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | - }, | ||
35 | - 'auth.user': { | ||
36 | - 'Meta': {'object_name': 'User'}, | ||
37 | - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | - }, | ||
51 | - 'contenttypes.contenttype': { | ||
52 | - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | - }, | ||
58 | - 'super_archives.emailaddress': { | ||
59 | - 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | - 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
64 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | - }, | ||
66 | - 'super_archives.mailinglist': { | ||
67 | - 'Meta': {'object_name': 'MailingList'}, | ||
68 | - 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | - }, | ||
75 | - 'super_archives.mailinglistmembership': { | ||
76 | - 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | - }, | ||
81 | - 'super_archives.message': { | ||
82 | - 'Meta': {'object_name': 'Message'}, | ||
83 | - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
87 | - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
88 | - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
89 | - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
90 | - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
91 | - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
92 | - }, | ||
93 | - 'super_archives.messagemetadata': { | ||
94 | - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
95 | - 'Meta': {'object_name': 'MessageMetadata'}, | ||
96 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
97 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | - 'value': ('django.db.models.fields.TextField', [], {}) | ||
99 | - }, | ||
100 | - 'super_archives.pagehit': { | ||
101 | - 'Meta': {'object_name': 'PageHit'}, | ||
102 | - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
103 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
105 | - }, | ||
106 | - 'super_archives.thread': { | ||
107 | - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
108 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
109 | - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
110 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
111 | - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
112 | - }, | ||
113 | - 'super_archives.userprofile': { | ||
114 | - 'Meta': {'object_name': 'UserProfile'}, | ||
115 | - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
116 | - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
117 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
118 | - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
119 | - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
120 | - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
121 | - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
122 | - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
123 | - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
124 | - }, | ||
125 | - 'super_archives.vote': { | ||
126 | - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
127 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
128 | - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
129 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
130 | - } | ||
131 | - } | ||
132 | - | ||
133 | - complete_apps = ['super_archives'] |
colab/super_archives/migrations/0003_auto__add_field_thread_score.py
@@ -1,134 +0,0 @@ | @@ -1,134 +0,0 @@ | ||
1 | -# encoding: utf-8 | ||
2 | -import datetime | ||
3 | -from south.db import db | ||
4 | -from south.v2 import SchemaMigration | ||
5 | -from django.db import models | ||
6 | - | ||
7 | -class Migration(SchemaMigration): | ||
8 | - | ||
9 | - def forwards(self, orm): | ||
10 | - | ||
11 | - # Adding field 'Thread.score' | ||
12 | - db.add_column('super_archives_thread', 'score', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False) | ||
13 | - | ||
14 | - | ||
15 | - def backwards(self, orm): | ||
16 | - | ||
17 | - # Deleting field 'Thread.score' | ||
18 | - db.delete_column('super_archives_thread', 'score') | ||
19 | - | ||
20 | - | ||
21 | - models = { | ||
22 | - 'auth.group': { | ||
23 | - 'Meta': {'object_name': 'Group'}, | ||
24 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | - }, | ||
28 | - 'auth.permission': { | ||
29 | - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | - }, | ||
35 | - 'auth.user': { | ||
36 | - 'Meta': {'object_name': 'User'}, | ||
37 | - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | - }, | ||
51 | - 'contenttypes.contenttype': { | ||
52 | - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | - }, | ||
58 | - 'super_archives.emailaddress': { | ||
59 | - 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | - 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
64 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | - }, | ||
66 | - 'super_archives.mailinglist': { | ||
67 | - 'Meta': {'object_name': 'MailingList'}, | ||
68 | - 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | - }, | ||
75 | - 'super_archives.mailinglistmembership': { | ||
76 | - 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | - }, | ||
81 | - 'super_archives.message': { | ||
82 | - 'Meta': {'object_name': 'Message'}, | ||
83 | - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
87 | - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
88 | - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
89 | - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
90 | - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
91 | - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
92 | - }, | ||
93 | - 'super_archives.messagemetadata': { | ||
94 | - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
95 | - 'Meta': {'object_name': 'MessageMetadata'}, | ||
96 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
97 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | - 'value': ('django.db.models.fields.TextField', [], {}) | ||
99 | - }, | ||
100 | - 'super_archives.pagehit': { | ||
101 | - 'Meta': {'object_name': 'PageHit'}, | ||
102 | - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
103 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
105 | - }, | ||
106 | - 'super_archives.thread': { | ||
107 | - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
108 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
109 | - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
110 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
111 | - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
112 | - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
113 | - }, | ||
114 | - 'super_archives.userprofile': { | ||
115 | - 'Meta': {'object_name': 'UserProfile'}, | ||
116 | - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
117 | - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
118 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
119 | - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
120 | - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
121 | - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
122 | - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
123 | - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
124 | - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
125 | - }, | ||
126 | - 'super_archives.vote': { | ||
127 | - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
128 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
129 | - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
130 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
131 | - } | ||
132 | - } | ||
133 | - | ||
134 | - complete_apps = ['super_archives'] |
colab/super_archives/migrations/0004_auto__add_field_vote_created.py
@@ -1,135 +0,0 @@ | @@ -1,135 +0,0 @@ | ||
1 | -# encoding: utf-8 | ||
2 | -import datetime | ||
3 | -from south.db import db | ||
4 | -from south.v2 import SchemaMigration | ||
5 | -from django.db import models | ||
6 | - | ||
7 | -class Migration(SchemaMigration): | ||
8 | - | ||
9 | - def forwards(self, orm): | ||
10 | - | ||
11 | - # Adding field 'Vote.created' | ||
12 | - db.add_column('super_archives_vote', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2012, 1, 19, 18, 8, 46, 813949), blank=True), keep_default=False) | ||
13 | - | ||
14 | - | ||
15 | - def backwards(self, orm): | ||
16 | - | ||
17 | - # Deleting field 'Vote.created' | ||
18 | - db.delete_column('super_archives_vote', 'created') | ||
19 | - | ||
20 | - | ||
21 | - models = { | ||
22 | - 'auth.group': { | ||
23 | - 'Meta': {'object_name': 'Group'}, | ||
24 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | - }, | ||
28 | - 'auth.permission': { | ||
29 | - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | - }, | ||
35 | - 'auth.user': { | ||
36 | - 'Meta': {'object_name': 'User'}, | ||
37 | - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | - }, | ||
51 | - 'contenttypes.contenttype': { | ||
52 | - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | - }, | ||
58 | - 'super_archives.emailaddress': { | ||
59 | - 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | - 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
64 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | - }, | ||
66 | - 'super_archives.mailinglist': { | ||
67 | - 'Meta': {'object_name': 'MailingList'}, | ||
68 | - 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | - }, | ||
75 | - 'super_archives.mailinglistmembership': { | ||
76 | - 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | - }, | ||
81 | - 'super_archives.message': { | ||
82 | - 'Meta': {'object_name': 'Message'}, | ||
83 | - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
87 | - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
88 | - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
89 | - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
90 | - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
91 | - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
92 | - }, | ||
93 | - 'super_archives.messagemetadata': { | ||
94 | - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
95 | - 'Meta': {'object_name': 'MessageMetadata'}, | ||
96 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
97 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | - 'value': ('django.db.models.fields.TextField', [], {}) | ||
99 | - }, | ||
100 | - 'super_archives.pagehit': { | ||
101 | - 'Meta': {'object_name': 'PageHit'}, | ||
102 | - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
103 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
105 | - }, | ||
106 | - 'super_archives.thread': { | ||
107 | - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
108 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
109 | - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
110 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
111 | - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
112 | - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
113 | - }, | ||
114 | - 'super_archives.userprofile': { | ||
115 | - 'Meta': {'object_name': 'UserProfile'}, | ||
116 | - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
117 | - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
118 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
119 | - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
120 | - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
121 | - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
122 | - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
123 | - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
124 | - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
125 | - }, | ||
126 | - 'super_archives.vote': { | ||
127 | - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
128 | - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
129 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
130 | - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
131 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
132 | - } | ||
133 | - } | ||
134 | - | ||
135 | - complete_apps = ['super_archives'] |
colab/super_archives/migrations/0005_auto__add_field_message_spam__add_field_thread_spam.py
@@ -1,143 +0,0 @@ | @@ -1,143 +0,0 @@ | ||
1 | -# encoding: utf-8 | ||
2 | -import datetime | ||
3 | -from south.db import db | ||
4 | -from south.v2 import SchemaMigration | ||
5 | -from django.db import models | ||
6 | - | ||
7 | -class Migration(SchemaMigration): | ||
8 | - | ||
9 | - def forwards(self, orm): | ||
10 | - | ||
11 | - # Adding field 'Message.spam' | ||
12 | - db.add_column('super_archives_message', 'spam', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) | ||
13 | - | ||
14 | - # Adding field 'Thread.spam' | ||
15 | - db.add_column('super_archives_thread', 'spam', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) | ||
16 | - | ||
17 | - | ||
18 | - def backwards(self, orm): | ||
19 | - | ||
20 | - # Deleting field 'Message.spam' | ||
21 | - db.delete_column('super_archives_message', 'spam') | ||
22 | - | ||
23 | - # Deleting field 'Thread.spam' | ||
24 | - db.delete_column('super_archives_thread', 'spam') | ||
25 | - | ||
26 | - | ||
27 | - models = { | ||
28 | - 'auth.group': { | ||
29 | - 'Meta': {'object_name': 'Group'}, | ||
30 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
31 | - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
32 | - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
33 | - }, | ||
34 | - 'auth.permission': { | ||
35 | - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
36 | - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
37 | - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
38 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
39 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
40 | - }, | ||
41 | - 'auth.user': { | ||
42 | - 'Meta': {'object_name': 'User'}, | ||
43 | - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
44 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
45 | - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
46 | - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
47 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
48 | - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
49 | - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
50 | - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
51 | - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
52 | - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
53 | - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
54 | - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
55 | - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
56 | - }, | ||
57 | - 'contenttypes.contenttype': { | ||
58 | - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
59 | - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
60 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
61 | - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
62 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
63 | - }, | ||
64 | - 'super_archives.emailaddress': { | ||
65 | - 'Meta': {'object_name': 'EmailAddress'}, | ||
66 | - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
67 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
68 | - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
69 | - 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
70 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
71 | - }, | ||
72 | - 'super_archives.mailinglist': { | ||
73 | - 'Meta': {'object_name': 'MailingList'}, | ||
74 | - 'description': ('django.db.models.fields.TextField', [], {}), | ||
75 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
76 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
77 | - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
78 | - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
79 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
80 | - }, | ||
81 | - 'super_archives.mailinglistmembership': { | ||
82 | - 'Meta': {'object_name': 'MailingListMembership'}, | ||
83 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
84 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
85 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
86 | - }, | ||
87 | - 'super_archives.message': { | ||
88 | - 'Meta': {'object_name': 'Message'}, | ||
89 | - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
90 | - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
91 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
92 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
93 | - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
94 | - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
95 | - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
96 | - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
97 | - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
99 | - }, | ||
100 | - 'super_archives.messagemetadata': { | ||
101 | - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
102 | - 'Meta': {'object_name': 'MessageMetadata'}, | ||
103 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
105 | - 'value': ('django.db.models.fields.TextField', [], {}) | ||
106 | - }, | ||
107 | - 'super_archives.pagehit': { | ||
108 | - 'Meta': {'object_name': 'PageHit'}, | ||
109 | - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
110 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
111 | - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
112 | - }, | ||
113 | - 'super_archives.thread': { | ||
114 | - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
115 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
116 | - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
117 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
118 | - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
119 | - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
120 | - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
121 | - }, | ||
122 | - 'super_archives.userprofile': { | ||
123 | - 'Meta': {'object_name': 'UserProfile'}, | ||
124 | - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
125 | - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
126 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
127 | - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
128 | - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
129 | - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
130 | - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
131 | - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
132 | - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
133 | - }, | ||
134 | - 'super_archives.vote': { | ||
135 | - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
136 | - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
137 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
138 | - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
139 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
140 | - } | ||
141 | - } | ||
142 | - | ||
143 | - complete_apps = ['super_archives'] |
colab/super_archives/migrations/0006_auto.py
@@ -1,143 +0,0 @@ | @@ -1,143 +0,0 @@ | ||
1 | -# encoding: utf-8 | ||
2 | -import datetime | ||
3 | -from south.db import db | ||
4 | -from south.v2 import SchemaMigration | ||
5 | -from django.db import models | ||
6 | - | ||
7 | -class Migration(SchemaMigration): | ||
8 | - | ||
9 | - def forwards(self, orm): | ||
10 | - | ||
11 | - # Adding index on 'Message', fields ['subject_clean'] | ||
12 | - db.create_index('super_archives_message', ['subject_clean']) | ||
13 | - | ||
14 | - # Adding index on 'Message', fields ['subject'] | ||
15 | - db.create_index('super_archives_message', ['subject']) | ||
16 | - | ||
17 | - | ||
18 | - def backwards(self, orm): | ||
19 | - | ||
20 | - # Removing index on 'Message', fields ['subject'] | ||
21 | - db.delete_index('super_archives_message', ['subject']) | ||
22 | - | ||
23 | - # Removing index on 'Message', fields ['subject_clean'] | ||
24 | - db.delete_index('super_archives_message', ['subject_clean']) | ||
25 | - | ||
26 | - | ||
27 | - models = { | ||
28 | - 'auth.group': { | ||
29 | - 'Meta': {'object_name': 'Group'}, | ||
30 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
31 | - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
32 | - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
33 | - }, | ||
34 | - 'auth.permission': { | ||
35 | - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
36 | - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
37 | - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
38 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
39 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
40 | - }, | ||
41 | - 'auth.user': { | ||
42 | - 'Meta': {'object_name': 'User'}, | ||
43 | - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
44 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
45 | - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
46 | - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
47 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
48 | - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
49 | - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
50 | - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
51 | - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
52 | - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
53 | - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
54 | - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
55 | - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
56 | - }, | ||
57 | - 'contenttypes.contenttype': { | ||
58 | - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
59 | - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
60 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
61 | - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
62 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
63 | - }, | ||
64 | - 'super_archives.emailaddress': { | ||
65 | - 'Meta': {'object_name': 'EmailAddress'}, | ||
66 | - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
67 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
68 | - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
69 | - 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
70 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
71 | - }, | ||
72 | - 'super_archives.mailinglist': { | ||
73 | - 'Meta': {'object_name': 'MailingList'}, | ||
74 | - 'description': ('django.db.models.fields.TextField', [], {}), | ||
75 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
76 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
77 | - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
78 | - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
79 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
80 | - }, | ||
81 | - 'super_archives.mailinglistmembership': { | ||
82 | - 'Meta': {'object_name': 'MailingListMembership'}, | ||
83 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
84 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
85 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
86 | - }, | ||
87 | - 'super_archives.message': { | ||
88 | - 'Meta': {'object_name': 'Message'}, | ||
89 | - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
90 | - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
91 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
92 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
93 | - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
94 | - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
95 | - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
96 | - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
97 | - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
98 | - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
99 | - }, | ||
100 | - 'super_archives.messagemetadata': { | ||
101 | - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
102 | - 'Meta': {'object_name': 'MessageMetadata'}, | ||
103 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
105 | - 'value': ('django.db.models.fields.TextField', [], {}) | ||
106 | - }, | ||
107 | - 'super_archives.pagehit': { | ||
108 | - 'Meta': {'object_name': 'PageHit'}, | ||
109 | - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
110 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
111 | - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
112 | - }, | ||
113 | - 'super_archives.thread': { | ||
114 | - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
115 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
116 | - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
117 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
118 | - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
119 | - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
120 | - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
121 | - }, | ||
122 | - 'super_archives.userprofile': { | ||
123 | - 'Meta': {'object_name': 'UserProfile'}, | ||
124 | - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
125 | - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
126 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
127 | - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
128 | - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
129 | - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
130 | - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
131 | - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
132 | - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
133 | - }, | ||
134 | - 'super_archives.vote': { | ||
135 | - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
136 | - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
137 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
138 | - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
139 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
140 | - } | ||
141 | - } | ||
142 | - | ||
143 | - complete_apps = ['super_archives'] |
colab/super_archives/migrations/0007_auto.py
@@ -1,137 +0,0 @@ | @@ -1,137 +0,0 @@ | ||
1 | -# encoding: utf-8 | ||
2 | -import datetime | ||
3 | -from south.db import db | ||
4 | -from south.v2 import SchemaMigration | ||
5 | -from django.db import models | ||
6 | - | ||
7 | -class Migration(SchemaMigration): | ||
8 | - | ||
9 | - def forwards(self, orm): | ||
10 | - | ||
11 | - # Adding index on 'EmailAddress', fields ['real_name'] | ||
12 | - db.create_index('super_archives_emailaddress', ['real_name']) | ||
13 | - | ||
14 | - | ||
15 | - def backwards(self, orm): | ||
16 | - | ||
17 | - # Removing index on 'EmailAddress', fields ['real_name'] | ||
18 | - db.delete_index('super_archives_emailaddress', ['real_name']) | ||
19 | - | ||
20 | - | ||
21 | - models = { | ||
22 | - 'auth.group': { | ||
23 | - 'Meta': {'object_name': 'Group'}, | ||
24 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | - }, | ||
28 | - 'auth.permission': { | ||
29 | - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | - }, | ||
35 | - 'auth.user': { | ||
36 | - 'Meta': {'object_name': 'User'}, | ||
37 | - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | - }, | ||
51 | - 'contenttypes.contenttype': { | ||
52 | - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | - }, | ||
58 | - 'super_archives.emailaddress': { | ||
59 | - 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | - 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), | ||
64 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | - }, | ||
66 | - 'super_archives.mailinglist': { | ||
67 | - 'Meta': {'object_name': 'MailingList'}, | ||
68 | - 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | - }, | ||
75 | - 'super_archives.mailinglistmembership': { | ||
76 | - 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | - }, | ||
81 | - 'super_archives.message': { | ||
82 | - 'Meta': {'object_name': 'Message'}, | ||
83 | - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
87 | - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
88 | - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
89 | - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
90 | - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
91 | - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
92 | - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
93 | - }, | ||
94 | - 'super_archives.messagemetadata': { | ||
95 | - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
96 | - 'Meta': {'object_name': 'MessageMetadata'}, | ||
97 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
98 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
99 | - 'value': ('django.db.models.fields.TextField', [], {}) | ||
100 | - }, | ||
101 | - 'super_archives.pagehit': { | ||
102 | - 'Meta': {'object_name': 'PageHit'}, | ||
103 | - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
104 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
105 | - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
106 | - }, | ||
107 | - 'super_archives.thread': { | ||
108 | - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
109 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
110 | - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
111 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
112 | - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
113 | - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
114 | - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
115 | - }, | ||
116 | - 'super_archives.userprofile': { | ||
117 | - 'Meta': {'object_name': 'UserProfile'}, | ||
118 | - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
119 | - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
120 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
121 | - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
122 | - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
123 | - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
124 | - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
125 | - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
126 | - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
127 | - }, | ||
128 | - 'super_archives.vote': { | ||
129 | - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
130 | - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
131 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
132 | - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
133 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
134 | - } | ||
135 | - } | ||
136 | - | ||
137 | - complete_apps = ['super_archives'] |
colab/super_archives/migrations/0008_add_mailinglist_name_to_url.py
@@ -1,142 +0,0 @@ | @@ -1,142 +0,0 @@ | ||
1 | -# encoding: utf-8 | ||
2 | -import datetime | ||
3 | -from south.db import db | ||
4 | -from south.v2 import DataMigration | ||
5 | -from django.db import models | ||
6 | - | ||
7 | -class Migration(DataMigration): | ||
8 | - | ||
9 | - def forwards(self, orm): | ||
10 | - page_hits = orm.PageHit.objects.all() | ||
11 | - for page_hit in page_hits: | ||
12 | - if page_hit.url_path.startswith('/archives/thread/'): | ||
13 | - token = page_hit.url_path.split('/')[-1] | ||
14 | - threads = orm.Thread.objects.filter(subject_token=token) | ||
15 | - if not len(threads): continue | ||
16 | - thread = threads[0] | ||
17 | - new_url = '/archives/thread/%s/%s' % (thread.mailinglist.name, | ||
18 | - thread.subject_token) | ||
19 | - page_hit.url_path = new_url | ||
20 | - page_hit.save() | ||
21 | - | ||
22 | - | ||
23 | - def backwards(self, orm): | ||
24 | - raise RuntimeError("Cannot reverse this migration.") | ||
25 | - | ||
26 | - models = { | ||
27 | - 'auth.group': { | ||
28 | - 'Meta': {'object_name': 'Group'}, | ||
29 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
30 | - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
31 | - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
32 | - }, | ||
33 | - 'auth.permission': { | ||
34 | - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
35 | - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
36 | - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
37 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
38 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
39 | - }, | ||
40 | - 'auth.user': { | ||
41 | - 'Meta': {'object_name': 'User'}, | ||
42 | - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
43 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
44 | - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
45 | - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
46 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
47 | - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
48 | - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
49 | - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
50 | - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
51 | - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
52 | - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
53 | - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
54 | - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
55 | - }, | ||
56 | - 'contenttypes.contenttype': { | ||
57 | - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
58 | - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
59 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
60 | - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
61 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
62 | - }, | ||
63 | - 'super_archives.emailaddress': { | ||
64 | - 'Meta': {'object_name': 'EmailAddress'}, | ||
65 | - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
66 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
67 | - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
68 | - 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), | ||
69 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
70 | - }, | ||
71 | - 'super_archives.mailinglist': { | ||
72 | - 'Meta': {'object_name': 'MailingList'}, | ||
73 | - 'description': ('django.db.models.fields.TextField', [], {}), | ||
74 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
75 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
76 | - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
77 | - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
78 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
79 | - }, | ||
80 | - 'super_archives.mailinglistmembership': { | ||
81 | - 'Meta': {'object_name': 'MailingListMembership'}, | ||
82 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
83 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
84 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
85 | - }, | ||
86 | - 'super_archives.message': { | ||
87 | - 'Meta': {'object_name': 'Message'}, | ||
88 | - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
89 | - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
90 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
91 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
92 | - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
93 | - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
94 | - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
95 | - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
96 | - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
97 | - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
98 | - }, | ||
99 | - 'super_archives.messagemetadata': { | ||
100 | - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
101 | - 'Meta': {'object_name': 'MessageMetadata'}, | ||
102 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
103 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
104 | - 'value': ('django.db.models.fields.TextField', [], {}) | ||
105 | - }, | ||
106 | - 'super_archives.pagehit': { | ||
107 | - 'Meta': {'object_name': 'PageHit'}, | ||
108 | - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
109 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
110 | - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
111 | - }, | ||
112 | - 'super_archives.thread': { | ||
113 | - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
114 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
115 | - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
116 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
117 | - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
118 | - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
119 | - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
120 | - }, | ||
121 | - 'super_archives.userprofile': { | ||
122 | - 'Meta': {'object_name': 'UserProfile'}, | ||
123 | - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
124 | - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
125 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
126 | - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
127 | - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
128 | - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
129 | - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
130 | - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
131 | - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
132 | - }, | ||
133 | - 'super_archives.vote': { | ||
134 | - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
135 | - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
136 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
137 | - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
138 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
139 | - } | ||
140 | - } | ||
141 | - | ||
142 | - complete_apps = ['super_archives'] |
colab/super_archives/migrations/0009_auto__del_field_message_mailinglist.py
@@ -1,136 +0,0 @@ | @@ -1,136 +0,0 @@ | ||
1 | -# encoding: utf-8 | ||
2 | -import datetime | ||
3 | -from south.db import db | ||
4 | -from south.v2 import SchemaMigration | ||
5 | -from django.db import models | ||
6 | - | ||
7 | -class Migration(SchemaMigration): | ||
8 | - | ||
9 | - def forwards(self, orm): | ||
10 | - | ||
11 | - # Deleting field 'Message.mailinglist' | ||
12 | - db.delete_column('super_archives_message', 'mailinglist_id') | ||
13 | - | ||
14 | - | ||
15 | - def backwards(self, orm): | ||
16 | - | ||
17 | - # User chose to not deal with backwards NULL issues for 'Message.mailinglist' | ||
18 | - raise RuntimeError("Cannot reverse this migration. 'Message.mailinglist' and its values cannot be restored.") | ||
19 | - | ||
20 | - | ||
21 | - models = { | ||
22 | - 'auth.group': { | ||
23 | - 'Meta': {'object_name': 'Group'}, | ||
24 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | - }, | ||
28 | - 'auth.permission': { | ||
29 | - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | - }, | ||
35 | - 'auth.user': { | ||
36 | - 'Meta': {'object_name': 'User'}, | ||
37 | - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | - }, | ||
51 | - 'contenttypes.contenttype': { | ||
52 | - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | - }, | ||
58 | - 'super_archives.emailaddress': { | ||
59 | - 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | - 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), | ||
64 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | - }, | ||
66 | - 'super_archives.mailinglist': { | ||
67 | - 'Meta': {'object_name': 'MailingList'}, | ||
68 | - 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | - }, | ||
75 | - 'super_archives.mailinglistmembership': { | ||
76 | - 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | - }, | ||
81 | - 'super_archives.message': { | ||
82 | - 'Meta': {'object_name': 'Message'}, | ||
83 | - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
87 | - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
88 | - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
89 | - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
90 | - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
91 | - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
92 | - }, | ||
93 | - 'super_archives.messagemetadata': { | ||
94 | - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
95 | - 'Meta': {'object_name': 'MessageMetadata'}, | ||
96 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
97 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | - 'value': ('django.db.models.fields.TextField', [], {}) | ||
99 | - }, | ||
100 | - 'super_archives.pagehit': { | ||
101 | - 'Meta': {'object_name': 'PageHit'}, | ||
102 | - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
103 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
105 | - }, | ||
106 | - 'super_archives.thread': { | ||
107 | - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
108 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
109 | - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
110 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
111 | - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
112 | - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
113 | - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
114 | - }, | ||
115 | - 'super_archives.userprofile': { | ||
116 | - 'Meta': {'object_name': 'UserProfile'}, | ||
117 | - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
118 | - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
119 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
120 | - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
121 | - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
122 | - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
123 | - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
124 | - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
125 | - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
126 | - }, | ||
127 | - 'super_archives.vote': { | ||
128 | - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
129 | - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
130 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
131 | - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
132 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
133 | - } | ||
134 | - } | ||
135 | - | ||
136 | - complete_apps = ['super_archives'] |
colab/super_archives/migrations/0010_auto__add_unique_message_message_id_thread.py
@@ -1,136 +0,0 @@ | @@ -1,136 +0,0 @@ | ||
1 | -# encoding: utf-8 | ||
2 | -import datetime | ||
3 | -from south.db import db | ||
4 | -from south.v2 import SchemaMigration | ||
5 | -from django.db import models | ||
6 | - | ||
7 | -class Migration(SchemaMigration): | ||
8 | - | ||
9 | - def forwards(self, orm): | ||
10 | - | ||
11 | - # Adding unique constraint on 'Message', fields ['message_id', 'thread'] | ||
12 | - db.create_unique('super_archives_message', ['message_id', 'thread_id']) | ||
13 | - | ||
14 | - | ||
15 | - def backwards(self, orm): | ||
16 | - | ||
17 | - # Removing unique constraint on 'Message', fields ['message_id', 'thread'] | ||
18 | - db.delete_unique('super_archives_message', ['message_id', 'thread_id']) | ||
19 | - | ||
20 | - | ||
21 | - models = { | ||
22 | - 'auth.group': { | ||
23 | - 'Meta': {'object_name': 'Group'}, | ||
24 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | - }, | ||
28 | - 'auth.permission': { | ||
29 | - 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | - }, | ||
35 | - 'auth.user': { | ||
36 | - 'Meta': {'object_name': 'User'}, | ||
37 | - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | - }, | ||
51 | - 'contenttypes.contenttype': { | ||
52 | - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | - }, | ||
58 | - 'super_archives.emailaddress': { | ||
59 | - 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | - 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | - 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | - 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), | ||
64 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | - }, | ||
66 | - 'super_archives.mailinglist': { | ||
67 | - 'Meta': {'object_name': 'MailingList'}, | ||
68 | - 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | - 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | - 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | - }, | ||
75 | - 'super_archives.mailinglistmembership': { | ||
76 | - 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | - }, | ||
81 | - 'super_archives.message': { | ||
82 | - 'Meta': {'unique_together': "(('thread', 'message_id'),)", 'object_name': 'Message'}, | ||
83 | - 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | - 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | - 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
87 | - 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
88 | - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
89 | - 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
90 | - 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
91 | - 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
92 | - }, | ||
93 | - 'super_archives.messagemetadata': { | ||
94 | - 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
95 | - 'Meta': {'object_name': 'MessageMetadata'}, | ||
96 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
97 | - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | - 'value': ('django.db.models.fields.TextField', [], {}) | ||
99 | - }, | ||
100 | - 'super_archives.pagehit': { | ||
101 | - 'Meta': {'object_name': 'PageHit'}, | ||
102 | - 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
103 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | - 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
105 | - }, | ||
106 | - 'super_archives.thread': { | ||
107 | - 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
108 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
109 | - 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
110 | - 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
111 | - 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
112 | - 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
113 | - 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
114 | - }, | ||
115 | - 'super_archives.userprofile': { | ||
116 | - 'Meta': {'object_name': 'UserProfile'}, | ||
117 | - 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
118 | - 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
119 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
120 | - 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
121 | - 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
122 | - 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
123 | - 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
124 | - 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
125 | - 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
126 | - }, | ||
127 | - 'super_archives.vote': { | ||
128 | - 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
129 | - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
130 | - 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
131 | - 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
132 | - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
133 | - } | ||
134 | - } | ||
135 | - | ||
136 | - complete_apps = ['super_archives'] |
colab/super_archives/migrations/__init__.py
colab/super_archives/models.py
@@ -1,279 +0,0 @@ | @@ -1,279 +0,0 @@ | ||
1 | -# -*- coding: utf-8 -*- | ||
2 | - | ||
3 | -import datetime | ||
4 | -from hashlib import md5 | ||
5 | - | ||
6 | -from django.db import models | ||
7 | -from django.conf import settings | ||
8 | -from django.contrib.auth.models import User | ||
9 | -from django.core.urlresolvers import reverse, NoReverseMatch | ||
10 | -from django.utils.translation import ugettext_lazy as _ | ||
11 | - | ||
12 | - | ||
13 | -class NotSpamManager(models.Manager): | ||
14 | - """Only return objects which are not marked as spam.""" | ||
15 | - | ||
16 | - def get_query_set(self): | ||
17 | - return super(NotSpamManager, self).get_query_set().exclude(spam=True) | ||
18 | - | ||
19 | - | ||
20 | -class PageHit(models.Model): | ||
21 | - url_path = models.CharField(max_length=2048, unique=True, db_index=True) | ||
22 | - hit_count = models.IntegerField(default=0) | ||
23 | - | ||
24 | - | ||
25 | -class EmailAddress(models.Model): | ||
26 | - user = models.ForeignKey(User, null=True, related_name='emails') | ||
27 | - address = models.EmailField(unique=True) | ||
28 | - real_name = models.CharField(max_length=64, blank=True, db_index=True) | ||
29 | - md5 = models.CharField(max_length=32, null=True) | ||
30 | - | ||
31 | - def save(self, *args, **kwargs): | ||
32 | - self.md5 = md5(self.address).hexdigest() | ||
33 | - super(EmailAddress, self).save(*args, **kwargs) | ||
34 | - | ||
35 | - def get_full_name(self): | ||
36 | - if self.user and self.user.get_full_name(): | ||
37 | - return self.user.get_full_name() | ||
38 | - elif self.user and self.username: | ||
39 | - return self.username | ||
40 | - elif self.real_name: | ||
41 | - return self.real_name | ||
42 | - | ||
43 | - def get_profile_link(self): | ||
44 | - if self.user: | ||
45 | - return reverse('user_profile', args=[self.user.username]) | ||
46 | - else: | ||
47 | - return reverse('colab.views.userprofile.by_emailhash', | ||
48 | - args=[self.md5]) | ||
49 | - | ||
50 | - def __unicode__(self): | ||
51 | - return '"%s" <%s>' % (self.get_full_name(), self.address) | ||
52 | - | ||
53 | - | ||
54 | -class UserProfile(models.Model): | ||
55 | - | ||
56 | - user = models.OneToOneField(User, unique=True) | ||
57 | - institution = models.CharField(max_length=128, null=True) | ||
58 | - role = models.CharField(max_length=128, null=True) | ||
59 | - twitter = models.CharField(max_length=128, null=True) | ||
60 | - facebook = models.CharField(max_length=128, null=True) | ||
61 | - google_talk = models.EmailField(null=True) | ||
62 | - webpage = models.CharField(max_length=256) | ||
63 | - verification_hash = models.CharField(max_length=32, null=True) | ||
64 | - | ||
65 | - class Meta: | ||
66 | - verbose_name = _(u"User Profile") | ||
67 | - verbose_name_plural = _(u"Users Profiles") | ||
68 | - | ||
69 | - def __unicode__(self): | ||
70 | - return '%s (%s)' % (self.user.get_full_name(), self.user.username) | ||
71 | - | ||
72 | -# This does the same the same than related_name argument but it also creates | ||
73 | -# a profile in the case it doesn't exist yet. | ||
74 | -User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0]) | ||
75 | - | ||
76 | - | ||
77 | -class MailingList(models.Model): | ||
78 | - name = models.CharField(max_length=80) | ||
79 | - email = models.EmailField() | ||
80 | - description = models.TextField() | ||
81 | - logo = models.FileField(upload_to='list_logo') #TODO | ||
82 | - last_imported_index = models.IntegerField(default=0) | ||
83 | - | ||
84 | - def __unicode__(self): | ||
85 | - return self.name | ||
86 | - | ||
87 | - | ||
88 | -class MailingListMembership(models.Model): | ||
89 | - user = models.ForeignKey(User) | ||
90 | - mailinglist = models.ForeignKey(MailingList) | ||
91 | - | ||
92 | - def __unicode__(self): | ||
93 | - return '%s on %s' % (self.user.username, self.mailinglist.name) | ||
94 | - | ||
95 | - | ||
96 | -class Thread(models.Model): | ||
97 | - | ||
98 | - subject_token = models.CharField(max_length=512) | ||
99 | - mailinglist = models.ForeignKey(MailingList, | ||
100 | - verbose_name=_(u"Mailing List"), | ||
101 | - help_text=_(u"The Mailing List where is the thread")) | ||
102 | - latest_message = models.OneToOneField('Message', null=True, | ||
103 | - related_name='+', | ||
104 | - verbose_name=_(u"Latest message"), | ||
105 | - help_text=_(u"Latest message posted")) | ||
106 | - score = models.IntegerField(default=0, verbose_name=_(u"Score"), help_text=_(u"Thread score")) | ||
107 | - spam = models.BooleanField(default=False) | ||
108 | - | ||
109 | - all_objects = models.Manager() | ||
110 | - objects = NotSpamManager() | ||
111 | - | ||
112 | - class Meta: | ||
113 | - verbose_name = _(u"Thread") | ||
114 | - verbose_name_plural = _(u"Threads") | ||
115 | - unique_together = ('subject_token', 'mailinglist') | ||
116 | - | ||
117 | - def __unicode__(self): | ||
118 | - return '%s - %s (%s)' % (self.id, | ||
119 | - self.subject_token, | ||
120 | - self.message_set.count()) | ||
121 | - | ||
122 | - def update_score(self): | ||
123 | - """Update the relevance score for this thread. | ||
124 | - | ||
125 | - The score is calculated with the following variables: | ||
126 | - | ||
127 | - * vote_weight: 100 - (minus) 1 for each 3 days since | ||
128 | - voted with minimum of 5. | ||
129 | - * replies_weight: 300 - (minus) 1 for each 3 days since | ||
130 | - replied with minimum of 5. | ||
131 | - * page_view_weight: 10. | ||
132 | - | ||
133 | - * vote_score: sum(vote_weight) | ||
134 | - * replies_score: sum(replies_weight) | ||
135 | - * page_view_score: sum(page_view_weight) | ||
136 | - | ||
137 | - * score = (vote_score + replies_score + page_view_score) // 10 | ||
138 | - with minimum of 0 and maximum of 5000 | ||
139 | - | ||
140 | - """ | ||
141 | - | ||
142 | - if not self.subject_token: | ||
143 | - return | ||
144 | - | ||
145 | - # Save this pseudo now to avoid calling the | ||
146 | - # function N times in the loops below | ||
147 | - now = datetime.datetime.now() | ||
148 | - days_ago = lambda date: (now - date).days | ||
149 | - get_score = lambda weight, created: \ | ||
150 | - max(weight - (days_ago(created) // 3), 5) | ||
151 | - | ||
152 | - vote_score = 0 | ||
153 | - replies_score = 0 | ||
154 | - for msg in self.message_set.all(): | ||
155 | - # Calculate replies_score | ||
156 | - replies_score += get_score(300, msg.received_time) | ||
157 | - | ||
158 | - # Calculate vote_score | ||
159 | - for vote in msg.vote_set.all(): | ||
160 | - vote_score += get_score(100, vote.created) | ||
161 | - | ||
162 | - # Calculate page_view_score | ||
163 | - try: | ||
164 | - url = reverse('thread_view', args=[self.mailinglist.name, | ||
165 | - self.subject_token]) | ||
166 | - pagehit = PageHit.objects.get(url_path=url) | ||
167 | - page_view_score = pagehit.hit_count * 10 | ||
168 | - except (NoReverseMatch, PageHit.DoesNotExist): | ||
169 | - page_view_score = 0 | ||
170 | - | ||
171 | - self.score = (page_view_score + vote_score + replies_score) // 10 | ||
172 | - self.save() | ||
173 | - | ||
174 | - | ||
175 | -class Vote(models.Model): | ||
176 | - user = models.ForeignKey(User) | ||
177 | - message = models.ForeignKey('Message') | ||
178 | - created = models.DateTimeField(auto_now_add=True) | ||
179 | - | ||
180 | - class Meta: | ||
181 | - unique_together = ('user', 'message') | ||
182 | - | ||
183 | - def __unicode__(self): | ||
184 | - return 'Vote on %s by %s' % (self.Message.id, | ||
185 | - self.user.username) | ||
186 | - | ||
187 | - | ||
188 | -class Message(models.Model): | ||
189 | - | ||
190 | - from_address = models.ForeignKey(EmailAddress, db_index=True) | ||
191 | - thread = models.ForeignKey(Thread, null=True, db_index=True) | ||
192 | - # RFC 2822 recommends to use 78 chars + CRLF (so 80 chars) for | ||
193 | - # the max_length of a subject but most of implementations | ||
194 | - # goes for 256. We use 512 just in case. | ||
195 | - subject = models.CharField(max_length=512, db_index=True, | ||
196 | - verbose_name=_(u"Subject"), | ||
197 | - help_text=_(u"Please enter a message subject")) | ||
198 | - subject_clean = models.CharField(max_length=512, db_index=True) | ||
199 | - body = models.TextField(default='', | ||
200 | - verbose_name=_(u"Message body"), | ||
201 | - help_text=_(u"Please enter a message body")) | ||
202 | - received_time = models.DateTimeField() | ||
203 | - message_id = models.CharField(max_length=512) | ||
204 | - spam = models.BooleanField(default=False) | ||
205 | - | ||
206 | - all_objects = models.Manager() | ||
207 | - objects = NotSpamManager() | ||
208 | - | ||
209 | - class Meta: | ||
210 | - verbose_name = _(u"Message") | ||
211 | - verbose_name_plural = _(u"Messages") | ||
212 | - unique_together = ('thread', 'message_id') | ||
213 | - | ||
214 | - def __unicode__(self): | ||
215 | - return '(%s) %s: %s' % (self.id, | ||
216 | - self.from_address.get_full_name(), | ||
217 | - self.subject_clean) | ||
218 | - | ||
219 | - @property | ||
220 | - def mailinglist(self): | ||
221 | - if not self.thread or not self.thread.mailinglist: | ||
222 | - return None | ||
223 | - | ||
224 | - return self.thread.mailinglist | ||
225 | - | ||
226 | - | ||
227 | - def vote_list(self): | ||
228 | - """Return a list of user that voted in this message.""" | ||
229 | - | ||
230 | - return [vote.user for vote in self.vote_set.all()] | ||
231 | - | ||
232 | - def votes_count(self): | ||
233 | - return len(self.vote_list()) | ||
234 | - | ||
235 | - def vote(self, user): | ||
236 | - Vote.objects.create( | ||
237 | - message=self, | ||
238 | - user=user | ||
239 | - ) | ||
240 | - | ||
241 | - def unvote(self, user): | ||
242 | - Vote.objects.get( | ||
243 | - message=self, | ||
244 | - user=user | ||
245 | - ).delete() | ||
246 | - | ||
247 | - @property | ||
248 | - def url(self): | ||
249 | - """Shortcut to get thread url""" | ||
250 | - return reverse('thread_view', args=[self.mailinglist.name, | ||
251 | - self.thread.subject_token]) | ||
252 | - | ||
253 | - @property | ||
254 | - def Description(self): | ||
255 | - """Alias to self.body""" | ||
256 | - return self.body | ||
257 | - | ||
258 | - @property | ||
259 | - def Title(self): | ||
260 | - """Alias to self.subject_clean""" | ||
261 | - return self.subject_clean | ||
262 | - | ||
263 | - @property | ||
264 | - def modified(self): | ||
265 | - """Alias to self.modified""" | ||
266 | - return self.received_time | ||
267 | - | ||
268 | - | ||
269 | -class MessageMetadata(models.Model): | ||
270 | - Message = models.ForeignKey(Message) | ||
271 | - # Same problem here than on subjects. Read comment above | ||
272 | - # on Message.subject | ||
273 | - name = models.CharField(max_length=512) | ||
274 | - value = models.TextField() | ||
275 | - | ||
276 | - def __unicode__(self): | ||
277 | - return 'Email Message Id: %s - %s: %s' % (self.Message.id, | ||
278 | - self.name, self.value) | ||
279 | - |
colab/super_archives/queries.py
@@ -1,54 +0,0 @@ | @@ -1,54 +0,0 @@ | ||
1 | - | ||
2 | -from django.core.exceptions import ObjectDoesNotExist | ||
3 | -from colab.super_archives.models import Thread, Vote, Message, PageHit | ||
4 | - | ||
5 | - | ||
6 | -def get_messages_by_date(): | ||
7 | - return Message.objects.order_by('received_time') | ||
8 | - | ||
9 | - | ||
10 | -def get_messages_by_voted(): | ||
11 | - """Query for the most voted messages sorting by the sum of | ||
12 | - voted and after by date.""" | ||
13 | - | ||
14 | - sql = """ | ||
15 | - SELECT | ||
16 | - count(sav.id) | ||
17 | - FROM | ||
18 | - super_archives_vote AS sav | ||
19 | - WHERE | ||
20 | - super_archives_message.id = sav.message_id | ||
21 | - """ | ||
22 | - messages = Message.objects.extra( | ||
23 | - select={ | ||
24 | - 'vote_count': sql, | ||
25 | - } | ||
26 | - ) | ||
27 | - return messages.order_by('-vote_count', 'received_time') | ||
28 | - | ||
29 | - | ||
30 | -def get_first_message_in_thread(mailinglist, thread_token): | ||
31 | - query = get_messages_by_date() | ||
32 | - query = query.filter(thread__mailinglist__name=mailinglist) | ||
33 | - try: | ||
34 | - query = query.filter(thread__subject_token=thread_token)[0] | ||
35 | - except IndexError: | ||
36 | - raise ObjectDoesNotExist | ||
37 | - return query | ||
38 | - | ||
39 | - | ||
40 | -def get_latest_threads(): | ||
41 | - return Thread.objects.order_by('-latest_message__received_time') | ||
42 | - | ||
43 | - | ||
44 | -def get_hottest_threads(): | ||
45 | - return Thread.objects.order_by('-score', '-latest_message__received_time') | ||
46 | - | ||
47 | - | ||
48 | -def get_page_hits(path_info): | ||
49 | - pagehit = PageHit.objects.filter(url_path=path_info) | ||
50 | - | ||
51 | - if pagehit: | ||
52 | - return pagehit[0].hit_count | ||
53 | - return 0 | ||
54 | - |
colab/super_archives/templates/message-list.html
@@ -1,68 +0,0 @@ | @@ -1,68 +0,0 @@ | ||
1 | -{% extends "base.html" %} | ||
2 | -{% load i18n %} | ||
3 | -{% load append_to_get %} | ||
4 | -{% block main-content %} | ||
5 | -<div id="message-list"> | ||
6 | - <h2 class="span-5">{% trans "Discussions" %}</h2> | ||
7 | - <hr/> | ||
8 | - | ||
9 | - <div class="span-5 border filters"> | ||
10 | - <h3>{% trans "Filters" %}</h3> | ||
11 | - | ||
12 | - <h4>{% trans "Sort by" %}</h4> | ||
13 | - <ul> | ||
14 | - <li {% ifequal order_by "hottest" %} class="selected" title="{% trans "Remove filter" %}" {% endifequal %}> | ||
15 | - <a href="{% ifequal order_by "hottest" %} {% append_to_get order="",p=1 %} {% else %} {% append_to_get order='hottest',p=1 %} {% endifequal %}"> | ||
16 | - {% trans "Relevance" %}</a></li> | ||
17 | - <li {% ifequal order_by "latest" %} class="selected" title="{% trans "Remove filter" %}" {% endifequal %}> | ||
18 | - <a href="{% ifequal order_by "latest" %} {% append_to_get order="",p=1 %} {% else %} {% append_to_get order='latest',p=1 %} {% endifequal %}"> | ||
19 | - {% trans "Recent activity" %}</a></li> | ||
20 | - </ul> | ||
21 | - | ||
22 | - <hr class="space" /> | ||
23 | - | ||
24 | - <h4>{% trans "Lists" %}</h4> | ||
25 | - <ul> | ||
26 | - {% for list in lists %} | ||
27 | - <li {% ifequal list.name selected_list %} class="selected" title="{% trans "Remove filter" %}" {% endifequal %}> | ||
28 | - <a href="{% ifnotequal list.name selected_list %} {% append_to_get list=list.name,p=1 %} {% else %} {% append_to_get list="",p=1 %} | ||
29 | - {% endifnotequal %}">{{ list.name }}</a></li> | ||
30 | - {% endfor %} | ||
31 | - </ul> | ||
32 | - </div> | ||
33 | - | ||
34 | - <div class="span-17 prepend-1 last"> | ||
35 | - <ul> | ||
36 | - {% for thread in threads.object_list %} | ||
37 | - {% include "message-preview.html" with doc=thread.latest_message %} | ||
38 | - {% empty %} | ||
39 | - <br/><br/> | ||
40 | - <span class="span-18 center large"> | ||
41 | - <b>{% trans "No discussion found" %}</b> | ||
42 | - </span> | ||
43 | - {% endfor %} | ||
44 | - </ul> | ||
45 | - <hr class="space"/> | ||
46 | - | ||
47 | - {% if n_results %} | ||
48 | - <div class="pagination center"> | ||
49 | - <span class="step-links"> | ||
50 | - {% if threads.has_previous %} | ||
51 | - <a href="{% append_to_get p=threads.previous_page_number %}">{% trans "Previous" %}</a> | ||
52 | - {% endif %} | ||
53 | - | ||
54 | - <span class="current"> | ||
55 | - {% trans "Page" %} {{ threads.number }} {% trans "of" %} {{ threads.paginator.num_pages }} | ||
56 | - </span> | ||
57 | - | ||
58 | - {% if threads.has_next %} | ||
59 | - <a href="{% append_to_get p=threads.next_page_number %}">{% trans "Next" %}</a> | ||
60 | - {% endif %} | ||
61 | - </span> | ||
62 | - </div> | ||
63 | - {% endif %} | ||
64 | - | ||
65 | - </div> | ||
66 | -</div> | ||
67 | - | ||
68 | -{% endblock %} |
colab/super_archives/templates/message-preview.html
@@ -1,51 +0,0 @@ | @@ -1,51 +0,0 @@ | ||
1 | -{% load i18n %} | ||
2 | - | ||
3 | -{% if doc.Title %} | ||
4 | -<li class="preview-message"> | ||
5 | - {% if doc.Type %} | ||
6 | - <img alt="{{ doc.Type }}" title="{{ doc.Type }}" | ||
7 | - src="{{ STATIC_URL }}img/{{ doc.Type }}.png" /> | ||
8 | - {% else %} | ||
9 | - <img alt="thread" title="thread" | ||
10 | - src="{{ STATIC_URL }}img/thread.png" /> | ||
11 | - {% endif %} | ||
12 | - | ||
13 | - {% if doc.mailinglist %} | ||
14 | - <a href="{% url super_archives.views.list_messages %}?list={{ doc.mailinglist }}"> | ||
15 | - <span class="tag">{{ doc.mailinglist }}</span> | ||
16 | - </a> | ||
17 | - {% endif %} | ||
18 | - | ||
19 | - <span class="subject"> | ||
20 | - <a href="{{ doc.url }}" | ||
21 | - {% if | ||
22 | - title="{% filter striptags|truncatewords:50 %} | ||
23 | - {{ doc.Description|escape }} | ||
24 | - {% endfilter %}"> | ||
25 | - {{ doc.Title }} | ||
26 | - </a> | ||
27 | - </span> | ||
28 | - | ||
29 | - <span class="quiet">- | ||
30 | - {{ doc.Description|striptags }} | ||
31 | - </span> | ||
32 | - | ||
33 | - <div class="quiet"> | ||
34 | - <span class="left"> | ||
35 | - {% trans "by" %} | ||
36 | - {% if doc.from_address.get_full_name %} | ||
37 | - <a href="{{ doc.from_address.get_profile_link }}"> | ||
38 | - {{ doc.from_address.get_full_name }} | ||
39 | - </a> | ||
40 | - {% else %} | ||
41 | - {% firstof doc.last_author doc.Creator _("anônimo") %} | ||
42 | - {% endif %} | ||
43 | - </span> | ||
44 | - | ||
45 | - <span class="right"> | ||
46 | - {{ doc.modified|timesince }} | ||
47 | - {% trans "back" %} | ||
48 | - </span> | ||
49 | - </div> | ||
50 | -</li> | ||
51 | -{% endif %} |
colab/super_archives/templates/message-thread.html
@@ -1,77 +0,0 @@ | @@ -1,77 +0,0 @@ | ||
1 | -{% extends "base.html" %} | ||
2 | -{% load i18n %} | ||
3 | -{% load append_to_get %} | ||
4 | -{% block main-content %} | ||
5 | - <div id="vote-notification" class="error hide"></div> | ||
6 | - | ||
7 | - <h2>{{ first_msg.subject_clean }}</h2> | ||
8 | - <hr/> | ||
9 | - <div class="span-17 border"> | ||
10 | - <ul> | ||
11 | - {% for email in emails %} | ||
12 | - <li> | ||
13 | - <div id="msg-{{ email.id }}" class="email_message"> | ||
14 | - <div class="span-3 center"> | ||
15 | - <div> | ||
16 | - <a href="{{ email.from_address.get_profile_link }}"> | ||
17 | - <img class="avatar" width="80px" heigth="80px" | ||
18 | - src="http://www.gravatar.com/avatar/{{ email.from_address.md5 }}?s=80&d=identicon" /> | ||
19 | - <span>{% firstof email.from_address.get_full_name "Anônimo" %}</span> | ||
20 | - </a> | ||
21 | - </div> | ||
22 | - <p>{{ email.received_time|date:"SHORT_DATETIME_FORMAT" }}</p> | ||
23 | - | ||
24 | - <div class="plus"> | ||
25 | - <span>{{ email.votes_count }}</span> | ||
26 | - <img title="{% trans 'Vote' %}" class="right" src="{{ STATIC_URL }}img/plus.png"> | ||
27 | - </div> | ||
28 | - | ||
29 | - <p class="minus {% if not user in email.vote_list %}hide{% endif %}"> | ||
30 | - <a href="#">{% trans "Remove votes" %}</a> | ||
31 | - </p> | ||
32 | - </div> | ||
33 | - | ||
34 | - <div class="span-13"> | ||
35 | - <pre>{{ email.body }}</pre> | ||
36 | - </div> | ||
37 | - </div> | ||
38 | - {% if not forloop.last %} | ||
39 | - <hr/> | ||
40 | - {% endif %} | ||
41 | - </li> | ||
42 | - {% endfor %} | ||
43 | - </ul> | ||
44 | - </div> | ||
45 | - <div class="span-6 filters last"> | ||
46 | - <h4><b>{% trans "Order by" %}:</b></h4> | ||
47 | - <ul> | ||
48 | - <li><a href="{% append_to_get order='voted' %}">{% trans "Votes" %}</a></li> | ||
49 | - <li><a href="{% append_to_get order='date' %}">{% trans "Data" %}</a></li> | ||
50 | - </ul> | ||
51 | - | ||
52 | - <hr class="space"/> | ||
53 | - | ||
54 | - <h4><b>{% trans "Statistics:" %}</b></h4> | ||
55 | - | ||
56 | - <ul> | ||
57 | - <li class="quiet">{% trans "started at" %} | ||
58 | - <h4>{{ first_msg.received_time|timesince }} {% trans "back" %}</h4> | ||
59 | - </li> | ||
60 | - <li class="quiet">{% trans "viewed" %} | ||
61 | - <h4>{{ pagehits }} {% trans "times" %}</h4> | ||
62 | - </li> | ||
63 | - <li class="quiet">{% trans "answered" %} | ||
64 | - <h4>{{ emails|length }} {% trans "times" %}</h4> | ||
65 | - </li> | ||
66 | - <li class="quiet">{% trans "voted" %} | ||
67 | - <h4>{{ total_votes }} {% trans "times" %}</h4> | ||
68 | - </li> | ||
69 | - </ul> | ||
70 | - | ||
71 | - </div> | ||
72 | - | ||
73 | - <script type="text/javascript" charset="utf-8"> | ||
74 | - pagehit("{{ request.path_info }}"); | ||
75 | - </script> | ||
76 | - | ||
77 | -{% endblock %} |
colab/super_archives/templatetags/__init__.py
colab/super_archives/templatetags/append_to_get.py
@@ -1,56 +0,0 @@ | @@ -1,56 +0,0 @@ | ||
1 | - | ||
2 | -import urllib | ||
3 | -from django import template | ||
4 | - | ||
5 | -register = template.Library() | ||
6 | - | ||
7 | -""" | ||
8 | -Decorator to facilitate template tag creation | ||
9 | -""" | ||
10 | -def easy_tag(func): | ||
11 | - """deal with the repetitive parts of parsing template tags""" | ||
12 | - def inner(parser, token): | ||
13 | - #print token | ||
14 | - try: | ||
15 | - return func(*token.split_contents()) | ||
16 | - except TypeError: | ||
17 | - raise template.TemplateSyntaxError('Bad arguments for tag "%s"' % | ||
18 | - token.split_contents()[0]) | ||
19 | - inner.__name__ = func.__name__ | ||
20 | - inner.__doc__ = inner.__doc__ | ||
21 | - return inner | ||
22 | - | ||
23 | - | ||
24 | -class AppendGetNode(template.Node): | ||
25 | - def __init__(self, dict): | ||
26 | - self.dict_pairs = {} | ||
27 | - for pair in dict.split(','): | ||
28 | - pair = pair.split('=') | ||
29 | - self.dict_pairs[pair[0]] = template.Variable(pair[1]) | ||
30 | - | ||
31 | - def render(self, context): | ||
32 | - get = context['request'].GET.copy() | ||
33 | - | ||
34 | - for key in self.dict_pairs: | ||
35 | - get[key] = self.dict_pairs[key].resolve(context) | ||
36 | - | ||
37 | - path = context['request'].META['PATH_INFO'] | ||
38 | - | ||
39 | - if len(get): | ||
40 | - # Convert all unicode objects in the get dict to | ||
41 | - # str (utf-8 encoded) | ||
42 | - get_utf_encoded = {} | ||
43 | - for (key, value) in get.items(): | ||
44 | - if isinstance(value, unicode): | ||
45 | - value = value.encode('utf-8') | ||
46 | - get_utf_encoded.update({key: value}) | ||
47 | - get_utf_encoded = dict(get_utf_encoded) | ||
48 | - | ||
49 | - path = '?' + urllib.urlencode(get_utf_encoded) | ||
50 | - | ||
51 | - return path | ||
52 | - | ||
53 | -@register.tag() | ||
54 | -@easy_tag | ||
55 | -def append_to_get(_tag_name, dict): | ||
56 | - return AppendGetNode(dict) |
colab/super_archives/templatetags/form_field.py
@@ -1,64 +0,0 @@ | @@ -1,64 +0,0 @@ | ||
1 | -from django import template | ||
2 | -from django import forms | ||
3 | - | ||
4 | -def render_form_field(parser, token): | ||
5 | - variables = token.split_contents() | ||
6 | - | ||
7 | - if len(variables) == 2: | ||
8 | - tag_name, form_field = variables | ||
9 | - default_value = 'None' | ||
10 | - elif len(variables) == 3: | ||
11 | - tag_name, form_field, default_value = variables | ||
12 | - else: | ||
13 | - raise template.TemplateSyntaxError | ||
14 | - | ||
15 | - return RenderFormField(form_field, default_value) | ||
16 | - | ||
17 | - | ||
18 | -class RenderFormField(template.Node): | ||
19 | - | ||
20 | - def __init__(self, form_field, default_value): | ||
21 | - self.form_field_nocontext = template.Variable(form_field) | ||
22 | - self.default_value_nocontext = template.Variable(default_value) | ||
23 | - | ||
24 | - def render(self, context): | ||
25 | - editable = context.get('editable', True) | ||
26 | - | ||
27 | - class_ = u'' | ||
28 | - errors = u'' | ||
29 | - form_field_tag = u'' | ||
30 | - try: | ||
31 | - form_field = self.form_field_nocontext.resolve(context) | ||
32 | - except template.VariableDoesNotExist: | ||
33 | - return u'' | ||
34 | - | ||
35 | - if form_field.errors: | ||
36 | - class_ += u'error' | ||
37 | - if form_field.field.required: | ||
38 | - class_ += u' required' | ||
39 | - if form_field.errors: | ||
40 | - errors = u'<br/>' + form_field.errors.as_text() | ||
41 | - | ||
42 | - try: | ||
43 | - default_value = self.default_value_nocontext.resolve(context) | ||
44 | - except template.VariableDoesNotExist: | ||
45 | - default_value = u'' | ||
46 | - | ||
47 | - if editable: | ||
48 | - form_field_tag = u'<br/>' + unicode(form_field) | ||
49 | - elif isinstance(form_field.field, forms.URLField): | ||
50 | - form_field_tag = u"""<a href="%s" target="_blank">%s</a>""" % ( | ||
51 | - default_value, default_value) | ||
52 | - else: | ||
53 | - form_field_tag = default_value | ||
54 | - | ||
55 | - return u"""<p class="%s">%s: %s %s</p>""" % ( | ||
56 | - class_, | ||
57 | - form_field.label_tag(), | ||
58 | - form_field_tag, | ||
59 | - errors | ||
60 | - ) | ||
61 | - | ||
62 | - | ||
63 | -register = template.Library() | ||
64 | -register.tag('render_form_field', render_form_field) |
colab/super_archives/tests.py
@@ -1,16 +0,0 @@ | @@ -1,16 +0,0 @@ | ||
1 | -""" | ||
2 | -This file demonstrates writing tests using the unittest module. These will pass | ||
3 | -when you run "manage.py test". | ||
4 | - | ||
5 | -Replace this with more appropriate tests for your application. | ||
6 | -""" | ||
7 | - | ||
8 | -from django.test import TestCase | ||
9 | - | ||
10 | - | ||
11 | -class SimpleTest(TestCase): | ||
12 | - def test_basic_addition(self): | ||
13 | - """ | ||
14 | - Tests that 1 + 1 always equals 2. | ||
15 | - """ | ||
16 | - self.assertEqual(1 + 1, 2) |
colab/super_archives/urls.py
@@ -1,9 +0,0 @@ | @@ -1,9 +0,0 @@ | ||
1 | -from django.conf.urls.defaults import patterns, include, url | ||
2 | - | ||
3 | -urlpatterns = patterns('', | ||
4 | -# url(r'thread/(?P<thread>\d+)/$', 'super_archives.views.thread', name='thread'), | ||
5 | - url(r'thread/(?P<mailinglist>[-\w]+)/(?P<thread_token>[-\w]+)$', | ||
6 | - 'colab.super_archives.views.thread', name="thread_view"), | ||
7 | - url(r'thread/$', | ||
8 | - 'colab.super_archives.views.list_messages', name='thread_list') | ||
9 | -) |
colab/super_archives/validators.py
@@ -1,15 +0,0 @@ | @@ -1,15 +0,0 @@ | ||
1 | -# -*- coding: utf-8 -*- | ||
2 | - | ||
3 | -from django.core.exceptions import ValidationError | ||
4 | - | ||
5 | -class UniqueValidator(object): | ||
6 | - | ||
7 | - def __init__(self, model, field_name): | ||
8 | - self.model = model | ||
9 | - self.field_name = field_name | ||
10 | - | ||
11 | - def __call__(self, value): | ||
12 | - result = self.model.objects.filter(**{self.field_name: value}) | ||
13 | - if result: | ||
14 | - msg = u'Já existente. Escolha outro.' | ||
15 | - raise ValidationError(msg) |
colab/super_archives/views.py
@@ -1,80 +0,0 @@ | @@ -1,80 +0,0 @@ | ||
1 | -# -*- coding: utf-8 -*- | ||
2 | - | ||
3 | -from django.http import Http404 | ||
4 | -from django.template import RequestContext | ||
5 | -from django.core.paginator import Paginator | ||
6 | -from django.core.exceptions import ObjectDoesNotExist | ||
7 | -from django.shortcuts import render_to_response, get_list_or_404 | ||
8 | - | ||
9 | -from colab.super_archives import queries | ||
10 | -from colab.super_archives.models import MailingList, Thread | ||
11 | - | ||
12 | - | ||
13 | -def thread(request, mailinglist, thread_token): | ||
14 | - | ||
15 | - try: | ||
16 | - first_message = queries.get_first_message_in_thread(mailinglist, thread_token) | ||
17 | - except ObjectDoesNotExist: | ||
18 | - raise Http404 | ||
19 | - order_by = request.GET.get('order') | ||
20 | - if order_by == 'voted': | ||
21 | - msgs_query = queries.get_messages_by_voted() | ||
22 | - else: | ||
23 | - msgs_query = queries.get_messages_by_date() | ||
24 | - | ||
25 | - msgs_query = msgs_query.filter(thread__subject_token=thread_token) | ||
26 | - msgs_query = msgs_query.filter(thread__mailinglist__name=mailinglist) | ||
27 | - emails = msgs_query.exclude(id=first_message.id) | ||
28 | - | ||
29 | - total_votes = first_message.votes_count() | ||
30 | - for email in emails: | ||
31 | - total_votes += email.votes_count() | ||
32 | - | ||
33 | - # Update relevance score | ||
34 | - query = Thread.objects.filter(mailinglist__name=mailinglist) | ||
35 | - thread = query.get(subject_token=thread_token) | ||
36 | - thread.update_score() | ||
37 | - | ||
38 | - template_data = { | ||
39 | - 'first_msg': first_message, | ||
40 | - 'emails': [first_message] + list(emails), | ||
41 | - 'pagehits': queries.get_page_hits(request.path_info), | ||
42 | - 'total_votes': total_votes, | ||
43 | - } | ||
44 | - | ||
45 | - return render_to_response('message-thread.html', template_data, | ||
46 | - RequestContext(request)) | ||
47 | - | ||
48 | - | ||
49 | -def list_messages(request): | ||
50 | - | ||
51 | - selected_list = request.GET.get('list') | ||
52 | - | ||
53 | - order_by = request.GET.get('order') | ||
54 | - if order_by == 'hottest': | ||
55 | - threads = queries.get_hottest_threads() | ||
56 | - else: | ||
57 | - threads = queries.get_latest_threads() | ||
58 | - | ||
59 | - mail_list = request.GET.get('list') | ||
60 | - if mail_list: | ||
61 | - threads = threads.filter(mailinglist__name=mail_list) | ||
62 | - | ||
63 | - paginator = Paginator(threads, 16) | ||
64 | - try: | ||
65 | - page = int(request.GET.get('p', '1')) | ||
66 | - except ValueError: | ||
67 | - page = 1 | ||
68 | - threads = paginator.page(page) | ||
69 | - | ||
70 | - lists = MailingList.objects.all() | ||
71 | - | ||
72 | - template_data = { | ||
73 | - 'lists': lists, | ||
74 | - 'n_results': paginator.count, | ||
75 | - 'threads': threads, | ||
76 | - 'selected_list': selected_list, | ||
77 | - 'order_by': order_by, | ||
78 | - } | ||
79 | - return render_to_response('message-list.html', template_data, | ||
80 | - RequestContext(request)) |
@@ -0,0 +1,103 @@ | @@ -0,0 +1,103 @@ | ||
1 | + | ||
2 | +from django.core.cache import cache | ||
3 | +from django.db import IntegrityError | ||
4 | +from django.core.exceptions import ObjectDoesNotExist | ||
5 | +from django.contrib.auth.decorators import login_required | ||
6 | + | ||
7 | +from piston.utils import rc | ||
8 | +from piston.handler import BaseHandler | ||
9 | + | ||
10 | +from colab import solrutils | ||
11 | +from colab.super_archives.models import Message, PageHit | ||
12 | + | ||
13 | + | ||
14 | +class VoteHandler(BaseHandler): | ||
15 | + allowed_methods = ('GET', 'POST', 'DELETE') | ||
16 | + | ||
17 | + def create(self, request, message_id): | ||
18 | + if not request.user.is_authenticated(): | ||
19 | + return rc.FORBIDDEN | ||
20 | + | ||
21 | + try: | ||
22 | + Message.objects.get(id=message_id).vote(request.user) | ||
23 | + except IntegrityError: | ||
24 | + return rc.DUPLICATE_ENTRY | ||
25 | + | ||
26 | + return rc.CREATED | ||
27 | + | ||
28 | + def read(self, request, message_id): | ||
29 | + return Message.objects.get(id=message_id).votes_count() | ||
30 | + | ||
31 | + def delete(self, request, message_id): | ||
32 | + if not request.user.is_authenticated(): | ||
33 | + return rc.FORBIDDEN | ||
34 | + | ||
35 | + try: | ||
36 | + Message.objects.get(id=message_id).unvote(request.user) | ||
37 | + except ObjectDoesNotExist: | ||
38 | + return rc.NOT_HERE | ||
39 | + | ||
40 | + return rc.DELETED | ||
41 | + | ||
42 | + | ||
43 | +class CountHandler(BaseHandler): | ||
44 | + allowed_methods = ('POST') | ||
45 | + | ||
46 | + def create(self, request): | ||
47 | + """Add one page view for the given url""" | ||
48 | + | ||
49 | + # If missing the path_info argument we can't do anything | ||
50 | + path_info = request.POST.get('path_info') | ||
51 | + if not path_info: | ||
52 | + return rc.BAD_REQUEST | ||
53 | + | ||
54 | + # Here we cache the user's IP to ensure that the same | ||
55 | + # IP won't hit the same page again for while | ||
56 | + ip_addr = request.META.get('REMOTE_ADDR') | ||
57 | + page_hits_cache = cache.get('page_hits', {}) | ||
58 | + duplicate = page_hits_cache.get(path_info, {}).get(ip_addr) | ||
59 | + | ||
60 | + if duplicate: | ||
61 | + return rc.DUPLICATE_ENTRY | ||
62 | + else: | ||
63 | + page_hits_cache.update({path_info: {ip_addr: True }}) | ||
64 | + cache.set('page_hits', page_hits_cache) | ||
65 | + | ||
66 | + # Everything ok, so just increment the page count | ||
67 | + page_hit = PageHit.objects.get_or_create(url_path=path_info)[0] | ||
68 | + page_hit.hit_count += 1 | ||
69 | + page_hit.save() | ||
70 | + | ||
71 | + return rc.CREATED | ||
72 | + | ||
73 | +class SearchHandler(BaseHandler): | ||
74 | + allowed_methods = ('GET', ) | ||
75 | + | ||
76 | + def read(self, request): | ||
77 | + query = request.GET.get('q') | ||
78 | + page = request.GET.get('p', 1) | ||
79 | + results_per_page = request.GET.get('n', 50) | ||
80 | + order = request.GET.get('o') | ||
81 | + | ||
82 | + if not query: | ||
83 | + return 'Query cannot be empty.' | ||
84 | + else: | ||
85 | + query = query.encode('utf-8') | ||
86 | + | ||
87 | + try: | ||
88 | + n = int(results_per_page) | ||
89 | + except ValueError: | ||
90 | + n = 10 | ||
91 | + | ||
92 | + if 1 > n > 500: | ||
93 | + n = 1 | ||
94 | + | ||
95 | + try: | ||
96 | + page = int(page) | ||
97 | + except ValueError: | ||
98 | + page = 1 | ||
99 | + | ||
100 | + if page < 1: | ||
101 | + page = 1 | ||
102 | + | ||
103 | + return solrutils.select(query, results_per_page, page, order) |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +from django.conf.urls.defaults import patterns, include, url | ||
2 | + | ||
3 | +from piston.resource import Resource | ||
4 | + | ||
5 | +from colab.api.handlers import VoteHandler, CountHandler, SearchHandler | ||
6 | + | ||
7 | + | ||
8 | +vote_handler = Resource(VoteHandler) | ||
9 | +count_handler = Resource(CountHandler) | ||
10 | +search_handler = Resource(SearchHandler) | ||
11 | + | ||
12 | +urlpatterns = patterns('', | ||
13 | + url(r'message/(?P<message_id>\d+)/vote$', vote_handler), | ||
14 | + url(r'hit/$', count_handler), | ||
15 | + url(r'search/$', search_handler), | ||
16 | +) |
@@ -0,0 +1,78 @@ | @@ -0,0 +1,78 @@ | ||
1 | +#!/usr/bin/env python | ||
2 | +# encoding: utf-8 | ||
3 | + | ||
4 | +from django.contrib.syndication.views import Feed | ||
5 | +from django.utils.translation import ugettext as _ | ||
6 | + | ||
7 | +from colab.super_archives.models import Thread | ||
8 | +from colab.super_archives import queries | ||
9 | +from colab import solrutils | ||
10 | + | ||
11 | +class LatestThreadsFeeds(Feed): | ||
12 | + title = _(u'Latest Discussions') | ||
13 | + link = '/rss/threads/latest/' | ||
14 | + | ||
15 | + def items(self): | ||
16 | + return queries.get_latest_threads()[:20] | ||
17 | + | ||
18 | + def item_link(self, item): | ||
19 | + return item.latest_message.url | ||
20 | + | ||
21 | + def item_title(self, item): | ||
22 | + title = '[' + item.mailinglist.name + '] ' | ||
23 | + title += item.latest_message.subject_clean | ||
24 | + return title | ||
25 | + | ||
26 | + def item_description(self, item): | ||
27 | + return item.latest_message.body | ||
28 | + | ||
29 | + | ||
30 | +class HottestThreadsFeeds(Feed): | ||
31 | + title = _(u'Discussions Most Relevance') | ||
32 | + link = '/rss/threads/hottest/' | ||
33 | + | ||
34 | + def items(self): | ||
35 | + return queries.get_hottest_threads()[:20] | ||
36 | + | ||
37 | + def item_link(self, item): | ||
38 | + return item.latest_message.url | ||
39 | + | ||
40 | + def item_title(self, item): | ||
41 | + title = '[' + item.mailinglist.name + '] ' | ||
42 | + title += item.latest_message.subject_clean | ||
43 | + return title | ||
44 | + | ||
45 | + def item_description(self, item): | ||
46 | + return item.latest_message.body | ||
47 | + | ||
48 | + | ||
49 | +class LatestColabFeeds(Feed): | ||
50 | + title = _(u'Latest collaborations') | ||
51 | + link = '/rss/colab/latest/' | ||
52 | + | ||
53 | + def items(self): | ||
54 | + items = solrutils.get_latest_collaborations(20) | ||
55 | + return items | ||
56 | + | ||
57 | + def item_title(self, item): | ||
58 | + type_ = item.get('Type') + ': ' | ||
59 | + mailinglist = item.get('mailinglist') | ||
60 | + | ||
61 | + if mailinglist: | ||
62 | + prefix = type_ + mailinglist + ' - ' | ||
63 | + else: | ||
64 | + prefix = type_ | ||
65 | + | ||
66 | + return prefix + item.get('Title') | ||
67 | + | ||
68 | + def item_description(self, item): | ||
69 | + return item.get('Description') | ||
70 | + | ||
71 | + def item_link(self, item): | ||
72 | + if item.get('Type') != 'thread': | ||
73 | + url = item.get('url') | ||
74 | + else: | ||
75 | + url = 'http://colab.interlegis.leg.br' | ||
76 | + url += item.get('url') | ||
77 | + return url | ||
78 | + |
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +from django.conf.urls.defaults import patterns, url | ||
2 | +import feeds | ||
3 | + | ||
4 | +urlpatterns = patterns('', | ||
5 | + url(r'threads/latest/$', feeds.LatestThreadsFeeds(), name='rss_latest_threads'), | ||
6 | + url(r'colab/latest/$', feeds.LatestColabFeeds(), name='rss_latest_colab'), | ||
7 | + url(r'threads/hottest/$', feeds.HottestThreadsFeeds(), name='rss_hottest_threads'), | ||
8 | +) | ||
9 | + |
@@ -0,0 +1,54 @@ | @@ -0,0 +1,54 @@ | ||
1 | + | ||
2 | +from django.contrib import admin | ||
3 | +from colab.super_archives.models import Message, Thread, UserProfile | ||
4 | + | ||
5 | +class MessageAdmin(admin.ModelAdmin): | ||
6 | + list_filter = ('spam', 'thread__mailinglist', 'received_time', ) | ||
7 | + search_fields = ( | ||
8 | + 'id', | ||
9 | + 'subject', | ||
10 | + 'subject_clean', | ||
11 | + 'body', | ||
12 | + 'from_address__real_name', | ||
13 | + 'from_address__address', | ||
14 | + 'from_address__user__first_name', | ||
15 | + 'from_address__user__last_name', | ||
16 | + 'from_address__user__username', | ||
17 | + ) | ||
18 | + readonly_fields = ('thread', 'from_address', 'mailinglist') | ||
19 | + | ||
20 | + | ||
21 | +class ThreadAdmin(admin.ModelAdmin): | ||
22 | + list_filter = ('spam', 'mailinglist', 'message__received_time',) | ||
23 | + search_fields = ( | ||
24 | + 'id', | ||
25 | + 'subject_token', | ||
26 | + 'message__subject', | ||
27 | + 'message__subject_clean', | ||
28 | + 'message__from_address__real_name', | ||
29 | + 'message__from_address__address', | ||
30 | + 'message__from_address__user__first_name', | ||
31 | + 'message__from_address__user__last_name', | ||
32 | + 'message__from_address__user__username', | ||
33 | + ) | ||
34 | + | ||
35 | + readonly_fields = ( | ||
36 | + 'mailinglist', | ||
37 | + 'subject_token', | ||
38 | + 'latest_message', | ||
39 | + 'score', | ||
40 | + ) | ||
41 | + | ||
42 | + fields = ( | ||
43 | + 'mailinglist', | ||
44 | + 'subject_token', | ||
45 | + 'latest_message', | ||
46 | + 'score', | ||
47 | + 'spam', | ||
48 | + ) | ||
49 | + | ||
50 | + | ||
51 | +admin.site.register(UserProfile) | ||
52 | +admin.site.register(Thread, ThreadAdmin) | ||
53 | +admin.site.register(Message, MessageAdmin) | ||
54 | + |
@@ -0,0 +1,66 @@ | @@ -0,0 +1,66 @@ | ||
1 | +# -*- coding: utf-8 -*- | ||
2 | + | ||
3 | +from django import forms | ||
4 | +from django.core.exceptions import ValidationError | ||
5 | +from django.contrib.auth.models import User | ||
6 | +from django.contrib.auth.forms import UserCreationForm as UserCreationForm_ | ||
7 | +from django.utils.translation import ugettext_lazy as _ | ||
8 | + | ||
9 | +from colab.super_archives.models import MailingList | ||
10 | +from colab.super_archives.validators import UniqueValidator | ||
11 | + | ||
12 | +# XXX: I know that this code does not look nice AT ALL. | ||
13 | +# probably it should be implemented using formsets instead of | ||
14 | +# the hack below. Feel free to improve it! :) | ||
15 | + | ||
16 | +# User fields | ||
17 | +username_field = UserCreationForm_().fields.get(u'username') | ||
18 | +first_name_field = forms.CharField(max_length=30, label=_(u'Name')) | ||
19 | +last_name_field = forms.CharField(max_length=30, label=_(u'Last name')) | ||
20 | +email_field = forms.EmailField(validators=[UniqueValidator(User, 'email')]) | ||
21 | + | ||
22 | +# UserProfile fields | ||
23 | +institution_field = forms.CharField(max_length=120, label=_(u'Institution'), | ||
24 | + required=False) | ||
25 | +role_field = forms.CharField(max_length=60, label=_(u'Function'), required=False) | ||
26 | +twitter_field = forms.URLField(label=_(u'Twitter'), required=False) | ||
27 | +facebook_field = forms.URLField(label=_(u'Facebook'), required=False) | ||
28 | +google_talk_field = forms.EmailField(label=_(u'Google Talk'), required=False) | ||
29 | +webpage_field = forms.URLField(label=_(u'Personal Website/Blog'), required=False) | ||
30 | + | ||
31 | +all_lists = MailingList.objects.all() | ||
32 | +lists_names = [] | ||
33 | +for list_ in all_lists: | ||
34 | + choice = (list_.name, list_.name) | ||
35 | + lists_names.append(choice) | ||
36 | + | ||
37 | +lists_field = forms.MultipleChoiceField( | ||
38 | + label=u'Listas', | ||
39 | + required=False, | ||
40 | + widget=forms.CheckboxSelectMultiple, | ||
41 | + choices=lists_names | ||
42 | +) | ||
43 | + | ||
44 | + | ||
45 | +class UserCreationForm(UserCreationForm_): | ||
46 | + first_name = first_name_field | ||
47 | + last_name = last_name_field | ||
48 | + email = email_field | ||
49 | + institution = institution_field | ||
50 | + role = role_field | ||
51 | + twitter = twitter_field | ||
52 | + facebook = facebook_field | ||
53 | + google_talk = google_talk_field | ||
54 | + webpage = webpage_field | ||
55 | + lists = lists_field | ||
56 | + | ||
57 | + | ||
58 | +class UserUpdateForm(forms.Form): | ||
59 | + username = username_field | ||
60 | + username.required = False | ||
61 | + institution = institution_field | ||
62 | + role = role_field | ||
63 | + twitter = twitter_field | ||
64 | + facebook = facebook_field | ||
65 | + google_talk = google_talk_field | ||
66 | + webpage = webpage_field |
@@ -0,0 +1,258 @@ | @@ -0,0 +1,258 @@ | ||
1 | +#!/usr/bin/env python | ||
2 | +# -*- encoding: utf-8 -*- | ||
3 | + | ||
4 | +"""Import emails from a mailman storage to the django database.""" | ||
5 | + | ||
6 | +import os | ||
7 | +import re | ||
8 | +import sys | ||
9 | +import mailbox | ||
10 | +from optparse import make_option | ||
11 | + | ||
12 | +from django.db import transaction | ||
13 | +from django.template.defaultfilters import slugify | ||
14 | +from django.core.management.base import BaseCommand, CommandError | ||
15 | + | ||
16 | +from colab.super_archives.models import MailingList, Message, \ | ||
17 | + Thread, EmailAddress | ||
18 | +from colab.super_archives.management.commands.message import Message as \ | ||
19 | + CustomMessage | ||
20 | + | ||
21 | + | ||
22 | +class Command(BaseCommand, object): | ||
23 | + """Get emails from mailman archives and import them in the django db. """ | ||
24 | + | ||
25 | + help = __doc__ | ||
26 | + | ||
27 | + default_archives_path = '/var/lib/mailman/archives/private' | ||
28 | + RE_SUBJECT_CLEAN = re.compile('((re|res|fw|fwd|en|enc):)|\[.*?\]', | ||
29 | + re.IGNORECASE) | ||
30 | + THREAD_CACHE = {} | ||
31 | + EMAIL_ADDR_CACHE = {} | ||
32 | + | ||
33 | + # A new command line option to get the dump file to parse. | ||
34 | + option_list = BaseCommand.option_list + ( | ||
35 | + make_option('--archives_path', | ||
36 | + dest='archives_path', | ||
37 | + help='Path of email archives to be imported. (default: %s)' % | ||
38 | + default_archives_path, | ||
39 | + default=default_archives_path), | ||
40 | + | ||
41 | + make_option('--exclude-list', | ||
42 | + dest='exclude_lists', | ||
43 | + help=("Mailing list that won't be imported. It can be used many" | ||
44 | + "times for more than one list."), | ||
45 | + action='append', | ||
46 | + default=None), | ||
47 | + | ||
48 | + make_option('--all', | ||
49 | + dest='all', | ||
50 | + help='Import all messages (default: False)', | ||
51 | + action="store_true", | ||
52 | + default=False), | ||
53 | + ) | ||
54 | + | ||
55 | + def __init__(self, *args, **kwargs): | ||
56 | + super(Command, self).__init__(*args, **kwargs) | ||
57 | + | ||
58 | + def log(self, msg, error=False): | ||
59 | + """Log message helper.""" | ||
60 | + output = self.stdout | ||
61 | + if error: | ||
62 | + output = self.stderr | ||
63 | + | ||
64 | + output.write(msg) | ||
65 | + output.write('\n') | ||
66 | + | ||
67 | + def parse_emails(self, email_filename, index=0): | ||
68 | + """Generator function that parse and extract emails from the file | ||
69 | + `email_filename` starting from the position `index`. | ||
70 | + | ||
71 | + Yield: An instance of `mailbox.mboxMessage` for each email in the | ||
72 | + file. | ||
73 | + | ||
74 | + """ | ||
75 | + self.log("Parsing email dump: %s." % email_filename) | ||
76 | + mbox = mailbox.mbox(email_filename, factory=CustomMessage) | ||
77 | + | ||
78 | + # Get each email from mbox file | ||
79 | + # | ||
80 | + # The following implementation was used because the object | ||
81 | + # mbox does not support slicing. Converting the object to a | ||
82 | + # tuple (as represented in the code down here) was a valid | ||
83 | + # option but its performance was too poor. | ||
84 | + # | ||
85 | + #for message in tuple(mbox)[index:]: | ||
86 | + # yield message | ||
87 | + # | ||
88 | + key = index | ||
89 | + while mbox.has_key(key): | ||
90 | + key += 1 | ||
91 | + yield key-1, mbox[key-1] | ||
92 | + | ||
93 | + def get_emails(self, mailinglist_dir, all, exclude_lists): | ||
94 | + """Generator function that get the emails from each mailing | ||
95 | + list dump dirctory. If `all` is set to True all the emails in the | ||
96 | + mbox will be imported if not it will just resume from the last | ||
97 | + message previously imported. The lists set in `exclude_lists` | ||
98 | + won't be imported. | ||
99 | + | ||
100 | + Yield: A tuple in the form: (mailing list name, email message). | ||
101 | + | ||
102 | + """ | ||
103 | + self.log("Getting emails dumps from: %s" % mailinglist_dir) | ||
104 | + | ||
105 | + # Get the list of directories ending with .mbox | ||
106 | + mailing_lists_mboxes = (mbox for mbox in os.listdir(mailinglist_dir) | ||
107 | + if mbox.endswith('.mbox')) | ||
108 | + | ||
109 | + # Get messages from each mbox | ||
110 | + for mbox in mailing_lists_mboxes: | ||
111 | + mbox_path = os.path.join(mailinglist_dir, mbox, mbox) | ||
112 | + mailinglist_name = mbox.split('.')[0] | ||
113 | + | ||
114 | + # Check if the mailinglist is set not to be imported | ||
115 | + if exclude_lists and mailinglist_name in exclude_lists: | ||
116 | + continue | ||
117 | + | ||
118 | + # Find the index of the last imported message | ||
119 | + if all: | ||
120 | + n_msgs = 0 | ||
121 | + else: | ||
122 | + try: | ||
123 | + mailinglist = MailingList.objects.get( | ||
124 | + name=mailinglist_name) | ||
125 | + n_msgs = mailinglist.last_imported_index | ||
126 | + except MailingList.DoesNotExist: | ||
127 | + n_msgs = 0 | ||
128 | + | ||
129 | + for index, msg in self.parse_emails(mbox_path, n_msgs): | ||
130 | + yield mailinglist_name, msg, index | ||
131 | + | ||
132 | + def get_thread(self, email, mailinglist): | ||
133 | + """Group messages by thread looking for similar subjects""" | ||
134 | + | ||
135 | + subject_slug = slugify(email.subject_clean) | ||
136 | + thread = self.THREAD_CACHE.get(subject_slug, {}).get(mailinglist.id) | ||
137 | + if thread is None: | ||
138 | + thread = Thread.objects.get_or_create( | ||
139 | + mailinglist=mailinglist, | ||
140 | + subject_token=subject_slug | ||
141 | + )[0] | ||
142 | + | ||
143 | + if self.THREAD_CACHE.get(subject_slug) is None: | ||
144 | + self.THREAD_CACHE[subject_slug] = dict() | ||
145 | + self.THREAD_CACHE[subject_slug][mailinglist.id] = thread | ||
146 | + | ||
147 | + thread.latest_message = email | ||
148 | + thread.save() | ||
149 | + return thread | ||
150 | + | ||
151 | + def save_email(self, list_name, email_msg, index): | ||
152 | + """Save email message into the database.""" | ||
153 | + | ||
154 | + # Update last imported message into the DB | ||
155 | + mailinglist, created = MailingList.objects.get_or_create(name=list_name) | ||
156 | + mailinglist.last_imported_index = index | ||
157 | + | ||
158 | + if created: | ||
159 | + # if the mailinglist is newly created it's sure that the message | ||
160 | + # is not in the DB yet. | ||
161 | + self.create_email(mailinglist, email_msg) | ||
162 | + | ||
163 | + else: | ||
164 | + # If the message is already at the database don't do anything | ||
165 | + try: | ||
166 | + messages = Message.objects.get( | ||
167 | + message_id=email_msg.get('Message-ID'), | ||
168 | + thread__mailinglist=mailinglist | ||
169 | + ) | ||
170 | + | ||
171 | + except Message.DoesNotExist: | ||
172 | + self.create_email(mailinglist, email_msg) | ||
173 | + | ||
174 | + mailinglist.save() | ||
175 | + | ||
176 | + def create_email(self, mailinglist, email_msg): | ||
177 | + | ||
178 | + real_name, from_ = email_msg.get_from_addr() | ||
179 | + | ||
180 | + email_addr = self.EMAIL_ADDR_CACHE.get(from_) | ||
181 | + if email_addr is None: | ||
182 | + email_addr = EmailAddress.objects.get_or_create( | ||
183 | + address=from_)[0] | ||
184 | + self.EMAIL_ADDR_CACHE[from_] = email_addr | ||
185 | + | ||
186 | + if not email_addr.real_name and real_name: | ||
187 | + email_addr.real_name = real_name[:64] | ||
188 | + email_addr.save() | ||
189 | + | ||
190 | + subject = email_msg.get_subject() | ||
191 | + | ||
192 | + email = Message.objects.create( | ||
193 | + message_id=email_msg.get('Message-ID'), | ||
194 | + from_address=email_addr, | ||
195 | + subject=subject, | ||
196 | + subject_clean=self.RE_SUBJECT_CLEAN.sub('', subject).strip(), | ||
197 | + body=email_msg.get_body(), | ||
198 | + received_time=email_msg.get_received_datetime(), | ||
199 | + ) | ||
200 | + email.thread = self.get_thread(email, mailinglist) | ||
201 | + email.save() | ||
202 | + | ||
203 | + @transaction.commit_manually | ||
204 | + def import_emails(self, archives_path, all, exclude_lists=None): | ||
205 | + """Get emails from the filesystem from the `archives_path` | ||
206 | + and store them into the database. If `all` is set to True all | ||
207 | + the filesystem storage will be imported otherwise the | ||
208 | + importation will resume from the last message previously | ||
209 | + imported. The lists set in `exclude_lists` won't be imported. | ||
210 | + | ||
211 | + """ | ||
212 | + | ||
213 | + count = 0 | ||
214 | + email_generator = self.get_emails(archives_path, all, exclude_lists) | ||
215 | + for mailinglist_name, msg, index in email_generator: | ||
216 | + try: | ||
217 | + self.save_email(mailinglist_name, msg, index) | ||
218 | + except: | ||
219 | + # This anti-pattern is needed to avoid the transations to | ||
220 | + # get stuck in case of errors. | ||
221 | + transaction.rollback() | ||
222 | + raise | ||
223 | + | ||
224 | + count += 1 | ||
225 | + if count % 1000 == 0: | ||
226 | + transaction.commit() | ||
227 | + | ||
228 | + transaction.commit() | ||
229 | + | ||
230 | + def handle(self, *args, **options): | ||
231 | + """Main command method.""" | ||
232 | + | ||
233 | + lock_file = '/var/lock/colab/import_emails.lock' | ||
234 | + | ||
235 | + # Already running, so quit | ||
236 | + if os.path.exists(lock_file): | ||
237 | + self.log(("This script is already running. (If your are sure it's " | ||
238 | + "not please delete the lock file in %s')") % lock_file) | ||
239 | + sys.exit(0) | ||
240 | + | ||
241 | + if not os.path.exists(os.path.dirname(lock_file)): | ||
242 | + os.mkdir(os.path.dirname(lock_file), 0755) | ||
243 | + | ||
244 | + run_lock = file(lock_file, 'w') | ||
245 | + run_lock.close() | ||
246 | + | ||
247 | + archives_path = options.get('archives_path') | ||
248 | + self.log('Using archives_path `%s`' % self.default_archives_path) | ||
249 | + | ||
250 | + if not os.path.exists(archives_path): | ||
251 | + raise CommandError('archives_path (%s) does not exist' % | ||
252 | + archives_path) | ||
253 | + | ||
254 | + self.import_emails(archives_path, | ||
255 | + options.get('all'), options.get('exclude_lists')) | ||
256 | + | ||
257 | + os.remove(lock_file) | ||
258 | + |
@@ -0,0 +1,101 @@ | @@ -0,0 +1,101 @@ | ||
1 | + | ||
2 | +import re | ||
3 | +import pytz | ||
4 | +import email | ||
5 | +import codecs | ||
6 | +import mailbox | ||
7 | +import datetime | ||
8 | +from email.iterators import typed_subpart_iterator | ||
9 | + | ||
10 | +import chardet | ||
11 | + | ||
12 | + | ||
13 | +def get_charset(message, default='ASCII'): | ||
14 | + """Get the message charset""" | ||
15 | + | ||
16 | + charset = message.get_content_charset() | ||
17 | + | ||
18 | + if not charset: | ||
19 | + charset = message.get_charset() | ||
20 | + | ||
21 | + if not charset: | ||
22 | + charset = default | ||
23 | + | ||
24 | + try: | ||
25 | + codecs.lookup(charset) | ||
26 | + except LookupError: | ||
27 | + charset = default | ||
28 | + | ||
29 | + return charset | ||
30 | + | ||
31 | + | ||
32 | +class Message(mailbox.mboxMessage): | ||
33 | + | ||
34 | + RECEIVED_DELIMITER = re.compile('\n|;') | ||
35 | + | ||
36 | + def get_subject(self): | ||
37 | + subject = email.header.decode_header(self['Subject']) | ||
38 | + | ||
39 | + if isinstance(subject, list): | ||
40 | + new_subject = u'' | ||
41 | + for text_part, encoding in subject: | ||
42 | + if not encoding: | ||
43 | + encoding = get_charset(self) | ||
44 | + | ||
45 | + try: | ||
46 | + new_subject += unicode(text_part, encoding) | ||
47 | + except (UnicodeDecodeError, LookupError): | ||
48 | + try: | ||
49 | + new_subject += unicode(text_part, get_charset(self)) | ||
50 | + except (UnicodeDecodeError, LookupError): | ||
51 | + encoding = chardet.detect(text_part)['encoding'] | ||
52 | + new_subject += unicode(text_part, encoding) | ||
53 | + | ||
54 | + return ''.join(new_subject) | ||
55 | + | ||
56 | + def get_body(self): | ||
57 | + """Get the body of the email message""" | ||
58 | + | ||
59 | + if self.is_multipart(): | ||
60 | + #get the plain text version only | ||
61 | + text_parts = [part | ||
62 | + for part in typed_subpart_iterator(self, | ||
63 | + 'text', | ||
64 | + 'plain')] | ||
65 | + body = [] | ||
66 | + for part in text_parts: | ||
67 | + charset = get_charset(part, get_charset(self)) | ||
68 | + body.append(unicode(part.get_payload(decode=True), | ||
69 | + charset, | ||
70 | + "replace")) | ||
71 | + | ||
72 | + return u"\n".join(body).strip() | ||
73 | + | ||
74 | + else: # if it is not multipart, the payload will be a string | ||
75 | + # representing the message body | ||
76 | + body = unicode(self.get_payload(decode=True), | ||
77 | + get_charset(self), | ||
78 | + "replace") | ||
79 | + return body.strip() | ||
80 | + | ||
81 | + def get_received_datetime(self): | ||
82 | + # The time received should always be the last element | ||
83 | + # in the `Received` attribute from the message headers | ||
84 | + received_header = self.RECEIVED_DELIMITER.split(self['Received']) | ||
85 | + received_time_header = received_header[-1].strip() | ||
86 | + | ||
87 | + date_tuple = email.utils.parsedate_tz(received_time_header) | ||
88 | + utc_timestamp = email.utils.mktime_tz(date_tuple) | ||
89 | + utc_datetime = datetime.datetime.fromtimestamp(utc_timestamp, | ||
90 | + pytz.utc) | ||
91 | + | ||
92 | + return utc_datetime | ||
93 | + | ||
94 | + def get_from_addr(self): | ||
95 | + real_name_raw, from_ = email.utils.parseaddr(self['From']) | ||
96 | + real_name_str, encoding = email.header.decode_header(real_name_raw)[0] | ||
97 | + if not encoding: | ||
98 | + encoding = 'ascii' | ||
99 | + | ||
100 | + real_name = unicode(real_name_str, encoding, errors='replace') | ||
101 | + return real_name, from_ |
@@ -0,0 +1,255 @@ | @@ -0,0 +1,255 @@ | ||
1 | +# encoding: utf-8 | ||
2 | +import datetime | ||
3 | +from south.db import db | ||
4 | +from south.v2 import SchemaMigration | ||
5 | +from django.db import models | ||
6 | + | ||
7 | +class Migration(SchemaMigration): | ||
8 | + | ||
9 | + def forwards(self, orm): | ||
10 | + | ||
11 | + # Adding model 'PageHit' | ||
12 | + db.create_table('super_archives_pagehit', ( | ||
13 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
14 | + ('url_path', self.gf('django.db.models.fields.CharField')(unique=True, max_length=2048, db_index=True)), | ||
15 | + ('hit_count', self.gf('django.db.models.fields.IntegerField')(default=0)), | ||
16 | + )) | ||
17 | + db.send_create_signal('super_archives', ['PageHit']) | ||
18 | + | ||
19 | + # Adding model 'EmailAddress' | ||
20 | + db.create_table('super_archives_emailaddress', ( | ||
21 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
22 | + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='emails', null=True, to=orm['auth.User'])), | ||
23 | + ('address', self.gf('django.db.models.fields.EmailField')(unique=True, max_length=75)), | ||
24 | + ('real_name', self.gf('django.db.models.fields.CharField')(max_length=64, blank=True)), | ||
25 | + ('md5', self.gf('django.db.models.fields.CharField')(max_length=32, null=True)), | ||
26 | + )) | ||
27 | + db.send_create_signal('super_archives', ['EmailAddress']) | ||
28 | + | ||
29 | + # Adding model 'UserProfile' | ||
30 | + db.create_table('super_archives_userprofile', ( | ||
31 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
32 | + ('user', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['auth.User'], unique=True)), | ||
33 | + ('institution', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), | ||
34 | + ('role', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), | ||
35 | + ('twitter', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), | ||
36 | + ('facebook', self.gf('django.db.models.fields.CharField')(max_length=128, null=True)), | ||
37 | + ('google_talk', self.gf('django.db.models.fields.EmailField')(max_length=75, null=True)), | ||
38 | + ('webpage', self.gf('django.db.models.fields.CharField')(max_length=256)), | ||
39 | + )) | ||
40 | + db.send_create_signal('super_archives', ['UserProfile']) | ||
41 | + | ||
42 | + # Adding model 'MailingList' | ||
43 | + db.create_table('super_archives_mailinglist', ( | ||
44 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
45 | + ('name', self.gf('django.db.models.fields.CharField')(max_length=80)), | ||
46 | + ('email', self.gf('django.db.models.fields.EmailField')(max_length=75)), | ||
47 | + ('description', self.gf('django.db.models.fields.TextField')()), | ||
48 | + ('logo', self.gf('django.db.models.fields.files.FileField')(max_length=100)), | ||
49 | + ('last_imported_index', self.gf('django.db.models.fields.IntegerField')(default=0)), | ||
50 | + )) | ||
51 | + db.send_create_signal('super_archives', ['MailingList']) | ||
52 | + | ||
53 | + # Adding model 'MailingListMembership' | ||
54 | + db.create_table('super_archives_mailinglistmembership', ( | ||
55 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
56 | + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), | ||
57 | + ('mailinglist', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.MailingList'])), | ||
58 | + )) | ||
59 | + db.send_create_signal('super_archives', ['MailingListMembership']) | ||
60 | + | ||
61 | + # Adding model 'Thread' | ||
62 | + db.create_table('super_archives_thread', ( | ||
63 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
64 | + ('subject_token', self.gf('django.db.models.fields.CharField')(max_length=512)), | ||
65 | + ('mailinglist', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.MailingList'])), | ||
66 | + ('latest_message', self.gf('django.db.models.fields.related.OneToOneField')(related_name='+', unique=True, null=True, to=orm['super_archives.Message'])), | ||
67 | + )) | ||
68 | + db.send_create_signal('super_archives', ['Thread']) | ||
69 | + | ||
70 | + # Adding unique constraint on 'Thread', fields ['subject_token', 'mailinglist'] | ||
71 | + db.create_unique('super_archives_thread', ['subject_token', 'mailinglist_id']) | ||
72 | + | ||
73 | + # Adding model 'Vote' | ||
74 | + db.create_table('super_archives_vote', ( | ||
75 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
76 | + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])), | ||
77 | + ('message', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.Message'])), | ||
78 | + )) | ||
79 | + db.send_create_signal('super_archives', ['Vote']) | ||
80 | + | ||
81 | + # Adding unique constraint on 'Vote', fields ['user', 'message'] | ||
82 | + db.create_unique('super_archives_vote', ['user_id', 'message_id']) | ||
83 | + | ||
84 | + # Adding model 'Message' | ||
85 | + db.create_table('super_archives_message', ( | ||
86 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
87 | + ('from_address', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.EmailAddress'])), | ||
88 | + ('mailinglist', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.MailingList'])), | ||
89 | + ('thread', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.Thread'], null=True)), | ||
90 | + ('subject', self.gf('django.db.models.fields.CharField')(max_length=512)), | ||
91 | + ('subject_clean', self.gf('django.db.models.fields.CharField')(max_length=512)), | ||
92 | + ('body', self.gf('django.db.models.fields.TextField')(default='')), | ||
93 | + ('received_time', self.gf('django.db.models.fields.DateTimeField')()), | ||
94 | + ('message_id', self.gf('django.db.models.fields.CharField')(max_length=512)), | ||
95 | + )) | ||
96 | + db.send_create_signal('super_archives', ['Message']) | ||
97 | + | ||
98 | + # Adding model 'MessageMetadata' | ||
99 | + db.create_table('super_archives_messagemetadata', ( | ||
100 | + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), | ||
101 | + ('Message', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['super_archives.Message'])), | ||
102 | + ('name', self.gf('django.db.models.fields.CharField')(max_length=512)), | ||
103 | + ('value', self.gf('django.db.models.fields.TextField')()), | ||
104 | + )) | ||
105 | + db.send_create_signal('super_archives', ['MessageMetadata']) | ||
106 | + | ||
107 | + | ||
108 | + def backwards(self, orm): | ||
109 | + | ||
110 | + # Removing unique constraint on 'Vote', fields ['user', 'message'] | ||
111 | + db.delete_unique('super_archives_vote', ['user_id', 'message_id']) | ||
112 | + | ||
113 | + # Removing unique constraint on 'Thread', fields ['subject_token', 'mailinglist'] | ||
114 | + db.delete_unique('super_archives_thread', ['subject_token', 'mailinglist_id']) | ||
115 | + | ||
116 | + # Deleting model 'PageHit' | ||
117 | + db.delete_table('super_archives_pagehit') | ||
118 | + | ||
119 | + # Deleting model 'EmailAddress' | ||
120 | + db.delete_table('super_archives_emailaddress') | ||
121 | + | ||
122 | + # Deleting model 'UserProfile' | ||
123 | + db.delete_table('super_archives_userprofile') | ||
124 | + | ||
125 | + # Deleting model 'MailingList' | ||
126 | + db.delete_table('super_archives_mailinglist') | ||
127 | + | ||
128 | + # Deleting model 'MailingListMembership' | ||
129 | + db.delete_table('super_archives_mailinglistmembership') | ||
130 | + | ||
131 | + # Deleting model 'Thread' | ||
132 | + db.delete_table('super_archives_thread') | ||
133 | + | ||
134 | + # Deleting model 'Vote' | ||
135 | + db.delete_table('super_archives_vote') | ||
136 | + | ||
137 | + # Deleting model 'Message' | ||
138 | + db.delete_table('super_archives_message') | ||
139 | + | ||
140 | + # Deleting model 'MessageMetadata' | ||
141 | + db.delete_table('super_archives_messagemetadata') | ||
142 | + | ||
143 | + | ||
144 | + models = { | ||
145 | + 'auth.group': { | ||
146 | + 'Meta': {'object_name': 'Group'}, | ||
147 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
148 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
149 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
150 | + }, | ||
151 | + 'auth.permission': { | ||
152 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
153 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
154 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
155 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
156 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
157 | + }, | ||
158 | + 'auth.user': { | ||
159 | + 'Meta': {'object_name': 'User'}, | ||
160 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
161 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
162 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
163 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
164 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
165 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
166 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
167 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
168 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
169 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
170 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
171 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
172 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
173 | + }, | ||
174 | + 'contenttypes.contenttype': { | ||
175 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
176 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
177 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
178 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
179 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
180 | + }, | ||
181 | + 'super_archives.emailaddress': { | ||
182 | + 'Meta': {'object_name': 'EmailAddress'}, | ||
183 | + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
184 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
185 | + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
186 | + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
187 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
188 | + }, | ||
189 | + 'super_archives.mailinglist': { | ||
190 | + 'Meta': {'object_name': 'MailingList'}, | ||
191 | + 'description': ('django.db.models.fields.TextField', [], {}), | ||
192 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
193 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
194 | + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
195 | + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
196 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
197 | + }, | ||
198 | + 'super_archives.mailinglistmembership': { | ||
199 | + 'Meta': {'object_name': 'MailingListMembership'}, | ||
200 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
201 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
202 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
203 | + }, | ||
204 | + 'super_archives.message': { | ||
205 | + 'Meta': {'object_name': 'Message'}, | ||
206 | + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
207 | + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
208 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
209 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
210 | + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
211 | + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
212 | + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
213 | + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
214 | + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
215 | + }, | ||
216 | + 'super_archives.messagemetadata': { | ||
217 | + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
218 | + 'Meta': {'object_name': 'MessageMetadata'}, | ||
219 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
220 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
221 | + 'value': ('django.db.models.fields.TextField', [], {}) | ||
222 | + }, | ||
223 | + 'super_archives.pagehit': { | ||
224 | + 'Meta': {'object_name': 'PageHit'}, | ||
225 | + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
226 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
227 | + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
228 | + }, | ||
229 | + 'super_archives.thread': { | ||
230 | + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
231 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
232 | + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
233 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
234 | + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
235 | + }, | ||
236 | + 'super_archives.userprofile': { | ||
237 | + 'Meta': {'object_name': 'UserProfile'}, | ||
238 | + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
239 | + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
240 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
241 | + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
242 | + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
243 | + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
244 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
245 | + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
246 | + }, | ||
247 | + 'super_archives.vote': { | ||
248 | + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
249 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
250 | + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
251 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
252 | + } | ||
253 | + } | ||
254 | + | ||
255 | + complete_apps = ['super_archives'] |
src/super_archives/migrations/0002_auto__add_field_userprofile_verification_hash.py
0 → 100644
@@ -0,0 +1,133 @@ | @@ -0,0 +1,133 @@ | ||
1 | +# encoding: utf-8 | ||
2 | +import datetime | ||
3 | +from south.db import db | ||
4 | +from south.v2 import SchemaMigration | ||
5 | +from django.db import models | ||
6 | + | ||
7 | +class Migration(SchemaMigration): | ||
8 | + | ||
9 | + def forwards(self, orm): | ||
10 | + | ||
11 | + # Adding field 'UserProfile.verification_hash' | ||
12 | + db.add_column('super_archives_userprofile', 'verification_hash', self.gf('django.db.models.fields.CharField')(max_length=32, null=True), keep_default=False) | ||
13 | + | ||
14 | + | ||
15 | + def backwards(self, orm): | ||
16 | + | ||
17 | + # Deleting field 'UserProfile.verification_hash' | ||
18 | + db.delete_column('super_archives_userprofile', 'verification_hash') | ||
19 | + | ||
20 | + | ||
21 | + models = { | ||
22 | + 'auth.group': { | ||
23 | + 'Meta': {'object_name': 'Group'}, | ||
24 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | + }, | ||
28 | + 'auth.permission': { | ||
29 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | + }, | ||
35 | + 'auth.user': { | ||
36 | + 'Meta': {'object_name': 'User'}, | ||
37 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | + }, | ||
51 | + 'contenttypes.contenttype': { | ||
52 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | + }, | ||
58 | + 'super_archives.emailaddress': { | ||
59 | + 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
64 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | + }, | ||
66 | + 'super_archives.mailinglist': { | ||
67 | + 'Meta': {'object_name': 'MailingList'}, | ||
68 | + 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | + }, | ||
75 | + 'super_archives.mailinglistmembership': { | ||
76 | + 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | + }, | ||
81 | + 'super_archives.message': { | ||
82 | + 'Meta': {'object_name': 'Message'}, | ||
83 | + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
87 | + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
88 | + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
89 | + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
90 | + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
91 | + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
92 | + }, | ||
93 | + 'super_archives.messagemetadata': { | ||
94 | + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
95 | + 'Meta': {'object_name': 'MessageMetadata'}, | ||
96 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
97 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | + 'value': ('django.db.models.fields.TextField', [], {}) | ||
99 | + }, | ||
100 | + 'super_archives.pagehit': { | ||
101 | + 'Meta': {'object_name': 'PageHit'}, | ||
102 | + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
103 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
105 | + }, | ||
106 | + 'super_archives.thread': { | ||
107 | + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
108 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
109 | + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
110 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
111 | + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
112 | + }, | ||
113 | + 'super_archives.userprofile': { | ||
114 | + 'Meta': {'object_name': 'UserProfile'}, | ||
115 | + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
116 | + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
117 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
118 | + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
119 | + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
120 | + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
121 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
122 | + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
123 | + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
124 | + }, | ||
125 | + 'super_archives.vote': { | ||
126 | + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
127 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
128 | + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
129 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
130 | + } | ||
131 | + } | ||
132 | + | ||
133 | + complete_apps = ['super_archives'] |
src/super_archives/migrations/0003_auto__add_field_thread_score.py
0 → 100644
@@ -0,0 +1,134 @@ | @@ -0,0 +1,134 @@ | ||
1 | +# encoding: utf-8 | ||
2 | +import datetime | ||
3 | +from south.db import db | ||
4 | +from south.v2 import SchemaMigration | ||
5 | +from django.db import models | ||
6 | + | ||
7 | +class Migration(SchemaMigration): | ||
8 | + | ||
9 | + def forwards(self, orm): | ||
10 | + | ||
11 | + # Adding field 'Thread.score' | ||
12 | + db.add_column('super_archives_thread', 'score', self.gf('django.db.models.fields.IntegerField')(default=0), keep_default=False) | ||
13 | + | ||
14 | + | ||
15 | + def backwards(self, orm): | ||
16 | + | ||
17 | + # Deleting field 'Thread.score' | ||
18 | + db.delete_column('super_archives_thread', 'score') | ||
19 | + | ||
20 | + | ||
21 | + models = { | ||
22 | + 'auth.group': { | ||
23 | + 'Meta': {'object_name': 'Group'}, | ||
24 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | + }, | ||
28 | + 'auth.permission': { | ||
29 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | + }, | ||
35 | + 'auth.user': { | ||
36 | + 'Meta': {'object_name': 'User'}, | ||
37 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | + }, | ||
51 | + 'contenttypes.contenttype': { | ||
52 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | + }, | ||
58 | + 'super_archives.emailaddress': { | ||
59 | + 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
64 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | + }, | ||
66 | + 'super_archives.mailinglist': { | ||
67 | + 'Meta': {'object_name': 'MailingList'}, | ||
68 | + 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | + }, | ||
75 | + 'super_archives.mailinglistmembership': { | ||
76 | + 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | + }, | ||
81 | + 'super_archives.message': { | ||
82 | + 'Meta': {'object_name': 'Message'}, | ||
83 | + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
87 | + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
88 | + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
89 | + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
90 | + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
91 | + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
92 | + }, | ||
93 | + 'super_archives.messagemetadata': { | ||
94 | + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
95 | + 'Meta': {'object_name': 'MessageMetadata'}, | ||
96 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
97 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | + 'value': ('django.db.models.fields.TextField', [], {}) | ||
99 | + }, | ||
100 | + 'super_archives.pagehit': { | ||
101 | + 'Meta': {'object_name': 'PageHit'}, | ||
102 | + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
103 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
105 | + }, | ||
106 | + 'super_archives.thread': { | ||
107 | + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
108 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
109 | + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
110 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
111 | + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
112 | + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
113 | + }, | ||
114 | + 'super_archives.userprofile': { | ||
115 | + 'Meta': {'object_name': 'UserProfile'}, | ||
116 | + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
117 | + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
118 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
119 | + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
120 | + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
121 | + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
122 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
123 | + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
124 | + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
125 | + }, | ||
126 | + 'super_archives.vote': { | ||
127 | + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
128 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
129 | + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
130 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
131 | + } | ||
132 | + } | ||
133 | + | ||
134 | + complete_apps = ['super_archives'] |
src/super_archives/migrations/0004_auto__add_field_vote_created.py
0 → 100644
@@ -0,0 +1,135 @@ | @@ -0,0 +1,135 @@ | ||
1 | +# encoding: utf-8 | ||
2 | +import datetime | ||
3 | +from south.db import db | ||
4 | +from south.v2 import SchemaMigration | ||
5 | +from django.db import models | ||
6 | + | ||
7 | +class Migration(SchemaMigration): | ||
8 | + | ||
9 | + def forwards(self, orm): | ||
10 | + | ||
11 | + # Adding field 'Vote.created' | ||
12 | + db.add_column('super_archives_vote', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2012, 1, 19, 18, 8, 46, 813949), blank=True), keep_default=False) | ||
13 | + | ||
14 | + | ||
15 | + def backwards(self, orm): | ||
16 | + | ||
17 | + # Deleting field 'Vote.created' | ||
18 | + db.delete_column('super_archives_vote', 'created') | ||
19 | + | ||
20 | + | ||
21 | + models = { | ||
22 | + 'auth.group': { | ||
23 | + 'Meta': {'object_name': 'Group'}, | ||
24 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | + }, | ||
28 | + 'auth.permission': { | ||
29 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | + }, | ||
35 | + 'auth.user': { | ||
36 | + 'Meta': {'object_name': 'User'}, | ||
37 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | + }, | ||
51 | + 'contenttypes.contenttype': { | ||
52 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | + }, | ||
58 | + 'super_archives.emailaddress': { | ||
59 | + 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
64 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | + }, | ||
66 | + 'super_archives.mailinglist': { | ||
67 | + 'Meta': {'object_name': 'MailingList'}, | ||
68 | + 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | + }, | ||
75 | + 'super_archives.mailinglistmembership': { | ||
76 | + 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | + }, | ||
81 | + 'super_archives.message': { | ||
82 | + 'Meta': {'object_name': 'Message'}, | ||
83 | + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
87 | + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
88 | + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
89 | + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
90 | + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
91 | + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
92 | + }, | ||
93 | + 'super_archives.messagemetadata': { | ||
94 | + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
95 | + 'Meta': {'object_name': 'MessageMetadata'}, | ||
96 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
97 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | + 'value': ('django.db.models.fields.TextField', [], {}) | ||
99 | + }, | ||
100 | + 'super_archives.pagehit': { | ||
101 | + 'Meta': {'object_name': 'PageHit'}, | ||
102 | + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
103 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
105 | + }, | ||
106 | + 'super_archives.thread': { | ||
107 | + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
108 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
109 | + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
110 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
111 | + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
112 | + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
113 | + }, | ||
114 | + 'super_archives.userprofile': { | ||
115 | + 'Meta': {'object_name': 'UserProfile'}, | ||
116 | + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
117 | + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
118 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
119 | + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
120 | + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
121 | + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
122 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
123 | + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
124 | + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
125 | + }, | ||
126 | + 'super_archives.vote': { | ||
127 | + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
128 | + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
129 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
130 | + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
131 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
132 | + } | ||
133 | + } | ||
134 | + | ||
135 | + complete_apps = ['super_archives'] |
src/super_archives/migrations/0005_auto__add_field_message_spam__add_field_thread_spam.py
0 → 100644
@@ -0,0 +1,143 @@ | @@ -0,0 +1,143 @@ | ||
1 | +# encoding: utf-8 | ||
2 | +import datetime | ||
3 | +from south.db import db | ||
4 | +from south.v2 import SchemaMigration | ||
5 | +from django.db import models | ||
6 | + | ||
7 | +class Migration(SchemaMigration): | ||
8 | + | ||
9 | + def forwards(self, orm): | ||
10 | + | ||
11 | + # Adding field 'Message.spam' | ||
12 | + db.add_column('super_archives_message', 'spam', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) | ||
13 | + | ||
14 | + # Adding field 'Thread.spam' | ||
15 | + db.add_column('super_archives_thread', 'spam', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) | ||
16 | + | ||
17 | + | ||
18 | + def backwards(self, orm): | ||
19 | + | ||
20 | + # Deleting field 'Message.spam' | ||
21 | + db.delete_column('super_archives_message', 'spam') | ||
22 | + | ||
23 | + # Deleting field 'Thread.spam' | ||
24 | + db.delete_column('super_archives_thread', 'spam') | ||
25 | + | ||
26 | + | ||
27 | + models = { | ||
28 | + 'auth.group': { | ||
29 | + 'Meta': {'object_name': 'Group'}, | ||
30 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
31 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
32 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
33 | + }, | ||
34 | + 'auth.permission': { | ||
35 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
36 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
37 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
38 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
39 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
40 | + }, | ||
41 | + 'auth.user': { | ||
42 | + 'Meta': {'object_name': 'User'}, | ||
43 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
44 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
45 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
46 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
47 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
48 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
49 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
50 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
51 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
52 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
53 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
54 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
55 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
56 | + }, | ||
57 | + 'contenttypes.contenttype': { | ||
58 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
59 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
60 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
61 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
62 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
63 | + }, | ||
64 | + 'super_archives.emailaddress': { | ||
65 | + 'Meta': {'object_name': 'EmailAddress'}, | ||
66 | + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
67 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
68 | + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
69 | + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
70 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
71 | + }, | ||
72 | + 'super_archives.mailinglist': { | ||
73 | + 'Meta': {'object_name': 'MailingList'}, | ||
74 | + 'description': ('django.db.models.fields.TextField', [], {}), | ||
75 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
76 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
77 | + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
78 | + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
79 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
80 | + }, | ||
81 | + 'super_archives.mailinglistmembership': { | ||
82 | + 'Meta': {'object_name': 'MailingListMembership'}, | ||
83 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
84 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
85 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
86 | + }, | ||
87 | + 'super_archives.message': { | ||
88 | + 'Meta': {'object_name': 'Message'}, | ||
89 | + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
90 | + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
91 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
92 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
93 | + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
94 | + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
95 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
96 | + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
97 | + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
99 | + }, | ||
100 | + 'super_archives.messagemetadata': { | ||
101 | + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
102 | + 'Meta': {'object_name': 'MessageMetadata'}, | ||
103 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
105 | + 'value': ('django.db.models.fields.TextField', [], {}) | ||
106 | + }, | ||
107 | + 'super_archives.pagehit': { | ||
108 | + 'Meta': {'object_name': 'PageHit'}, | ||
109 | + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
110 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
111 | + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
112 | + }, | ||
113 | + 'super_archives.thread': { | ||
114 | + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
115 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
116 | + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
117 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
118 | + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
119 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
120 | + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
121 | + }, | ||
122 | + 'super_archives.userprofile': { | ||
123 | + 'Meta': {'object_name': 'UserProfile'}, | ||
124 | + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
125 | + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
126 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
127 | + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
128 | + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
129 | + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
130 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
131 | + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
132 | + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
133 | + }, | ||
134 | + 'super_archives.vote': { | ||
135 | + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
136 | + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
137 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
138 | + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
139 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
140 | + } | ||
141 | + } | ||
142 | + | ||
143 | + complete_apps = ['super_archives'] |
@@ -0,0 +1,143 @@ | @@ -0,0 +1,143 @@ | ||
1 | +# encoding: utf-8 | ||
2 | +import datetime | ||
3 | +from south.db import db | ||
4 | +from south.v2 import SchemaMigration | ||
5 | +from django.db import models | ||
6 | + | ||
7 | +class Migration(SchemaMigration): | ||
8 | + | ||
9 | + def forwards(self, orm): | ||
10 | + | ||
11 | + # Adding index on 'Message', fields ['subject_clean'] | ||
12 | + db.create_index('super_archives_message', ['subject_clean']) | ||
13 | + | ||
14 | + # Adding index on 'Message', fields ['subject'] | ||
15 | + db.create_index('super_archives_message', ['subject']) | ||
16 | + | ||
17 | + | ||
18 | + def backwards(self, orm): | ||
19 | + | ||
20 | + # Removing index on 'Message', fields ['subject'] | ||
21 | + db.delete_index('super_archives_message', ['subject']) | ||
22 | + | ||
23 | + # Removing index on 'Message', fields ['subject_clean'] | ||
24 | + db.delete_index('super_archives_message', ['subject_clean']) | ||
25 | + | ||
26 | + | ||
27 | + models = { | ||
28 | + 'auth.group': { | ||
29 | + 'Meta': {'object_name': 'Group'}, | ||
30 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
31 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
32 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
33 | + }, | ||
34 | + 'auth.permission': { | ||
35 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
36 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
37 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
38 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
39 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
40 | + }, | ||
41 | + 'auth.user': { | ||
42 | + 'Meta': {'object_name': 'User'}, | ||
43 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
44 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
45 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
46 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
47 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
48 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
49 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
50 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
51 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
52 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
53 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
54 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
55 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
56 | + }, | ||
57 | + 'contenttypes.contenttype': { | ||
58 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
59 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
60 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
61 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
62 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
63 | + }, | ||
64 | + 'super_archives.emailaddress': { | ||
65 | + 'Meta': {'object_name': 'EmailAddress'}, | ||
66 | + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
67 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
68 | + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
69 | + 'real_name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), | ||
70 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
71 | + }, | ||
72 | + 'super_archives.mailinglist': { | ||
73 | + 'Meta': {'object_name': 'MailingList'}, | ||
74 | + 'description': ('django.db.models.fields.TextField', [], {}), | ||
75 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
76 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
77 | + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
78 | + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
79 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
80 | + }, | ||
81 | + 'super_archives.mailinglistmembership': { | ||
82 | + 'Meta': {'object_name': 'MailingListMembership'}, | ||
83 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
84 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
85 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
86 | + }, | ||
87 | + 'super_archives.message': { | ||
88 | + 'Meta': {'object_name': 'Message'}, | ||
89 | + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
90 | + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
91 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
92 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
93 | + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
94 | + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
95 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
96 | + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
97 | + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
98 | + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
99 | + }, | ||
100 | + 'super_archives.messagemetadata': { | ||
101 | + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
102 | + 'Meta': {'object_name': 'MessageMetadata'}, | ||
103 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
105 | + 'value': ('django.db.models.fields.TextField', [], {}) | ||
106 | + }, | ||
107 | + 'super_archives.pagehit': { | ||
108 | + 'Meta': {'object_name': 'PageHit'}, | ||
109 | + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
110 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
111 | + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
112 | + }, | ||
113 | + 'super_archives.thread': { | ||
114 | + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
115 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
116 | + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
117 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
118 | + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
119 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
120 | + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
121 | + }, | ||
122 | + 'super_archives.userprofile': { | ||
123 | + 'Meta': {'object_name': 'UserProfile'}, | ||
124 | + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
125 | + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
126 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
127 | + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
128 | + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
129 | + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
130 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
131 | + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
132 | + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
133 | + }, | ||
134 | + 'super_archives.vote': { | ||
135 | + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
136 | + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
137 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
138 | + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
139 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
140 | + } | ||
141 | + } | ||
142 | + | ||
143 | + complete_apps = ['super_archives'] |
@@ -0,0 +1,137 @@ | @@ -0,0 +1,137 @@ | ||
1 | +# encoding: utf-8 | ||
2 | +import datetime | ||
3 | +from south.db import db | ||
4 | +from south.v2 import SchemaMigration | ||
5 | +from django.db import models | ||
6 | + | ||
7 | +class Migration(SchemaMigration): | ||
8 | + | ||
9 | + def forwards(self, orm): | ||
10 | + | ||
11 | + # Adding index on 'EmailAddress', fields ['real_name'] | ||
12 | + db.create_index('super_archives_emailaddress', ['real_name']) | ||
13 | + | ||
14 | + | ||
15 | + def backwards(self, orm): | ||
16 | + | ||
17 | + # Removing index on 'EmailAddress', fields ['real_name'] | ||
18 | + db.delete_index('super_archives_emailaddress', ['real_name']) | ||
19 | + | ||
20 | + | ||
21 | + models = { | ||
22 | + 'auth.group': { | ||
23 | + 'Meta': {'object_name': 'Group'}, | ||
24 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | + }, | ||
28 | + 'auth.permission': { | ||
29 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | + }, | ||
35 | + 'auth.user': { | ||
36 | + 'Meta': {'object_name': 'User'}, | ||
37 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | + }, | ||
51 | + 'contenttypes.contenttype': { | ||
52 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | + }, | ||
58 | + 'super_archives.emailaddress': { | ||
59 | + 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | + 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), | ||
64 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | + }, | ||
66 | + 'super_archives.mailinglist': { | ||
67 | + 'Meta': {'object_name': 'MailingList'}, | ||
68 | + 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | + }, | ||
75 | + 'super_archives.mailinglistmembership': { | ||
76 | + 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | + }, | ||
81 | + 'super_archives.message': { | ||
82 | + 'Meta': {'object_name': 'Message'}, | ||
83 | + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
87 | + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
88 | + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
89 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
90 | + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
91 | + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
92 | + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
93 | + }, | ||
94 | + 'super_archives.messagemetadata': { | ||
95 | + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
96 | + 'Meta': {'object_name': 'MessageMetadata'}, | ||
97 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
98 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
99 | + 'value': ('django.db.models.fields.TextField', [], {}) | ||
100 | + }, | ||
101 | + 'super_archives.pagehit': { | ||
102 | + 'Meta': {'object_name': 'PageHit'}, | ||
103 | + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
104 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
105 | + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
106 | + }, | ||
107 | + 'super_archives.thread': { | ||
108 | + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
109 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
110 | + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
111 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
112 | + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
113 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
114 | + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
115 | + }, | ||
116 | + 'super_archives.userprofile': { | ||
117 | + 'Meta': {'object_name': 'UserProfile'}, | ||
118 | + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
119 | + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
120 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
121 | + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
122 | + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
123 | + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
124 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
125 | + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
126 | + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
127 | + }, | ||
128 | + 'super_archives.vote': { | ||
129 | + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
130 | + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
131 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
132 | + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
133 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
134 | + } | ||
135 | + } | ||
136 | + | ||
137 | + complete_apps = ['super_archives'] |
src/super_archives/migrations/0008_add_mailinglist_name_to_url.py
0 → 100644
@@ -0,0 +1,142 @@ | @@ -0,0 +1,142 @@ | ||
1 | +# encoding: utf-8 | ||
2 | +import datetime | ||
3 | +from south.db import db | ||
4 | +from south.v2 import DataMigration | ||
5 | +from django.db import models | ||
6 | + | ||
7 | +class Migration(DataMigration): | ||
8 | + | ||
9 | + def forwards(self, orm): | ||
10 | + page_hits = orm.PageHit.objects.all() | ||
11 | + for page_hit in page_hits: | ||
12 | + if page_hit.url_path.startswith('/archives/thread/'): | ||
13 | + token = page_hit.url_path.split('/')[-1] | ||
14 | + threads = orm.Thread.objects.filter(subject_token=token) | ||
15 | + if not len(threads): continue | ||
16 | + thread = threads[0] | ||
17 | + new_url = '/archives/thread/%s/%s' % (thread.mailinglist.name, | ||
18 | + thread.subject_token) | ||
19 | + page_hit.url_path = new_url | ||
20 | + page_hit.save() | ||
21 | + | ||
22 | + | ||
23 | + def backwards(self, orm): | ||
24 | + raise RuntimeError("Cannot reverse this migration.") | ||
25 | + | ||
26 | + models = { | ||
27 | + 'auth.group': { | ||
28 | + 'Meta': {'object_name': 'Group'}, | ||
29 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
30 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
31 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
32 | + }, | ||
33 | + 'auth.permission': { | ||
34 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
35 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
36 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
37 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
38 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
39 | + }, | ||
40 | + 'auth.user': { | ||
41 | + 'Meta': {'object_name': 'User'}, | ||
42 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
43 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
44 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
45 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
46 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
47 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
48 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
49 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
50 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
51 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
52 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
53 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
54 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
55 | + }, | ||
56 | + 'contenttypes.contenttype': { | ||
57 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
58 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
59 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
60 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
61 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
62 | + }, | ||
63 | + 'super_archives.emailaddress': { | ||
64 | + 'Meta': {'object_name': 'EmailAddress'}, | ||
65 | + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
66 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
67 | + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
68 | + 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), | ||
69 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
70 | + }, | ||
71 | + 'super_archives.mailinglist': { | ||
72 | + 'Meta': {'object_name': 'MailingList'}, | ||
73 | + 'description': ('django.db.models.fields.TextField', [], {}), | ||
74 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
75 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
76 | + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
77 | + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
78 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
79 | + }, | ||
80 | + 'super_archives.mailinglistmembership': { | ||
81 | + 'Meta': {'object_name': 'MailingListMembership'}, | ||
82 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
83 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
84 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
85 | + }, | ||
86 | + 'super_archives.message': { | ||
87 | + 'Meta': {'object_name': 'Message'}, | ||
88 | + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
89 | + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
90 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
91 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
92 | + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
93 | + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
94 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
95 | + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
96 | + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
97 | + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
98 | + }, | ||
99 | + 'super_archives.messagemetadata': { | ||
100 | + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
101 | + 'Meta': {'object_name': 'MessageMetadata'}, | ||
102 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
103 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
104 | + 'value': ('django.db.models.fields.TextField', [], {}) | ||
105 | + }, | ||
106 | + 'super_archives.pagehit': { | ||
107 | + 'Meta': {'object_name': 'PageHit'}, | ||
108 | + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
109 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
110 | + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
111 | + }, | ||
112 | + 'super_archives.thread': { | ||
113 | + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
114 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
115 | + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
116 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
117 | + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
118 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
119 | + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
120 | + }, | ||
121 | + 'super_archives.userprofile': { | ||
122 | + 'Meta': {'object_name': 'UserProfile'}, | ||
123 | + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
124 | + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
125 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
126 | + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
127 | + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
128 | + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
129 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
130 | + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
131 | + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
132 | + }, | ||
133 | + 'super_archives.vote': { | ||
134 | + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
135 | + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
136 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
137 | + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
138 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
139 | + } | ||
140 | + } | ||
141 | + | ||
142 | + complete_apps = ['super_archives'] |
src/super_archives/migrations/0009_auto__del_field_message_mailinglist.py
0 → 100644
@@ -0,0 +1,136 @@ | @@ -0,0 +1,136 @@ | ||
1 | +# encoding: utf-8 | ||
2 | +import datetime | ||
3 | +from south.db import db | ||
4 | +from south.v2 import SchemaMigration | ||
5 | +from django.db import models | ||
6 | + | ||
7 | +class Migration(SchemaMigration): | ||
8 | + | ||
9 | + def forwards(self, orm): | ||
10 | + | ||
11 | + # Deleting field 'Message.mailinglist' | ||
12 | + db.delete_column('super_archives_message', 'mailinglist_id') | ||
13 | + | ||
14 | + | ||
15 | + def backwards(self, orm): | ||
16 | + | ||
17 | + # User chose to not deal with backwards NULL issues for 'Message.mailinglist' | ||
18 | + raise RuntimeError("Cannot reverse this migration. 'Message.mailinglist' and its values cannot be restored.") | ||
19 | + | ||
20 | + | ||
21 | + models = { | ||
22 | + 'auth.group': { | ||
23 | + 'Meta': {'object_name': 'Group'}, | ||
24 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | + }, | ||
28 | + 'auth.permission': { | ||
29 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | + }, | ||
35 | + 'auth.user': { | ||
36 | + 'Meta': {'object_name': 'User'}, | ||
37 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | + }, | ||
51 | + 'contenttypes.contenttype': { | ||
52 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | + }, | ||
58 | + 'super_archives.emailaddress': { | ||
59 | + 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | + 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), | ||
64 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | + }, | ||
66 | + 'super_archives.mailinglist': { | ||
67 | + 'Meta': {'object_name': 'MailingList'}, | ||
68 | + 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | + }, | ||
75 | + 'super_archives.mailinglistmembership': { | ||
76 | + 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | + }, | ||
81 | + 'super_archives.message': { | ||
82 | + 'Meta': {'object_name': 'Message'}, | ||
83 | + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
87 | + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
88 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
89 | + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
90 | + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
91 | + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
92 | + }, | ||
93 | + 'super_archives.messagemetadata': { | ||
94 | + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
95 | + 'Meta': {'object_name': 'MessageMetadata'}, | ||
96 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
97 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | + 'value': ('django.db.models.fields.TextField', [], {}) | ||
99 | + }, | ||
100 | + 'super_archives.pagehit': { | ||
101 | + 'Meta': {'object_name': 'PageHit'}, | ||
102 | + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
103 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
105 | + }, | ||
106 | + 'super_archives.thread': { | ||
107 | + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
108 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
109 | + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
110 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
111 | + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
112 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
113 | + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
114 | + }, | ||
115 | + 'super_archives.userprofile': { | ||
116 | + 'Meta': {'object_name': 'UserProfile'}, | ||
117 | + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
118 | + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
119 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
120 | + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
121 | + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
122 | + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
123 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
124 | + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
125 | + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
126 | + }, | ||
127 | + 'super_archives.vote': { | ||
128 | + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
129 | + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
130 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
131 | + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
132 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
133 | + } | ||
134 | + } | ||
135 | + | ||
136 | + complete_apps = ['super_archives'] |
src/super_archives/migrations/0010_auto__add_unique_message_message_id_thread.py
0 → 100644
@@ -0,0 +1,136 @@ | @@ -0,0 +1,136 @@ | ||
1 | +# encoding: utf-8 | ||
2 | +import datetime | ||
3 | +from south.db import db | ||
4 | +from south.v2 import SchemaMigration | ||
5 | +from django.db import models | ||
6 | + | ||
7 | +class Migration(SchemaMigration): | ||
8 | + | ||
9 | + def forwards(self, orm): | ||
10 | + | ||
11 | + # Adding unique constraint on 'Message', fields ['message_id', 'thread'] | ||
12 | + db.create_unique('super_archives_message', ['message_id', 'thread_id']) | ||
13 | + | ||
14 | + | ||
15 | + def backwards(self, orm): | ||
16 | + | ||
17 | + # Removing unique constraint on 'Message', fields ['message_id', 'thread'] | ||
18 | + db.delete_unique('super_archives_message', ['message_id', 'thread_id']) | ||
19 | + | ||
20 | + | ||
21 | + models = { | ||
22 | + 'auth.group': { | ||
23 | + 'Meta': {'object_name': 'Group'}, | ||
24 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | + }, | ||
28 | + 'auth.permission': { | ||
29 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | + }, | ||
35 | + 'auth.user': { | ||
36 | + 'Meta': {'object_name': 'User'}, | ||
37 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | + }, | ||
51 | + 'contenttypes.contenttype': { | ||
52 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | + }, | ||
58 | + 'super_archives.emailaddress': { | ||
59 | + 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | + 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), | ||
64 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | + }, | ||
66 | + 'super_archives.mailinglist': { | ||
67 | + 'Meta': {'object_name': 'MailingList'}, | ||
68 | + 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | + }, | ||
75 | + 'super_archives.mailinglistmembership': { | ||
76 | + 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | + }, | ||
81 | + 'super_archives.message': { | ||
82 | + 'Meta': {'unique_together': "(('thread', 'message_id'),)", 'object_name': 'Message'}, | ||
83 | + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
87 | + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
88 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
89 | + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
90 | + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
91 | + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
92 | + }, | ||
93 | + 'super_archives.messagemetadata': { | ||
94 | + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
95 | + 'Meta': {'object_name': 'MessageMetadata'}, | ||
96 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
97 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | + 'value': ('django.db.models.fields.TextField', [], {}) | ||
99 | + }, | ||
100 | + 'super_archives.pagehit': { | ||
101 | + 'Meta': {'object_name': 'PageHit'}, | ||
102 | + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
103 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
105 | + }, | ||
106 | + 'super_archives.thread': { | ||
107 | + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
108 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
109 | + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
110 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
111 | + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
112 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
113 | + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
114 | + }, | ||
115 | + 'super_archives.userprofile': { | ||
116 | + 'Meta': {'object_name': 'UserProfile'}, | ||
117 | + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
118 | + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
119 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
120 | + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
121 | + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
122 | + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
123 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
124 | + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
125 | + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
126 | + }, | ||
127 | + 'super_archives.vote': { | ||
128 | + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
129 | + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
130 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
131 | + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
132 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
133 | + } | ||
134 | + } | ||
135 | + | ||
136 | + complete_apps = ['super_archives'] |
@@ -0,0 +1,279 @@ | @@ -0,0 +1,279 @@ | ||
1 | +# -*- coding: utf-8 -*- | ||
2 | + | ||
3 | +import datetime | ||
4 | +from hashlib import md5 | ||
5 | + | ||
6 | +from django.db import models | ||
7 | +from django.conf import settings | ||
8 | +from django.contrib.auth.models import User | ||
9 | +from django.core.urlresolvers import reverse, NoReverseMatch | ||
10 | +from django.utils.translation import ugettext_lazy as _ | ||
11 | + | ||
12 | + | ||
13 | +class NotSpamManager(models.Manager): | ||
14 | + """Only return objects which are not marked as spam.""" | ||
15 | + | ||
16 | + def get_query_set(self): | ||
17 | + return super(NotSpamManager, self).get_query_set().exclude(spam=True) | ||
18 | + | ||
19 | + | ||
20 | +class PageHit(models.Model): | ||
21 | + url_path = models.CharField(max_length=2048, unique=True, db_index=True) | ||
22 | + hit_count = models.IntegerField(default=0) | ||
23 | + | ||
24 | + | ||
25 | +class EmailAddress(models.Model): | ||
26 | + user = models.ForeignKey(User, null=True, related_name='emails') | ||
27 | + address = models.EmailField(unique=True) | ||
28 | + real_name = models.CharField(max_length=64, blank=True, db_index=True) | ||
29 | + md5 = models.CharField(max_length=32, null=True) | ||
30 | + | ||
31 | + def save(self, *args, **kwargs): | ||
32 | + self.md5 = md5(self.address).hexdigest() | ||
33 | + super(EmailAddress, self).save(*args, **kwargs) | ||
34 | + | ||
35 | + def get_full_name(self): | ||
36 | + if self.user and self.user.get_full_name(): | ||
37 | + return self.user.get_full_name() | ||
38 | + elif self.user and self.username: | ||
39 | + return self.username | ||
40 | + elif self.real_name: | ||
41 | + return self.real_name | ||
42 | + | ||
43 | + def get_profile_link(self): | ||
44 | + if self.user: | ||
45 | + return reverse('user_profile', args=[self.user.username]) | ||
46 | + else: | ||
47 | + return reverse('colab.views.userprofile.by_emailhash', | ||
48 | + args=[self.md5]) | ||
49 | + | ||
50 | + def __unicode__(self): | ||
51 | + return '"%s" <%s>' % (self.get_full_name(), self.address) | ||
52 | + | ||
53 | + | ||
54 | +class UserProfile(models.Model): | ||
55 | + | ||
56 | + user = models.OneToOneField(User, unique=True) | ||
57 | + institution = models.CharField(max_length=128, null=True) | ||
58 | + role = models.CharField(max_length=128, null=True) | ||
59 | + twitter = models.CharField(max_length=128, null=True) | ||
60 | + facebook = models.CharField(max_length=128, null=True) | ||
61 | + google_talk = models.EmailField(null=True) | ||
62 | + webpage = models.CharField(max_length=256) | ||
63 | + verification_hash = models.CharField(max_length=32, null=True) | ||
64 | + | ||
65 | + class Meta: | ||
66 | + verbose_name = _(u"User Profile") | ||
67 | + verbose_name_plural = _(u"Users Profiles") | ||
68 | + | ||
69 | + def __unicode__(self): | ||
70 | + return '%s (%s)' % (self.user.get_full_name(), self.user.username) | ||
71 | + | ||
72 | +# This does the same the same than related_name argument but it also creates | ||
73 | +# a profile in the case it doesn't exist yet. | ||
74 | +User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0]) | ||
75 | + | ||
76 | + | ||
77 | +class MailingList(models.Model): | ||
78 | + name = models.CharField(max_length=80) | ||
79 | + email = models.EmailField() | ||
80 | + description = models.TextField() | ||
81 | + logo = models.FileField(upload_to='list_logo') #TODO | ||
82 | + last_imported_index = models.IntegerField(default=0) | ||
83 | + | ||
84 | + def __unicode__(self): | ||
85 | + return self.name | ||
86 | + | ||
87 | + | ||
88 | +class MailingListMembership(models.Model): | ||
89 | + user = models.ForeignKey(User) | ||
90 | + mailinglist = models.ForeignKey(MailingList) | ||
91 | + | ||
92 | + def __unicode__(self): | ||
93 | + return '%s on %s' % (self.user.username, self.mailinglist.name) | ||
94 | + | ||
95 | + | ||
96 | +class Thread(models.Model): | ||
97 | + | ||
98 | + subject_token = models.CharField(max_length=512) | ||
99 | + mailinglist = models.ForeignKey(MailingList, | ||
100 | + verbose_name=_(u"Mailing List"), | ||
101 | + help_text=_(u"The Mailing List where is the thread")) | ||
102 | + latest_message = models.OneToOneField('Message', null=True, | ||
103 | + related_name='+', | ||
104 | + verbose_name=_(u"Latest message"), | ||
105 | + help_text=_(u"Latest message posted")) | ||
106 | + score = models.IntegerField(default=0, verbose_name=_(u"Score"), help_text=_(u"Thread score")) | ||
107 | + spam = models.BooleanField(default=False) | ||
108 | + | ||
109 | + all_objects = models.Manager() | ||
110 | + objects = NotSpamManager() | ||
111 | + | ||
112 | + class Meta: | ||
113 | + verbose_name = _(u"Thread") | ||
114 | + verbose_name_plural = _(u"Threads") | ||
115 | + unique_together = ('subject_token', 'mailinglist') | ||
116 | + | ||
117 | + def __unicode__(self): | ||
118 | + return '%s - %s (%s)' % (self.id, | ||
119 | + self.subject_token, | ||
120 | + self.message_set.count()) | ||
121 | + | ||
122 | + def update_score(self): | ||
123 | + """Update the relevance score for this thread. | ||
124 | + | ||
125 | + The score is calculated with the following variables: | ||
126 | + | ||
127 | + * vote_weight: 100 - (minus) 1 for each 3 days since | ||
128 | + voted with minimum of 5. | ||
129 | + * replies_weight: 300 - (minus) 1 for each 3 days since | ||
130 | + replied with minimum of 5. | ||
131 | + * page_view_weight: 10. | ||
132 | + | ||
133 | + * vote_score: sum(vote_weight) | ||
134 | + * replies_score: sum(replies_weight) | ||
135 | + * page_view_score: sum(page_view_weight) | ||
136 | + | ||
137 | + * score = (vote_score + replies_score + page_view_score) // 10 | ||
138 | + with minimum of 0 and maximum of 5000 | ||
139 | + | ||
140 | + """ | ||
141 | + | ||
142 | + if not self.subject_token: | ||
143 | + return | ||
144 | + | ||
145 | + # Save this pseudo now to avoid calling the | ||
146 | + # function N times in the loops below | ||
147 | + now = datetime.datetime.now() | ||
148 | + days_ago = lambda date: (now - date).days | ||
149 | + get_score = lambda weight, created: \ | ||
150 | + max(weight - (days_ago(created) // 3), 5) | ||
151 | + | ||
152 | + vote_score = 0 | ||
153 | + replies_score = 0 | ||
154 | + for msg in self.message_set.all(): | ||
155 | + # Calculate replies_score | ||
156 | + replies_score += get_score(300, msg.received_time) | ||
157 | + | ||
158 | + # Calculate vote_score | ||
159 | + for vote in msg.vote_set.all(): | ||
160 | + vote_score += get_score(100, vote.created) | ||
161 | + | ||
162 | + # Calculate page_view_score | ||
163 | + try: | ||
164 | + url = reverse('thread_view', args=[self.mailinglist.name, | ||
165 | + self.subject_token]) | ||
166 | + pagehit = PageHit.objects.get(url_path=url) | ||
167 | + page_view_score = pagehit.hit_count * 10 | ||
168 | + except (NoReverseMatch, PageHit.DoesNotExist): | ||
169 | + page_view_score = 0 | ||
170 | + | ||
171 | + self.score = (page_view_score + vote_score + replies_score) // 10 | ||
172 | + self.save() | ||
173 | + | ||
174 | + | ||
175 | +class Vote(models.Model): | ||
176 | + user = models.ForeignKey(User) | ||
177 | + message = models.ForeignKey('Message') | ||
178 | + created = models.DateTimeField(auto_now_add=True) | ||
179 | + | ||
180 | + class Meta: | ||
181 | + unique_together = ('user', 'message') | ||
182 | + | ||
183 | + def __unicode__(self): | ||
184 | + return 'Vote on %s by %s' % (self.Message.id, | ||
185 | + self.user.username) | ||
186 | + | ||
187 | + | ||
188 | +class Message(models.Model): | ||
189 | + | ||
190 | + from_address = models.ForeignKey(EmailAddress, db_index=True) | ||
191 | + thread = models.ForeignKey(Thread, null=True, db_index=True) | ||
192 | + # RFC 2822 recommends to use 78 chars + CRLF (so 80 chars) for | ||
193 | + # the max_length of a subject but most of implementations | ||
194 | + # goes for 256. We use 512 just in case. | ||
195 | + subject = models.CharField(max_length=512, db_index=True, | ||
196 | + verbose_name=_(u"Subject"), | ||
197 | + help_text=_(u"Please enter a message subject")) | ||
198 | + subject_clean = models.CharField(max_length=512, db_index=True) | ||
199 | + body = models.TextField(default='', | ||
200 | + verbose_name=_(u"Message body"), | ||
201 | + help_text=_(u"Please enter a message body")) | ||
202 | + received_time = models.DateTimeField() | ||
203 | + message_id = models.CharField(max_length=512) | ||
204 | + spam = models.BooleanField(default=False) | ||
205 | + | ||
206 | + all_objects = models.Manager() | ||
207 | + objects = NotSpamManager() | ||
208 | + | ||
209 | + class Meta: | ||
210 | + verbose_name = _(u"Message") | ||
211 | + verbose_name_plural = _(u"Messages") | ||
212 | + unique_together = ('thread', 'message_id') | ||
213 | + | ||
214 | + def __unicode__(self): | ||
215 | + return '(%s) %s: %s' % (self.id, | ||
216 | + self.from_address.get_full_name(), | ||
217 | + self.subject_clean) | ||
218 | + | ||
219 | + @property | ||
220 | + def mailinglist(self): | ||
221 | + if not self.thread or not self.thread.mailinglist: | ||
222 | + return None | ||
223 | + | ||
224 | + return self.thread.mailinglist | ||
225 | + | ||
226 | + | ||
227 | + def vote_list(self): | ||
228 | + """Return a list of user that voted in this message.""" | ||
229 | + | ||
230 | + return [vote.user for vote in self.vote_set.all()] | ||
231 | + | ||
232 | + def votes_count(self): | ||
233 | + return len(self.vote_list()) | ||
234 | + | ||
235 | + def vote(self, user): | ||
236 | + Vote.objects.create( | ||
237 | + message=self, | ||
238 | + user=user | ||
239 | + ) | ||
240 | + | ||
241 | + def unvote(self, user): | ||
242 | + Vote.objects.get( | ||
243 | + message=self, | ||
244 | + user=user | ||
245 | + ).delete() | ||
246 | + | ||
247 | + @property | ||
248 | + def url(self): | ||
249 | + """Shortcut to get thread url""" | ||
250 | + return reverse('thread_view', args=[self.mailinglist.name, | ||
251 | + self.thread.subject_token]) | ||
252 | + | ||
253 | + @property | ||
254 | + def Description(self): | ||
255 | + """Alias to self.body""" | ||
256 | + return self.body | ||
257 | + | ||
258 | + @property | ||
259 | + def Title(self): | ||
260 | + """Alias to self.subject_clean""" | ||
261 | + return self.subject_clean | ||
262 | + | ||
263 | + @property | ||
264 | + def modified(self): | ||
265 | + """Alias to self.modified""" | ||
266 | + return self.received_time | ||
267 | + | ||
268 | + | ||
269 | +class MessageMetadata(models.Model): | ||
270 | + Message = models.ForeignKey(Message) | ||
271 | + # Same problem here than on subjects. Read comment above | ||
272 | + # on Message.subject | ||
273 | + name = models.CharField(max_length=512) | ||
274 | + value = models.TextField() | ||
275 | + | ||
276 | + def __unicode__(self): | ||
277 | + return 'Email Message Id: %s - %s: %s' % (self.Message.id, | ||
278 | + self.name, self.value) | ||
279 | + |
@@ -0,0 +1,54 @@ | @@ -0,0 +1,54 @@ | ||
1 | + | ||
2 | +from django.core.exceptions import ObjectDoesNotExist | ||
3 | +from colab.super_archives.models import Thread, Vote, Message, PageHit | ||
4 | + | ||
5 | + | ||
6 | +def get_messages_by_date(): | ||
7 | + return Message.objects.order_by('received_time') | ||
8 | + | ||
9 | + | ||
10 | +def get_messages_by_voted(): | ||
11 | + """Query for the most voted messages sorting by the sum of | ||
12 | + voted and after by date.""" | ||
13 | + | ||
14 | + sql = """ | ||
15 | + SELECT | ||
16 | + count(sav.id) | ||
17 | + FROM | ||
18 | + super_archives_vote AS sav | ||
19 | + WHERE | ||
20 | + super_archives_message.id = sav.message_id | ||
21 | + """ | ||
22 | + messages = Message.objects.extra( | ||
23 | + select={ | ||
24 | + 'vote_count': sql, | ||
25 | + } | ||
26 | + ) | ||
27 | + return messages.order_by('-vote_count', 'received_time') | ||
28 | + | ||
29 | + | ||
30 | +def get_first_message_in_thread(mailinglist, thread_token): | ||
31 | + query = get_messages_by_date() | ||
32 | + query = query.filter(thread__mailinglist__name=mailinglist) | ||
33 | + try: | ||
34 | + query = query.filter(thread__subject_token=thread_token)[0] | ||
35 | + except IndexError: | ||
36 | + raise ObjectDoesNotExist | ||
37 | + return query | ||
38 | + | ||
39 | + | ||
40 | +def get_latest_threads(): | ||
41 | + return Thread.objects.order_by('-latest_message__received_time') | ||
42 | + | ||
43 | + | ||
44 | +def get_hottest_threads(): | ||
45 | + return Thread.objects.order_by('-score', '-latest_message__received_time') | ||
46 | + | ||
47 | + | ||
48 | +def get_page_hits(path_info): | ||
49 | + pagehit = PageHit.objects.filter(url_path=path_info) | ||
50 | + | ||
51 | + if pagehit: | ||
52 | + return pagehit[0].hit_count | ||
53 | + return 0 | ||
54 | + |
@@ -0,0 +1,68 @@ | @@ -0,0 +1,68 @@ | ||
1 | +{% extends "base.html" %} | ||
2 | +{% load i18n %} | ||
3 | +{% load append_to_get %} | ||
4 | +{% block main-content %} | ||
5 | +<div id="message-list"> | ||
6 | + <h2 class="span-5">{% trans "Discussions" %}</h2> | ||
7 | + <hr/> | ||
8 | + | ||
9 | + <div class="span-5 border filters"> | ||
10 | + <h3>{% trans "Filters" %}</h3> | ||
11 | + | ||
12 | + <h4>{% trans "Sort by" %}</h4> | ||
13 | + <ul> | ||
14 | + <li {% ifequal order_by "hottest" %} class="selected" title="{% trans "Remove filter" %}" {% endifequal %}> | ||
15 | + <a href="{% ifequal order_by "hottest" %} {% append_to_get order="",p=1 %} {% else %} {% append_to_get order='hottest',p=1 %} {% endifequal %}"> | ||
16 | + {% trans "Relevance" %}</a></li> | ||
17 | + <li {% ifequal order_by "latest" %} class="selected" title="{% trans "Remove filter" %}" {% endifequal %}> | ||
18 | + <a href="{% ifequal order_by "latest" %} {% append_to_get order="",p=1 %} {% else %} {% append_to_get order='latest',p=1 %} {% endifequal %}"> | ||
19 | + {% trans "Recent activity" %}</a></li> | ||
20 | + </ul> | ||
21 | + | ||
22 | + <hr class="space" /> | ||
23 | + | ||
24 | + <h4>{% trans "Lists" %}</h4> | ||
25 | + <ul> | ||
26 | + {% for list in lists %} | ||
27 | + <li {% ifequal list.name selected_list %} class="selected" title="{% trans "Remove filter" %}" {% endifequal %}> | ||
28 | + <a href="{% ifnotequal list.name selected_list %} {% append_to_get list=list.name,p=1 %} {% else %} {% append_to_get list="",p=1 %} | ||
29 | + {% endifnotequal %}">{{ list.name }}</a></li> | ||
30 | + {% endfor %} | ||
31 | + </ul> | ||
32 | + </div> | ||
33 | + | ||
34 | + <div class="span-17 prepend-1 last"> | ||
35 | + <ul> | ||
36 | + {% for thread in threads.object_list %} | ||
37 | + {% include "message-preview.html" with doc=thread.latest_message %} | ||
38 | + {% empty %} | ||
39 | + <br/><br/> | ||
40 | + <span class="span-18 center large"> | ||
41 | + <b>{% trans "No discussion found" %}</b> | ||
42 | + </span> | ||
43 | + {% endfor %} | ||
44 | + </ul> | ||
45 | + <hr class="space"/> | ||
46 | + | ||
47 | + {% if n_results %} | ||
48 | + <div class="pagination center"> | ||
49 | + <span class="step-links"> | ||
50 | + {% if threads.has_previous %} | ||
51 | + <a href="{% append_to_get p=threads.previous_page_number %}">{% trans "Previous" %}</a> | ||
52 | + {% endif %} | ||
53 | + | ||
54 | + <span class="current"> | ||
55 | + {% trans "Page" %} {{ threads.number }} {% trans "of" %} {{ threads.paginator.num_pages }} | ||
56 | + </span> | ||
57 | + | ||
58 | + {% if threads.has_next %} | ||
59 | + <a href="{% append_to_get p=threads.next_page_number %}">{% trans "Next" %}</a> | ||
60 | + {% endif %} | ||
61 | + </span> | ||
62 | + </div> | ||
63 | + {% endif %} | ||
64 | + | ||
65 | + </div> | ||
66 | +</div> | ||
67 | + | ||
68 | +{% endblock %} |
@@ -0,0 +1,51 @@ | @@ -0,0 +1,51 @@ | ||
1 | +{% load i18n %} | ||
2 | + | ||
3 | +{% if doc.Title %} | ||
4 | +<li class="preview-message"> | ||
5 | + {% if doc.Type %} | ||
6 | + <img alt="{{ doc.Type }}" title="{{ doc.Type }}" | ||
7 | + src="{{ STATIC_URL }}img/{{ doc.Type }}.png" /> | ||
8 | + {% else %} | ||
9 | + <img alt="thread" title="thread" | ||
10 | + src="{{ STATIC_URL }}img/thread.png" /> | ||
11 | + {% endif %} | ||
12 | + | ||
13 | + {% if doc.mailinglist %} | ||
14 | + <a href="{% url super_archives.views.list_messages %}?list={{ doc.mailinglist }}"> | ||
15 | + <span class="tag">{{ doc.mailinglist }}</span> | ||
16 | + </a> | ||
17 | + {% endif %} | ||
18 | + | ||
19 | + <span class="subject"> | ||
20 | + <a href="{{ doc.url }}" | ||
21 | + {% if | ||
22 | + title="{% filter striptags|truncatewords:50 %} | ||
23 | + {{ doc.Description|escape }} | ||
24 | + {% endfilter %}"> | ||
25 | + {{ doc.Title }} | ||
26 | + </a> | ||
27 | + </span> | ||
28 | + | ||
29 | + <span class="quiet">- | ||
30 | + {{ doc.Description|striptags }} | ||
31 | + </span> | ||
32 | + | ||
33 | + <div class="quiet"> | ||
34 | + <span class="left"> | ||
35 | + {% trans "by" %} | ||
36 | + {% if doc.from_address.get_full_name %} | ||
37 | + <a href="{{ doc.from_address.get_profile_link }}"> | ||
38 | + {{ doc.from_address.get_full_name }} | ||
39 | + </a> | ||
40 | + {% else %} | ||
41 | + {% firstof doc.last_author doc.Creator _("anônimo") %} | ||
42 | + {% endif %} | ||
43 | + </span> | ||
44 | + | ||
45 | + <span class="right"> | ||
46 | + {{ doc.modified|timesince }} | ||
47 | + {% trans "back" %} | ||
48 | + </span> | ||
49 | + </div> | ||
50 | +</li> | ||
51 | +{% endif %} |
@@ -0,0 +1,77 @@ | @@ -0,0 +1,77 @@ | ||
1 | +{% extends "base.html" %} | ||
2 | +{% load i18n %} | ||
3 | +{% load append_to_get %} | ||
4 | +{% block main-content %} | ||
5 | + <div id="vote-notification" class="error hide"></div> | ||
6 | + | ||
7 | + <h2>{{ first_msg.subject_clean }}</h2> | ||
8 | + <hr/> | ||
9 | + <div class="span-17 border"> | ||
10 | + <ul> | ||
11 | + {% for email in emails %} | ||
12 | + <li> | ||
13 | + <div id="msg-{{ email.id }}" class="email_message"> | ||
14 | + <div class="span-3 center"> | ||
15 | + <div> | ||
16 | + <a href="{{ email.from_address.get_profile_link }}"> | ||
17 | + <img class="avatar" width="80px" heigth="80px" | ||
18 | + src="http://www.gravatar.com/avatar/{{ email.from_address.md5 }}?s=80&d=identicon" /> | ||
19 | + <span>{% firstof email.from_address.get_full_name "Anônimo" %}</span> | ||
20 | + </a> | ||
21 | + </div> | ||
22 | + <p>{{ email.received_time|date:"SHORT_DATETIME_FORMAT" }}</p> | ||
23 | + | ||
24 | + <div class="plus"> | ||
25 | + <span>{{ email.votes_count }}</span> | ||
26 | + <img title="{% trans 'Vote' %}" class="right" src="{{ STATIC_URL }}img/plus.png"> | ||
27 | + </div> | ||
28 | + | ||
29 | + <p class="minus {% if not user in email.vote_list %}hide{% endif %}"> | ||
30 | + <a href="#">{% trans "Remove votes" %}</a> | ||
31 | + </p> | ||
32 | + </div> | ||
33 | + | ||
34 | + <div class="span-13"> | ||
35 | + <pre>{{ email.body }}</pre> | ||
36 | + </div> | ||
37 | + </div> | ||
38 | + {% if not forloop.last %} | ||
39 | + <hr/> | ||
40 | + {% endif %} | ||
41 | + </li> | ||
42 | + {% endfor %} | ||
43 | + </ul> | ||
44 | + </div> | ||
45 | + <div class="span-6 filters last"> | ||
46 | + <h4><b>{% trans "Order by" %}:</b></h4> | ||
47 | + <ul> | ||
48 | + <li><a href="{% append_to_get order='voted' %}">{% trans "Votes" %}</a></li> | ||
49 | + <li><a href="{% append_to_get order='date' %}">{% trans "Data" %}</a></li> | ||
50 | + </ul> | ||
51 | + | ||
52 | + <hr class="space"/> | ||
53 | + | ||
54 | + <h4><b>{% trans "Statistics:" %}</b></h4> | ||
55 | + | ||
56 | + <ul> | ||
57 | + <li class="quiet">{% trans "started at" %} | ||
58 | + <h4>{{ first_msg.received_time|timesince }} {% trans "back" %}</h4> | ||
59 | + </li> | ||
60 | + <li class="quiet">{% trans "viewed" %} | ||
61 | + <h4>{{ pagehits }} {% trans "times" %}</h4> | ||
62 | + </li> | ||
63 | + <li class="quiet">{% trans "answered" %} | ||
64 | + <h4>{{ emails|length }} {% trans "times" %}</h4> | ||
65 | + </li> | ||
66 | + <li class="quiet">{% trans "voted" %} | ||
67 | + <h4>{{ total_votes }} {% trans "times" %}</h4> | ||
68 | + </li> | ||
69 | + </ul> | ||
70 | + | ||
71 | + </div> | ||
72 | + | ||
73 | + <script type="text/javascript" charset="utf-8"> | ||
74 | + pagehit("{{ request.path_info }}"); | ||
75 | + </script> | ||
76 | + | ||
77 | +{% endblock %} |
@@ -0,0 +1,56 @@ | @@ -0,0 +1,56 @@ | ||
1 | + | ||
2 | +import urllib | ||
3 | +from django import template | ||
4 | + | ||
5 | +register = template.Library() | ||
6 | + | ||
7 | +""" | ||
8 | +Decorator to facilitate template tag creation | ||
9 | +""" | ||
10 | +def easy_tag(func): | ||
11 | + """deal with the repetitive parts of parsing template tags""" | ||
12 | + def inner(parser, token): | ||
13 | + #print token | ||
14 | + try: | ||
15 | + return func(*token.split_contents()) | ||
16 | + except TypeError: | ||
17 | + raise template.TemplateSyntaxError('Bad arguments for tag "%s"' % | ||
18 | + token.split_contents()[0]) | ||
19 | + inner.__name__ = func.__name__ | ||
20 | + inner.__doc__ = inner.__doc__ | ||
21 | + return inner | ||
22 | + | ||
23 | + | ||
24 | +class AppendGetNode(template.Node): | ||
25 | + def __init__(self, dict): | ||
26 | + self.dict_pairs = {} | ||
27 | + for pair in dict.split(','): | ||
28 | + pair = pair.split('=') | ||
29 | + self.dict_pairs[pair[0]] = template.Variable(pair[1]) | ||
30 | + | ||
31 | + def render(self, context): | ||
32 | + get = context['request'].GET.copy() | ||
33 | + | ||
34 | + for key in self.dict_pairs: | ||
35 | + get[key] = self.dict_pairs[key].resolve(context) | ||
36 | + | ||
37 | + path = context['request'].META['PATH_INFO'] | ||
38 | + | ||
39 | + if len(get): | ||
40 | + # Convert all unicode objects in the get dict to | ||
41 | + # str (utf-8 encoded) | ||
42 | + get_utf_encoded = {} | ||
43 | + for (key, value) in get.items(): | ||
44 | + if isinstance(value, unicode): | ||
45 | + value = value.encode('utf-8') | ||
46 | + get_utf_encoded.update({key: value}) | ||
47 | + get_utf_encoded = dict(get_utf_encoded) | ||
48 | + | ||
49 | + path = '?' + urllib.urlencode(get_utf_encoded) | ||
50 | + | ||
51 | + return path | ||
52 | + | ||
53 | +@register.tag() | ||
54 | +@easy_tag | ||
55 | +def append_to_get(_tag_name, dict): | ||
56 | + return AppendGetNode(dict) |
@@ -0,0 +1,64 @@ | @@ -0,0 +1,64 @@ | ||
1 | +from django import template | ||
2 | +from django import forms | ||
3 | + | ||
4 | +def render_form_field(parser, token): | ||
5 | + variables = token.split_contents() | ||
6 | + | ||
7 | + if len(variables) == 2: | ||
8 | + tag_name, form_field = variables | ||
9 | + default_value = 'None' | ||
10 | + elif len(variables) == 3: | ||
11 | + tag_name, form_field, default_value = variables | ||
12 | + else: | ||
13 | + raise template.TemplateSyntaxError | ||
14 | + | ||
15 | + return RenderFormField(form_field, default_value) | ||
16 | + | ||
17 | + | ||
18 | +class RenderFormField(template.Node): | ||
19 | + | ||
20 | + def __init__(self, form_field, default_value): | ||
21 | + self.form_field_nocontext = template.Variable(form_field) | ||
22 | + self.default_value_nocontext = template.Variable(default_value) | ||
23 | + | ||
24 | + def render(self, context): | ||
25 | + editable = context.get('editable', True) | ||
26 | + | ||
27 | + class_ = u'' | ||
28 | + errors = u'' | ||
29 | + form_field_tag = u'' | ||
30 | + try: | ||
31 | + form_field = self.form_field_nocontext.resolve(context) | ||
32 | + except template.VariableDoesNotExist: | ||
33 | + return u'' | ||
34 | + | ||
35 | + if form_field.errors: | ||
36 | + class_ += u'error' | ||
37 | + if form_field.field.required: | ||
38 | + class_ += u' required' | ||
39 | + if form_field.errors: | ||
40 | + errors = u'<br/>' + form_field.errors.as_text() | ||
41 | + | ||
42 | + try: | ||
43 | + default_value = self.default_value_nocontext.resolve(context) | ||
44 | + except template.VariableDoesNotExist: | ||
45 | + default_value = u'' | ||
46 | + | ||
47 | + if editable: | ||
48 | + form_field_tag = u'<br/>' + unicode(form_field) | ||
49 | + elif isinstance(form_field.field, forms.URLField): | ||
50 | + form_field_tag = u"""<a href="%s" target="_blank">%s</a>""" % ( | ||
51 | + default_value, default_value) | ||
52 | + else: | ||
53 | + form_field_tag = default_value | ||
54 | + | ||
55 | + return u"""<p class="%s">%s: %s %s</p>""" % ( | ||
56 | + class_, | ||
57 | + form_field.label_tag(), | ||
58 | + form_field_tag, | ||
59 | + errors | ||
60 | + ) | ||
61 | + | ||
62 | + | ||
63 | +register = template.Library() | ||
64 | +register.tag('render_form_field', render_form_field) |
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +""" | ||
2 | +This file demonstrates writing tests using the unittest module. These will pass | ||
3 | +when you run "manage.py test". | ||
4 | + | ||
5 | +Replace this with more appropriate tests for your application. | ||
6 | +""" | ||
7 | + | ||
8 | +from django.test import TestCase | ||
9 | + | ||
10 | + | ||
11 | +class SimpleTest(TestCase): | ||
12 | + def test_basic_addition(self): | ||
13 | + """ | ||
14 | + Tests that 1 + 1 always equals 2. | ||
15 | + """ | ||
16 | + self.assertEqual(1 + 1, 2) |
@@ -0,0 +1,9 @@ | @@ -0,0 +1,9 @@ | ||
1 | +from django.conf.urls.defaults import patterns, include, url | ||
2 | + | ||
3 | +urlpatterns = patterns('', | ||
4 | +# url(r'thread/(?P<thread>\d+)/$', 'super_archives.views.thread', name='thread'), | ||
5 | + url(r'thread/(?P<mailinglist>[-\w]+)/(?P<thread_token>[-\w]+)$', | ||
6 | + 'colab.super_archives.views.thread', name="thread_view"), | ||
7 | + url(r'thread/$', | ||
8 | + 'colab.super_archives.views.list_messages', name='thread_list') | ||
9 | +) |
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +# -*- coding: utf-8 -*- | ||
2 | + | ||
3 | +from django.core.exceptions import ValidationError | ||
4 | + | ||
5 | +class UniqueValidator(object): | ||
6 | + | ||
7 | + def __init__(self, model, field_name): | ||
8 | + self.model = model | ||
9 | + self.field_name = field_name | ||
10 | + | ||
11 | + def __call__(self, value): | ||
12 | + result = self.model.objects.filter(**{self.field_name: value}) | ||
13 | + if result: | ||
14 | + msg = u'Já existente. Escolha outro.' | ||
15 | + raise ValidationError(msg) |
@@ -0,0 +1,80 @@ | @@ -0,0 +1,80 @@ | ||
1 | +# -*- coding: utf-8 -*- | ||
2 | + | ||
3 | +from django.http import Http404 | ||
4 | +from django.template import RequestContext | ||
5 | +from django.core.paginator import Paginator | ||
6 | +from django.core.exceptions import ObjectDoesNotExist | ||
7 | +from django.shortcuts import render_to_response, get_list_or_404 | ||
8 | + | ||
9 | +from colab.super_archives import queries | ||
10 | +from colab.super_archives.models import MailingList, Thread | ||
11 | + | ||
12 | + | ||
13 | +def thread(request, mailinglist, thread_token): | ||
14 | + | ||
15 | + try: | ||
16 | + first_message = queries.get_first_message_in_thread(mailinglist, thread_token) | ||
17 | + except ObjectDoesNotExist: | ||
18 | + raise Http404 | ||
19 | + order_by = request.GET.get('order') | ||
20 | + if order_by == 'voted': | ||
21 | + msgs_query = queries.get_messages_by_voted() | ||
22 | + else: | ||
23 | + msgs_query = queries.get_messages_by_date() | ||
24 | + | ||
25 | + msgs_query = msgs_query.filter(thread__subject_token=thread_token) | ||
26 | + msgs_query = msgs_query.filter(thread__mailinglist__name=mailinglist) | ||
27 | + emails = msgs_query.exclude(id=first_message.id) | ||
28 | + | ||
29 | + total_votes = first_message.votes_count() | ||
30 | + for email in emails: | ||
31 | + total_votes += email.votes_count() | ||
32 | + | ||
33 | + # Update relevance score | ||
34 | + query = Thread.objects.filter(mailinglist__name=mailinglist) | ||
35 | + thread = query.get(subject_token=thread_token) | ||
36 | + thread.update_score() | ||
37 | + | ||
38 | + template_data = { | ||
39 | + 'first_msg': first_message, | ||
40 | + 'emails': [first_message] + list(emails), | ||
41 | + 'pagehits': queries.get_page_hits(request.path_info), | ||
42 | + 'total_votes': total_votes, | ||
43 | + } | ||
44 | + | ||
45 | + return render_to_response('message-thread.html', template_data, | ||
46 | + RequestContext(request)) | ||
47 | + | ||
48 | + | ||
49 | +def list_messages(request): | ||
50 | + | ||
51 | + selected_list = request.GET.get('list') | ||
52 | + | ||
53 | + order_by = request.GET.get('order') | ||
54 | + if order_by == 'hottest': | ||
55 | + threads = queries.get_hottest_threads() | ||
56 | + else: | ||
57 | + threads = queries.get_latest_threads() | ||
58 | + | ||
59 | + mail_list = request.GET.get('list') | ||
60 | + if mail_list: | ||
61 | + threads = threads.filter(mailinglist__name=mail_list) | ||
62 | + | ||
63 | + paginator = Paginator(threads, 16) | ||
64 | + try: | ||
65 | + page = int(request.GET.get('p', '1')) | ||
66 | + except ValueError: | ||
67 | + page = 1 | ||
68 | + threads = paginator.page(page) | ||
69 | + | ||
70 | + lists = MailingList.objects.all() | ||
71 | + | ||
72 | + template_data = { | ||
73 | + 'lists': lists, | ||
74 | + 'n_results': paginator.count, | ||
75 | + 'threads': threads, | ||
76 | + 'selected_list': selected_list, | ||
77 | + 'order_by': order_by, | ||
78 | + } | ||
79 | + return render_to_response('message-list.html', template_data, | ||
80 | + RequestContext(request)) |