Commit 1e7861daedeaa731a40e293d6ab64ee7cf7dc5a6
1 parent
5dcd8f29
Exists in
master
and in
39 other branches
Separeted trac migration from colab
Showing
19 changed files
with
457 additions
and
438 deletions
Show diff stats
src/accounts/search_indexes.py
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | from haystack import indexes | 3 | from haystack import indexes |
4 | from django.db.models import Count | 4 | from django.db.models import Count |
5 | 5 | ||
6 | -from proxy.models import Revision, Ticket, Wiki | 6 | +from proxy.trac.models import Revision, Ticket, Wiki |
7 | from badger.utils import get_users_counters | 7 | from badger.utils import get_users_counters |
8 | from .models import User | 8 | from .models import User |
9 | 9 |
src/accounts/views.py
@@ -25,7 +25,7 @@ from haystack.query import SearchQuerySet | @@ -25,7 +25,7 @@ from haystack.query import SearchQuerySet | ||
25 | from super_archives.models import EmailAddress, Message | 25 | from super_archives.models import EmailAddress, Message |
26 | from super_archives.utils.email import send_email_lists | 26 | from super_archives.utils.email import send_email_lists |
27 | from search.utils import trans | 27 | from search.utils import trans |
28 | -from proxy.models import WikiCollabCount, TicketCollabCount | 28 | +from proxy.trac.models import WikiCollabCount, TicketCollabCount |
29 | from .forms import (UserCreationForm, ListsForm, UserUpdateForm, | 29 | from .forms import (UserCreationForm, ListsForm, UserUpdateForm, |
30 | ChangeXMPPPasswordForm) | 30 | ChangeXMPPPasswordForm) |
31 | from .errors import XMPPChangePwdException | 31 | from .errors import XMPPChangePwdException |
src/api/resources.py
@@ -7,7 +7,7 @@ from tastypie.constants import ALL_WITH_RELATIONS, ALL | @@ -7,7 +7,7 @@ from tastypie.constants import ALL_WITH_RELATIONS, ALL | ||
7 | from tastypie.resources import ModelResource | 7 | from tastypie.resources import ModelResource |
8 | 8 | ||
9 | from super_archives.models import Message, EmailAddress | 9 | from super_archives.models import Message, EmailAddress |
10 | -from proxy.models import Revision, Ticket, Wiki | 10 | +from proxy.trac.models import Revision, Ticket, Wiki |
11 | 11 | ||
12 | 12 | ||
13 | User = get_user_model() | 13 | User = get_user_model() |
src/badger/utils.py
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | 2 | ||
3 | from django.db.models import Count | 3 | from django.db.models import Count |
4 | 4 | ||
5 | -from proxy.models import (Revision, Ticket, Wiki, | 5 | +from proxy.trac.models import (Revision, Ticket, Wiki, |
6 | WikiCollabCount, TicketCollabCount) | 6 | WikiCollabCount, TicketCollabCount) |
7 | from accounts.models import User | 7 | from accounts.models import User |
8 | 8 |
src/colab/custom_settings.py
@@ -262,6 +262,9 @@ TRAC_ENABLED = False | @@ -262,6 +262,9 @@ TRAC_ENABLED = False | ||
262 | if TRAC_ENABLED: | 262 | if TRAC_ENABLED: |
263 | from trac_settings import * | 263 | from trac_settings import * |
264 | DATABASES['trac'] = TRAC_DATABASE | 264 | DATABASES['trac'] = TRAC_DATABASE |
265 | + INSTALLED_APPS = INSTALLED_APPS + ( | ||
266 | + 'proxy.trac', | ||
267 | + ) | ||
265 | 268 | ||
266 | 269 | ||
267 | ### Feedzilla (planet) | 270 | ### Feedzilla (planet) |
src/home/views.py
@@ -9,7 +9,7 @@ from django.http import HttpResponse, Http404 | @@ -9,7 +9,7 @@ from django.http import HttpResponse, Http404 | ||
9 | from search.utils import trans | 9 | from search.utils import trans |
10 | from haystack.query import SearchQuerySet | 10 | from haystack.query import SearchQuerySet |
11 | 11 | ||
12 | -from proxy.models import WikiCollabCount, TicketCollabCount | 12 | +from proxy.trac.models import WikiCollabCount, TicketCollabCount |
13 | from super_archives.models import Thread | 13 | from super_archives.models import Thread |
14 | 14 | ||
15 | 15 | ||
@@ -28,13 +28,15 @@ def index(request): | @@ -28,13 +28,15 @@ def index(request): | ||
28 | type=type, | 28 | type=type, |
29 | ).count() | 29 | ).count() |
30 | 30 | ||
31 | - count_types['ticket'] = sum([ | ||
32 | - ticket.count for ticket in TicketCollabCount.objects.all() | ||
33 | - ]) | 31 | + if settings.TRAC_ENABLED: |
32 | + count_types['ticket'] = sum([ | ||
33 | + ticket.count for ticket in TicketCollabCount.objects.all() | ||
34 | + ]) | ||
34 | 35 | ||
35 | - count_types['wiki'] = sum([ | ||
36 | - wiki.count for wiki in WikiCollabCount.objects.all() | ||
37 | - ]) | 36 | + count_types['wiki'] = sum([ |
37 | + wiki.count for wiki in WikiCollabCount.objects.all() | ||
38 | + ]) | ||
39 | + | ||
38 | cache.set('home_chart', count_types) | 40 | cache.set('home_chart', count_types) |
39 | 41 | ||
40 | for key in count_types.keys(): | 42 | for key in count_types.keys(): |
src/proxy/migrations/0001_initial.py
@@ -1,248 +0,0 @@ | @@ -1,248 +0,0 @@ | ||
1 | -# -*- coding: utf-8 -*- | ||
2 | -import datetime | ||
3 | -from django.db import connections | ||
4 | -from south.db import db | ||
5 | -from south.v2 import SchemaMigration | ||
6 | -from django.db import models | ||
7 | - | ||
8 | - | ||
9 | -class Migration(SchemaMigration): | ||
10 | - | ||
11 | - def forwards(self, orm): | ||
12 | - connection = connections['trac'] | ||
13 | - | ||
14 | - cursor = connection.cursor() | ||
15 | - cursor.execute(''' | ||
16 | - CREATE OR REPLACE VIEW wiki_view AS SELECT | ||
17 | - wiki.name AS name, | ||
18 | - (SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name | ||
19 | - AND wiki2.version = MAX(wiki.version)) AS wiki_text, | ||
20 | - (SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name | ||
21 | - AND wiki3.version = 1) AS author, | ||
22 | - string_agg(DISTINCT wiki.author, ', ') AS collaborators, | ||
23 | - TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS created, | ||
24 | - TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS modified | ||
25 | - FROM wiki | ||
26 | - GROUP BY wiki.name; | ||
27 | - | ||
28 | - CREATE OR REPLACE VIEW ticket_view AS SELECT | ||
29 | - ticket.id AS id, | ||
30 | - ticket.summary as summary, | ||
31 | - ticket.description as description, | ||
32 | - ticket.milestone as milestone, | ||
33 | - ticket.priority as priority, | ||
34 | - ticket.component as component, | ||
35 | - ticket.version as version, | ||
36 | - ticket.severity as severity, | ||
37 | - ticket.reporter as reporter, | ||
38 | - ticket.reporter as author, | ||
39 | - ticket.status as status, | ||
40 | - ticket.keywords as keywords, | ||
41 | - (SELECT | ||
42 | - string_agg(DISTINCT ticket_change.author, ', ') | ||
43 | - FROM ticket_change WHERE ticket_change.ticket = ticket.id | ||
44 | - GROUP BY ticket_change.ticket) as collaborators, | ||
45 | - TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created, | ||
46 | - TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified | ||
47 | - FROM ticket; | ||
48 | - | ||
49 | - CREATE OR REPLACE VIEW revision_view AS SELECT | ||
50 | - revision.rev, | ||
51 | - revision.author, | ||
52 | - revision.message, | ||
53 | - repository.value AS repository_name, | ||
54 | - TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created | ||
55 | - FROM revision | ||
56 | - INNER JOIN repository ON( | ||
57 | - repository.id = revision.repos | ||
58 | - AND repository.name = 'name' | ||
59 | - AND repository.value != '' | ||
60 | - ); | ||
61 | - ''') | ||
62 | - cursor.execute(''' | ||
63 | -CREATE OR REPLACE VIEW revision_view AS SELECT | ||
64 | -revision.rev, | ||
65 | -revision.author, | ||
66 | -revision.message, | ||
67 | -repository.value AS repository_name, | ||
68 | -TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created, | ||
69 | -CONCAT(revision.repos, '-', revision.rev) AS key | ||
70 | -FROM revision | ||
71 | -INNER JOIN repository ON( | ||
72 | -repository.id = revision.repos | ||
73 | -AND repository.name = 'name' | ||
74 | -AND repository.value != '' | ||
75 | -); | ||
76 | -''') | ||
77 | - cursor.execute(''' | ||
78 | -CREATE OR REPLACE VIEW attachment_view AS SELECT | ||
79 | -CONCAT(attachment.type, '/' , attachment.id, '/', attachment.filename) AS url, | ||
80 | -attachment.type AS used_by, | ||
81 | -attachment.filename AS filename, | ||
82 | -attachment.id as attach_id, | ||
83 | -(SELECT LOWER(SUBSTRING(attachment.filename FROM '\.(\w+)$'))) AS mimetype, | ||
84 | -attachment.author AS author, | ||
85 | -attachment.description AS description, | ||
86 | -attachment.size AS size, | ||
87 | -TIMESTAMP WITH TIME ZONE 'epoch' + (attachment.time/1000000)* INTERVAL '1s' AS created | ||
88 | -FROM attachment; | ||
89 | -''') | ||
90 | - cursor.execute(''' | ||
91 | -CREATE OR REPLACE VIEW wiki_view AS SELECT | ||
92 | -wiki.name AS name, | ||
93 | -(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name | ||
94 | -AND wiki2.version = MAX(wiki.version)) AS wiki_text, | ||
95 | -(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name | ||
96 | -AND wiki3.version = 1) AS author, | ||
97 | -string_agg(DISTINCT wiki.author, ', ') AS collaborators, | ||
98 | -TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created, | ||
99 | -TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified | ||
100 | -FROM wiki | ||
101 | -GROUP BY wiki.name; | ||
102 | -''') | ||
103 | - cursor.execute(''' | ||
104 | -CREATE OR REPLACE VIEW wiki_view AS SELECT | ||
105 | -wiki.name AS name, | ||
106 | -(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name | ||
107 | -AND wiki2.version = MAX(wiki.version)) AS wiki_text, | ||
108 | -(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name | ||
109 | -AND wiki3.version = 1) AS author, | ||
110 | -string_agg(DISTINCT wiki.author, ', ') AS collaborators, | ||
111 | -TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created, | ||
112 | -TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified, | ||
113 | -(SELECT wiki4.author FROM wiki AS wiki4 WHERE wiki4.name = wiki.name | ||
114 | -AND wiki4.version = MAX(wiki.version)) AS modified_by | ||
115 | -FROM wiki | ||
116 | -GROUP BY wiki.name; | ||
117 | - | ||
118 | -CREATE OR REPLACE VIEW ticket_view AS SELECT | ||
119 | -ticket.id AS id, | ||
120 | -ticket.summary as summary, | ||
121 | -ticket.description as description, | ||
122 | -ticket.milestone as milestone, | ||
123 | -ticket.priority as priority, | ||
124 | -ticket.component as component, | ||
125 | -ticket.version as version, | ||
126 | -ticket.severity as severity, | ||
127 | -ticket.reporter as reporter, | ||
128 | -ticket.reporter as author, | ||
129 | -ticket.status as status, | ||
130 | -ticket.keywords as keywords, | ||
131 | -(SELECT | ||
132 | -string_agg(DISTINCT ticket_change.author, ', ') | ||
133 | -FROM ticket_change WHERE ticket_change.ticket = ticket.id | ||
134 | -GROUP BY ticket_change.ticket) as collaborators, | ||
135 | -TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created, | ||
136 | -TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified, | ||
137 | -(SELECT | ||
138 | -ticket_change.author | ||
139 | -FROM ticket_change | ||
140 | -WHERE ticket_change.ticket = ticket.id | ||
141 | -AND ticket_change.time = ticket.changetime | ||
142 | -LIMIT 1 | ||
143 | -) AS modified_by | ||
144 | -FROM ticket; | ||
145 | -''') | ||
146 | - cursor.execute(''' | ||
147 | -CREATE OR REPLACE VIEW ticket_collab_count_view AS | ||
148 | -SELECT | ||
149 | -COALESCE (t1.author, t2.author) as author, | ||
150 | -(COALESCE(t1.count, 0) + COALESCE(t2.count, 0)) as count | ||
151 | -FROM | ||
152 | -(SELECT author, count(*) as count | ||
153 | -FROM ticket_change | ||
154 | -GROUP BY author | ||
155 | -ORDER BY author | ||
156 | -) AS t1 | ||
157 | -FULL OUTER JOIN | ||
158 | -(SELECT reporter as author, count(*) as count | ||
159 | -FROM ticket | ||
160 | -GROUP BY reporter | ||
161 | -ORDER BY reporter | ||
162 | -) AS t2 | ||
163 | -ON t1.author = t2.author; | ||
164 | - | ||
165 | -CREATE OR REPLACE VIEW wiki_collab_count_view AS | ||
166 | -SELECT author, count(*) from wiki GROUP BY author; | ||
167 | -''') | ||
168 | - | ||
169 | - pass | ||
170 | - | ||
171 | - def backwards(self, orm): | ||
172 | - connection = connections['trac'] | ||
173 | - | ||
174 | - cursor = connection.cursor() | ||
175 | - cursor.execute(''' | ||
176 | -DROP VIEW IF EXISTS revision_view; | ||
177 | -DROP VIEW IF EXISTS ticket_view; | ||
178 | -DROP VIEW IF EXISTS wiki_view; | ||
179 | -''') | ||
180 | - cursor.execute('DROP VIEW IF EXISTS attachment_view;') | ||
181 | - | ||
182 | - pass | ||
183 | - | ||
184 | - models = { | ||
185 | - u'proxy.attachment': { | ||
186 | - 'Meta': {'object_name': 'Attachment', 'db_table': "'attachment_view'", 'managed': 'False'}, | ||
187 | - 'attach_id': ('django.db.models.fields.TextField', [], {}), | ||
188 | - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
189 | - 'created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}), | ||
190 | - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
191 | - 'filename': ('django.db.models.fields.TextField', [], {}), | ||
192 | - 'mimetype': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
193 | - 'size': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}), | ||
194 | - 'url': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), | ||
195 | - 'used_by': ('django.db.models.fields.TextField', [], {}) | ||
196 | - }, | ||
197 | - u'proxy.revision': { | ||
198 | - 'Meta': {'object_name': 'Revision', 'db_table': "'revision_view'", 'managed': 'False'}, | ||
199 | - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
200 | - 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), | ||
201 | - 'key': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), | ||
202 | - 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
203 | - 'repository_name': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
204 | - 'rev': ('django.db.models.fields.TextField', [], {'blank': 'True'}) | ||
205 | - }, | ||
206 | - u'proxy.ticket': { | ||
207 | - 'Meta': {'object_name': 'Ticket', 'db_table': "'ticket_view'", 'managed': 'False'}, | ||
208 | - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
209 | - 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
210 | - 'component': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
211 | - 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), | ||
212 | - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
213 | - 'id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}), | ||
214 | - 'keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
215 | - 'milestone': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
216 | - 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), | ||
217 | - 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
218 | - 'priority': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
219 | - 'reporter': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
220 | - 'severity': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
221 | - 'status': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
222 | - 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
223 | - 'version': ('django.db.models.fields.TextField', [], {'blank': 'True'}) | ||
224 | - }, | ||
225 | - u'proxy.ticketcollabcount': { | ||
226 | - 'Meta': {'object_name': 'TicketCollabCount', 'db_table': "'ticket_collab_count_view'", 'managed': 'False'}, | ||
227 | - 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), | ||
228 | - 'count': ('django.db.models.fields.IntegerField', [], {}) | ||
229 | - }, | ||
230 | - u'proxy.wiki': { | ||
231 | - 'Meta': {'object_name': 'Wiki', 'db_table': "'wiki_view'", 'managed': 'False'}, | ||
232 | - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
233 | - 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
234 | - 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), | ||
235 | - 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), | ||
236 | - 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
237 | - 'name': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), | ||
238 | - 'wiki_text': ('django.db.models.fields.TextField', [], {'blank': 'True'}) | ||
239 | - }, | ||
240 | - u'proxy.wikicollabcount': { | ||
241 | - 'Meta': {'object_name': 'WikiCollabCount', 'db_table': "'wiki_collab_count_view'", 'managed': 'False'}, | ||
242 | - 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), | ||
243 | - 'count': ('django.db.models.fields.IntegerField', [], {}) | ||
244 | - } | ||
245 | - } | ||
246 | - | ||
247 | - complete_apps = ['proxy'] | ||
248 | - symmetrical = True |
src/proxy/migrations/__init__.py
src/proxy/models.py
1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
2 | - | ||
3 | -import os | ||
4 | -import urllib2 | ||
5 | - | 2 | +from django.db import models |
6 | from django.conf import settings | 3 | from django.conf import settings |
7 | -from django.db import models, connections | ||
8 | -from django.db.models.signals import post_save | ||
9 | -from django.dispatch import receiver | ||
10 | - | ||
11 | -from accounts.models import User | ||
12 | -from hitcounter.models import HitCounterModelMixin | ||
13 | - | ||
14 | - | ||
15 | -class Attachment(models.Model, HitCounterModelMixin): | ||
16 | - url = models.TextField(primary_key=True) | ||
17 | - attach_id = models.TextField() | ||
18 | - used_by = models.TextField() | ||
19 | - filename = models.TextField() | ||
20 | - author = models.TextField(blank=True) | ||
21 | - description = models.TextField(blank=True) | ||
22 | - created = models.DateTimeField(blank=True) | ||
23 | - mimetype = models.TextField(blank=True) | ||
24 | - size = models.IntegerField(blank=True) | ||
25 | - | ||
26 | - class Meta: | ||
27 | - managed = False | ||
28 | - db_table = 'attachment_view' | ||
29 | - | ||
30 | - @property | ||
31 | - def filepath(self): | ||
32 | - return os.path.join( | ||
33 | - settings.ATTACHMENTS_FOLDER_PATH, | ||
34 | - self.used_by, | ||
35 | - self.attach_id, | ||
36 | - urllib2.quote(self.filename.encode('utf8')) | ||
37 | - ) | ||
38 | - | ||
39 | - def get_absolute_url(self): | ||
40 | - return u'/raw-attachment/{}'.format(self.url) | ||
41 | - | ||
42 | - def get_author(self): | ||
43 | - try: | ||
44 | - return User.objects.get(username=self.author) | ||
45 | - except User.DoesNotExist: | ||
46 | - return None | ||
47 | - | ||
48 | - | ||
49 | -class Revision(models.Model, HitCounterModelMixin): | ||
50 | - key = models.TextField(blank=True, primary_key=True) | ||
51 | - rev = models.TextField(blank=True) | ||
52 | - author = models.TextField(blank=True) | ||
53 | - message = models.TextField(blank=True) | ||
54 | - repository_name = models.TextField(blank=True) | ||
55 | - created = models.DateTimeField(blank=True, null=True) | ||
56 | - | ||
57 | - class Meta: | ||
58 | - managed = False | ||
59 | - db_table = 'revision_view' | ||
60 | - | ||
61 | - def get_absolute_url(self): | ||
62 | - return u'/changeset/{}/{}'.format(self.rev, self.repository_name) | ||
63 | - | ||
64 | - def get_author(self): | ||
65 | - try: | ||
66 | - return User.objects.get(username=self.author) | ||
67 | - except User.DoesNotExist: | ||
68 | - return None | ||
69 | - | ||
70 | -class Ticket(models.Model, HitCounterModelMixin): | ||
71 | - id = models.IntegerField(primary_key=True) | ||
72 | - summary = models.TextField(blank=True) | ||
73 | - description = models.TextField(blank=True) | ||
74 | - milestone = models.TextField(blank=True) | ||
75 | - priority = models.TextField(blank=True) | ||
76 | - component = models.TextField(blank=True) | ||
77 | - version = models.TextField(blank=True) | ||
78 | - severity = models.TextField(blank=True) | ||
79 | - reporter = models.TextField(blank=True) | ||
80 | - author = models.TextField(blank=True) | ||
81 | - status = models.TextField(blank=True) | ||
82 | - keywords = models.TextField(blank=True) | ||
83 | - collaborators = models.TextField(blank=True) | ||
84 | - created = models.DateTimeField(blank=True, null=True) | ||
85 | - modified = models.DateTimeField(blank=True, null=True) | ||
86 | - modified_by = models.TextField(blank=True) | ||
87 | - | ||
88 | - class Meta: | ||
89 | - managed = False | ||
90 | - db_table = 'ticket_view' | ||
91 | - | ||
92 | - def get_absolute_url(self): | ||
93 | - return u'/ticket/{}'.format(self.id) | ||
94 | - | ||
95 | - def get_author(self): | ||
96 | - try: | ||
97 | - return User.objects.get(username=self.author) | ||
98 | - except User.DoesNotExist: | ||
99 | - return None | ||
100 | - | ||
101 | - def get_modified_by(self): | ||
102 | - try: | ||
103 | - return User.objects.get(username=self.modified_by) | ||
104 | - except User.DoesNotExist: | ||
105 | - return None | ||
106 | - | ||
107 | - | ||
108 | -class Wiki(models.Model, HitCounterModelMixin): | ||
109 | - name = models.TextField(primary_key=True) | ||
110 | - wiki_text = models.TextField(blank=True) | ||
111 | - author = models.TextField(blank=True) | ||
112 | - collaborators = models.TextField(blank=True) | ||
113 | - created = models.DateTimeField(blank=True, null=True) | ||
114 | - modified = models.DateTimeField(blank=True, null=True) | ||
115 | - modified_by = models.TextField(blank=True) | ||
116 | - | ||
117 | - class Meta: | ||
118 | - managed = False | ||
119 | - db_table = 'wiki_view' | ||
120 | - | ||
121 | - def get_absolute_url(self): | ||
122 | - return u'/wiki/{}'.format(self.name) | ||
123 | - | ||
124 | - def get_author(self): | ||
125 | - try: | ||
126 | - return User.objects.get(username=self.author) | ||
127 | - except User.DoesNotExist: | ||
128 | - return None | ||
129 | - | ||
130 | - def get_modified_by(self): | ||
131 | - try: | ||
132 | - return User.objects.get(username=self.modified_by) | ||
133 | - except User.DoesNotExist: | ||
134 | - return None | ||
135 | - | ||
136 | - | ||
137 | -class WikiCollabCount(models.Model): | ||
138 | - author = models.TextField(primary_key=True) | ||
139 | - count = models.IntegerField() | ||
140 | - | ||
141 | - class Meta: | ||
142 | - managed = False | ||
143 | - db_table = 'wiki_collab_count_view' | ||
144 | - | ||
145 | - | ||
146 | -class TicketCollabCount(models.Model): | ||
147 | - author = models.TextField(primary_key=True) | ||
148 | - count = models.IntegerField() | ||
149 | - | ||
150 | - class Meta: | ||
151 | - managed = False | ||
152 | - db_table = 'ticket_collab_count_view' | ||
153 | - | ||
154 | - | ||
155 | -@receiver(post_save, sender=User) | ||
156 | -def change_session_attribute_email(sender, instance, **kwargs): | ||
157 | - cursor = connections['trac'].cursor() | ||
158 | - | ||
159 | - cursor.execute(("UPDATE session_attribute SET value=%s " | ||
160 | - "WHERE name='email' AND sid=%s"), | ||
161 | - [instance.email, instance.username]) | ||
162 | - cursor.execute(("UPDATE session_attribute SET value=%s " | ||
163 | - "WHERE name='name' AND sid=%s"), | ||
164 | - [instance.get_full_name(), instance.username]) | ||
165 | - | ||
166 | - cursor.execute(("INSERT INTO session_attribute " | ||
167 | - "(sid, authenticated, name, value) " | ||
168 | - "SELECT %s, '1', 'email', %s WHERE NOT EXISTS " | ||
169 | - "(SELECT 1 FROM session_attribute WHERE sid=%s " | ||
170 | - "AND name='email')"), | ||
171 | - [instance.username, instance.email, instance.username]) | ||
172 | 4 | ||
173 | - cursor.execute(("INSERT INTO session_attribute " | ||
174 | - "(sid, authenticated, name, value) " | ||
175 | - "SELECT %s, '1', 'name', %s WHERE NOT EXISTS " | ||
176 | - "(SELECT 1 FROM session_attribute WHERE sid=%s " | ||
177 | - "AND name='name')"), | ||
178 | - [instance.username, instance.get_full_name(), | ||
179 | - instance.username]) | 5 | +if settings.TRAC_ENABLED: |
6 | + import trac.trac.models |
src/proxy/search_indexes.py
@@ -9,7 +9,7 @@ from haystack import indexes | @@ -9,7 +9,7 @@ from haystack import indexes | ||
9 | from haystack.utils import log as logging | 9 | from haystack.utils import log as logging |
10 | 10 | ||
11 | from search.base_indexes import BaseIndex | 11 | from search.base_indexes import BaseIndex |
12 | -from .models import Attachment, Ticket, Wiki, Revision | 12 | +from trac.models import Attachment, Ticket, Wiki, Revision |
13 | 13 | ||
14 | 14 | ||
15 | logger = logging.getLogger('haystack') | 15 | logger = logging.getLogger('haystack') |
@@ -0,0 +1,248 @@ | @@ -0,0 +1,248 @@ | ||
1 | +# -*- coding: utf-8 -*- | ||
2 | +import datetime | ||
3 | +from django.db import connections | ||
4 | +from south.db import db | ||
5 | +from south.v2 import SchemaMigration | ||
6 | +from django.db import models | ||
7 | + | ||
8 | + | ||
9 | +class Migration(SchemaMigration): | ||
10 | + | ||
11 | + def forwards(self, orm): | ||
12 | + connection = connections['trac'] | ||
13 | + | ||
14 | + cursor = connection.cursor() | ||
15 | + cursor.execute(''' | ||
16 | + CREATE OR REPLACE VIEW wiki_view AS SELECT | ||
17 | + wiki.name AS name, | ||
18 | + (SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name | ||
19 | + AND wiki2.version = MAX(wiki.version)) AS wiki_text, | ||
20 | + (SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name | ||
21 | + AND wiki3.version = 1) AS author, | ||
22 | + string_agg(DISTINCT wiki.author, ', ') AS collaborators, | ||
23 | + TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS created, | ||
24 | + TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS modified | ||
25 | + FROM wiki | ||
26 | + GROUP BY wiki.name; | ||
27 | + | ||
28 | + CREATE OR REPLACE VIEW ticket_view AS SELECT | ||
29 | + ticket.id AS id, | ||
30 | + ticket.summary as summary, | ||
31 | + ticket.description as description, | ||
32 | + ticket.milestone as milestone, | ||
33 | + ticket.priority as priority, | ||
34 | + ticket.component as component, | ||
35 | + ticket.version as version, | ||
36 | + ticket.severity as severity, | ||
37 | + ticket.reporter as reporter, | ||
38 | + ticket.reporter as author, | ||
39 | + ticket.status as status, | ||
40 | + ticket.keywords as keywords, | ||
41 | + (SELECT | ||
42 | + string_agg(DISTINCT ticket_change.author, ', ') | ||
43 | + FROM ticket_change WHERE ticket_change.ticket = ticket.id | ||
44 | + GROUP BY ticket_change.ticket) as collaborators, | ||
45 | + TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created, | ||
46 | + TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified | ||
47 | + FROM ticket; | ||
48 | + | ||
49 | + CREATE OR REPLACE VIEW revision_view AS SELECT | ||
50 | + revision.rev, | ||
51 | + revision.author, | ||
52 | + revision.message, | ||
53 | + repository.value AS repository_name, | ||
54 | + TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created | ||
55 | + FROM revision | ||
56 | + INNER JOIN repository ON( | ||
57 | + repository.id = revision.repos | ||
58 | + AND repository.name = 'name' | ||
59 | + AND repository.value != '' | ||
60 | + ); | ||
61 | + ''') | ||
62 | + cursor.execute(''' | ||
63 | +CREATE OR REPLACE VIEW revision_view AS SELECT | ||
64 | +revision.rev, | ||
65 | +revision.author, | ||
66 | +revision.message, | ||
67 | +repository.value AS repository_name, | ||
68 | +TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created, | ||
69 | +CONCAT(revision.repos, '-', revision.rev) AS key | ||
70 | +FROM revision | ||
71 | +INNER JOIN repository ON( | ||
72 | +repository.id = revision.repos | ||
73 | +AND repository.name = 'name' | ||
74 | +AND repository.value != '' | ||
75 | +); | ||
76 | +''') | ||
77 | + cursor.execute(''' | ||
78 | +CREATE OR REPLACE VIEW attachment_view AS SELECT | ||
79 | +CONCAT(attachment.type, '/' , attachment.id, '/', attachment.filename) AS url, | ||
80 | +attachment.type AS used_by, | ||
81 | +attachment.filename AS filename, | ||
82 | +attachment.id as attach_id, | ||
83 | +(SELECT LOWER(SUBSTRING(attachment.filename FROM '\.(\w+)$'))) AS mimetype, | ||
84 | +attachment.author AS author, | ||
85 | +attachment.description AS description, | ||
86 | +attachment.size AS size, | ||
87 | +TIMESTAMP WITH TIME ZONE 'epoch' + (attachment.time/1000000)* INTERVAL '1s' AS created | ||
88 | +FROM attachment; | ||
89 | +''') | ||
90 | + cursor.execute(''' | ||
91 | +CREATE OR REPLACE VIEW wiki_view AS SELECT | ||
92 | +wiki.name AS name, | ||
93 | +(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name | ||
94 | +AND wiki2.version = MAX(wiki.version)) AS wiki_text, | ||
95 | +(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name | ||
96 | +AND wiki3.version = 1) AS author, | ||
97 | +string_agg(DISTINCT wiki.author, ', ') AS collaborators, | ||
98 | +TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created, | ||
99 | +TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified | ||
100 | +FROM wiki | ||
101 | +GROUP BY wiki.name; | ||
102 | +''') | ||
103 | + cursor.execute(''' | ||
104 | +CREATE OR REPLACE VIEW wiki_view AS SELECT | ||
105 | +wiki.name AS name, | ||
106 | +(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name | ||
107 | +AND wiki2.version = MAX(wiki.version)) AS wiki_text, | ||
108 | +(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name | ||
109 | +AND wiki3.version = 1) AS author, | ||
110 | +string_agg(DISTINCT wiki.author, ', ') AS collaborators, | ||
111 | +TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created, | ||
112 | +TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified, | ||
113 | +(SELECT wiki4.author FROM wiki AS wiki4 WHERE wiki4.name = wiki.name | ||
114 | +AND wiki4.version = MAX(wiki.version)) AS modified_by | ||
115 | +FROM wiki | ||
116 | +GROUP BY wiki.name; | ||
117 | + | ||
118 | +CREATE OR REPLACE VIEW ticket_view AS SELECT | ||
119 | +ticket.id AS id, | ||
120 | +ticket.summary as summary, | ||
121 | +ticket.description as description, | ||
122 | +ticket.milestone as milestone, | ||
123 | +ticket.priority as priority, | ||
124 | +ticket.component as component, | ||
125 | +ticket.version as version, | ||
126 | +ticket.severity as severity, | ||
127 | +ticket.reporter as reporter, | ||
128 | +ticket.reporter as author, | ||
129 | +ticket.status as status, | ||
130 | +ticket.keywords as keywords, | ||
131 | +(SELECT | ||
132 | +string_agg(DISTINCT ticket_change.author, ', ') | ||
133 | +FROM ticket_change WHERE ticket_change.ticket = ticket.id | ||
134 | +GROUP BY ticket_change.ticket) as collaborators, | ||
135 | +TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created, | ||
136 | +TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified, | ||
137 | +(SELECT | ||
138 | +ticket_change.author | ||
139 | +FROM ticket_change | ||
140 | +WHERE ticket_change.ticket = ticket.id | ||
141 | +AND ticket_change.time = ticket.changetime | ||
142 | +LIMIT 1 | ||
143 | +) AS modified_by | ||
144 | +FROM ticket; | ||
145 | +''') | ||
146 | + cursor.execute(''' | ||
147 | +CREATE OR REPLACE VIEW ticket_collab_count_view AS | ||
148 | +SELECT | ||
149 | +COALESCE (t1.author, t2.author) as author, | ||
150 | +(COALESCE(t1.count, 0) + COALESCE(t2.count, 0)) as count | ||
151 | +FROM | ||
152 | +(SELECT author, count(*) as count | ||
153 | +FROM ticket_change | ||
154 | +GROUP BY author | ||
155 | +ORDER BY author | ||
156 | +) AS t1 | ||
157 | +FULL OUTER JOIN | ||
158 | +(SELECT reporter as author, count(*) as count | ||
159 | +FROM ticket | ||
160 | +GROUP BY reporter | ||
161 | +ORDER BY reporter | ||
162 | +) AS t2 | ||
163 | +ON t1.author = t2.author; | ||
164 | + | ||
165 | +CREATE OR REPLACE VIEW wiki_collab_count_view AS | ||
166 | +SELECT author, count(*) from wiki GROUP BY author; | ||
167 | +''') | ||
168 | + | ||
169 | + pass | ||
170 | + | ||
171 | + def backwards(self, orm): | ||
172 | + connection = connections['trac'] | ||
173 | + | ||
174 | + cursor = connection.cursor() | ||
175 | + cursor.execute(''' | ||
176 | +DROP VIEW IF EXISTS revision_view; | ||
177 | +DROP VIEW IF EXISTS ticket_view; | ||
178 | +DROP VIEW IF EXISTS wiki_view; | ||
179 | +''') | ||
180 | + cursor.execute('DROP VIEW IF EXISTS attachment_view;') | ||
181 | + | ||
182 | + pass | ||
183 | + | ||
184 | + models = { | ||
185 | + u'proxy.attachment': { | ||
186 | + 'Meta': {'object_name': 'Attachment', 'db_table': "'attachment_view'", 'managed': 'False'}, | ||
187 | + 'attach_id': ('django.db.models.fields.TextField', [], {}), | ||
188 | + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
189 | + 'created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}), | ||
190 | + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
191 | + 'filename': ('django.db.models.fields.TextField', [], {}), | ||
192 | + 'mimetype': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
193 | + 'size': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}), | ||
194 | + 'url': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), | ||
195 | + 'used_by': ('django.db.models.fields.TextField', [], {}) | ||
196 | + }, | ||
197 | + u'proxy.revision': { | ||
198 | + 'Meta': {'object_name': 'Revision', 'db_table': "'revision_view'", 'managed': 'False'}, | ||
199 | + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
200 | + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), | ||
201 | + 'key': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), | ||
202 | + 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
203 | + 'repository_name': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
204 | + 'rev': ('django.db.models.fields.TextField', [], {'blank': 'True'}) | ||
205 | + }, | ||
206 | + u'proxy.ticket': { | ||
207 | + 'Meta': {'object_name': 'Ticket', 'db_table': "'ticket_view'", 'managed': 'False'}, | ||
208 | + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
209 | + 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
210 | + 'component': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
211 | + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), | ||
212 | + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
213 | + 'id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}), | ||
214 | + 'keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
215 | + 'milestone': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
216 | + 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), | ||
217 | + 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
218 | + 'priority': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
219 | + 'reporter': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
220 | + 'severity': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
221 | + 'status': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
222 | + 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
223 | + 'version': ('django.db.models.fields.TextField', [], {'blank': 'True'}) | ||
224 | + }, | ||
225 | + u'proxy.ticketcollabcount': { | ||
226 | + 'Meta': {'object_name': 'TicketCollabCount', 'db_table': "'ticket_collab_count_view'", 'managed': 'False'}, | ||
227 | + 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), | ||
228 | + 'count': ('django.db.models.fields.IntegerField', [], {}) | ||
229 | + }, | ||
230 | + u'proxy.wiki': { | ||
231 | + 'Meta': {'object_name': 'Wiki', 'db_table': "'wiki_view'", 'managed': 'False'}, | ||
232 | + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
233 | + 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
234 | + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), | ||
235 | + 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), | ||
236 | + 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
237 | + 'name': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), | ||
238 | + 'wiki_text': ('django.db.models.fields.TextField', [], {'blank': 'True'}) | ||
239 | + }, | ||
240 | + u'proxy.wikicollabcount': { | ||
241 | + 'Meta': {'object_name': 'WikiCollabCount', 'db_table': "'wiki_collab_count_view'", 'managed': 'False'}, | ||
242 | + 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}), | ||
243 | + 'count': ('django.db.models.fields.IntegerField', [], {}) | ||
244 | + } | ||
245 | + } | ||
246 | + | ||
247 | + complete_apps = ['proxy'] | ||
248 | + symmetrical = True |
@@ -0,0 +1,178 @@ | @@ -0,0 +1,178 @@ | ||
1 | +# -*- coding: utf-8 -*- | ||
2 | + | ||
3 | +import os | ||
4 | +import urllib2 | ||
5 | + | ||
6 | +from django.conf import settings | ||
7 | +from django.db import models, connections | ||
8 | +from django.db.models.signals import post_save | ||
9 | +from django.dispatch import receiver | ||
10 | + | ||
11 | +from accounts.models import User | ||
12 | +from hitcounter.models import HitCounterModelMixin | ||
13 | + | ||
14 | + | ||
15 | +class Attachment(models.Model, HitCounterModelMixin): | ||
16 | + url = models.TextField(primary_key=True) | ||
17 | + attach_id = models.TextField() | ||
18 | + used_by = models.TextField() | ||
19 | + filename = models.TextField() | ||
20 | + author = models.TextField(blank=True) | ||
21 | + description = models.TextField(blank=True) | ||
22 | + created = models.DateTimeField(blank=True) | ||
23 | + mimetype = models.TextField(blank=True) | ||
24 | + size = models.IntegerField(blank=True) | ||
25 | + | ||
26 | + class Meta: | ||
27 | + managed = False | ||
28 | + db_table = 'attachment_view' | ||
29 | + | ||
30 | + @property | ||
31 | + def filepath(self): | ||
32 | + return os.path.join( | ||
33 | + settings.ATTACHMENTS_FOLDER_PATH, | ||
34 | + self.used_by, | ||
35 | + self.attach_id, | ||
36 | + urllib2.quote(self.filename.encode('utf8')) | ||
37 | + ) | ||
38 | + | ||
39 | + def get_absolute_url(self): | ||
40 | + return u'/raw-attachment/{}'.format(self.url) | ||
41 | + | ||
42 | + def get_author(self): | ||
43 | + try: | ||
44 | + return User.objects.get(username=self.author) | ||
45 | + except User.DoesNotExist: | ||
46 | + return None | ||
47 | + | ||
48 | + | ||
49 | +class Revision(models.Model, HitCounterModelMixin): | ||
50 | + key = models.TextField(blank=True, primary_key=True) | ||
51 | + rev = models.TextField(blank=True) | ||
52 | + author = models.TextField(blank=True) | ||
53 | + message = models.TextField(blank=True) | ||
54 | + repository_name = models.TextField(blank=True) | ||
55 | + created = models.DateTimeField(blank=True, null=True) | ||
56 | + | ||
57 | + class Meta: | ||
58 | + managed = False | ||
59 | + db_table = 'revision_view' | ||
60 | + | ||
61 | + def get_absolute_url(self): | ||
62 | + return u'/changeset/{}/{}'.format(self.rev, self.repository_name) | ||
63 | + | ||
64 | + def get_author(self): | ||
65 | + try: | ||
66 | + return User.objects.get(username=self.author) | ||
67 | + except User.DoesNotExist: | ||
68 | + return None | ||
69 | + | ||
70 | +class Ticket(models.Model, HitCounterModelMixin): | ||
71 | + id = models.IntegerField(primary_key=True) | ||
72 | + summary = models.TextField(blank=True) | ||
73 | + description = models.TextField(blank=True) | ||
74 | + milestone = models.TextField(blank=True) | ||
75 | + priority = models.TextField(blank=True) | ||
76 | + component = models.TextField(blank=True) | ||
77 | + version = models.TextField(blank=True) | ||
78 | + severity = models.TextField(blank=True) | ||
79 | + reporter = models.TextField(blank=True) | ||
80 | + author = models.TextField(blank=True) | ||
81 | + status = models.TextField(blank=True) | ||
82 | + keywords = models.TextField(blank=True) | ||
83 | + collaborators = models.TextField(blank=True) | ||
84 | + created = models.DateTimeField(blank=True, null=True) | ||
85 | + modified = models.DateTimeField(blank=True, null=True) | ||
86 | + modified_by = models.TextField(blank=True) | ||
87 | + | ||
88 | + class Meta: | ||
89 | + managed = False | ||
90 | + db_table = 'ticket_view' | ||
91 | + | ||
92 | + def get_absolute_url(self): | ||
93 | + return u'/ticket/{}'.format(self.id) | ||
94 | + | ||
95 | + def get_author(self): | ||
96 | + try: | ||
97 | + return User.objects.get(username=self.author) | ||
98 | + except User.DoesNotExist: | ||
99 | + return None | ||
100 | + | ||
101 | + def get_modified_by(self): | ||
102 | + try: | ||
103 | + return User.objects.get(username=self.modified_by) | ||
104 | + except User.DoesNotExist: | ||
105 | + return None | ||
106 | + | ||
107 | +class Wiki(models.Model, HitCounterModelMixin): | ||
108 | + name = models.TextField(primary_key=True) | ||
109 | + wiki_text = models.TextField(blank=True) | ||
110 | + author = models.TextField(blank=True) | ||
111 | + collaborators = models.TextField(blank=True) | ||
112 | + created = models.DateTimeField(blank=True, null=True) | ||
113 | + modified = models.DateTimeField(blank=True, null=True) | ||
114 | + modified_by = models.TextField(blank=True) | ||
115 | + | ||
116 | + class Meta: | ||
117 | + managed = False | ||
118 | + db_table = 'wiki_view' | ||
119 | + | ||
120 | + def get_absolute_url(self): | ||
121 | + return u'/wiki/{}'.format(self.name) | ||
122 | + | ||
123 | + def get_author(self): | ||
124 | + try: | ||
125 | + return User.objects.get(username=self.author) | ||
126 | + except User.DoesNotExist: | ||
127 | + return None | ||
128 | + | ||
129 | + def get_modified_by(self): | ||
130 | + try: | ||
131 | + return User.objects.get(username=self.modified_by) | ||
132 | + except User.DoesNotExist: | ||
133 | + return None | ||
134 | + | ||
135 | + | ||
136 | +class WikiCollabCount(models.Model): | ||
137 | + author = models.TextField(primary_key=True) | ||
138 | + count = models.IntegerField() | ||
139 | + | ||
140 | + class Meta: | ||
141 | + managed = False | ||
142 | + db_table = 'wiki_collab_count_view' | ||
143 | + | ||
144 | + | ||
145 | +class TicketCollabCount(models.Model): | ||
146 | + author = models.TextField(primary_key=True) | ||
147 | + count = models.IntegerField() | ||
148 | + | ||
149 | + class Meta: | ||
150 | + managed = False | ||
151 | + db_table = 'ticket_collab_count_view' | ||
152 | + | ||
153 | + | ||
154 | +@receiver(post_save, sender=User) | ||
155 | +def change_session_attribute_email(sender, instance, **kwargs): | ||
156 | + cursor = connections['trac'].cursor() | ||
157 | + | ||
158 | + cursor.execute(("UPDATE session_attribute SET value=%s " | ||
159 | + "WHERE name='email' AND sid=%s"), | ||
160 | + [instance.email, instance.username]) | ||
161 | + cursor.execute(("UPDATE session_attribute SET value=%s " | ||
162 | + "WHERE name='name' AND sid=%s"), | ||
163 | + [instance.get_full_name(), instance.username]) | ||
164 | + | ||
165 | + cursor.execute(("INSERT INTO session_attribute " | ||
166 | + "(sid, authenticated, name, value) " | ||
167 | + "SELECT %s, '1', 'email', %s WHERE NOT EXISTS " | ||
168 | + "(SELECT 1 FROM session_attribute WHERE sid=%s " | ||
169 | + "AND name='email')"), | ||
170 | + [instance.username, instance.email, instance.username]) | ||
171 | + | ||
172 | + cursor.execute(("INSERT INTO session_attribute " | ||
173 | + "(sid, authenticated, name, value) " | ||
174 | + "SELECT %s, '1', 'name', %s WHERE NOT EXISTS " | ||
175 | + "(SELECT 1 FROM session_attribute WHERE sid=%s " | ||
176 | + "AND name='name')"), | ||
177 | + [instance.username, instance.get_full_name(), | ||
178 | + instance.username]) |
src/proxy/views.py
@@ -4,7 +4,7 @@ import os | @@ -4,7 +4,7 @@ import os | ||
4 | from django.conf import settings | 4 | from django.conf import settings |
5 | 5 | ||
6 | from revproxy.views import ProxyView | 6 | from revproxy.views import ProxyView |
7 | -from .models import Wiki, Ticket, Revision | 7 | +from trac.models import Wiki, Ticket, Revision |
8 | from hitcounter.views import HitCounterViewMixin | 8 | from hitcounter.views import HitCounterViewMixin |
9 | 9 | ||
10 | 10 |
src/search/views.py
@@ -5,7 +5,7 @@ from django.utils.translation import ugettext as _ | @@ -5,7 +5,7 @@ from django.utils.translation import ugettext as _ | ||
5 | 5 | ||
6 | from haystack.views import SearchView | 6 | from haystack.views import SearchView |
7 | 7 | ||
8 | -from proxy.models import Attachment | 8 | +from proxy.trac.models import Attachment |
9 | 9 | ||
10 | 10 | ||
11 | class ColabSearchView(SearchView): | 11 | class ColabSearchView(SearchView): |