Clean up several aspects of the models
Updated 6 months ago
| Christian Hammond | Reviewers | ||
| trunk | reviewboard | ||
| None | Review Board SVN | ||
Cleaned up some of the models by giving all relationship fields explicit related_name fields, rather than using Django's pre-generated defaults. This makes for more natural names and is something we'd want to do before extensions land later on. This also moves error types and the custom Manager in reviews to their own files.
All unit tests pass.
Diff revision 1 (Latest)
- /trunk/reviewboard/accounts/views.py: 2 changes [ 1 2 ]
- /trunk/reviewboard/contrib/db/db2wiki.py: 2 changes [ 1 2 ]
- /trunk/reviewboard/diffviewer/models.py: 6 changes [ 1 2 3 4 5 6 ]
- /trunk/reviewboard/diffviewer/templatetags/difftags.py: 2 changes [ 1 2 ]
- /trunk/reviewboard/reviews/datagrids.py: 10 changes [ 1 2 3 4 5 6 7 8 9 10 ]
- /trunk/reviewboard/reviews/email.py: 1 change [ 1 ]
- /trunk/reviewboard/reviews/errors.py: 1 change [ new content ]
- /trunk/reviewboard/reviews/forms.py: 4 changes [ 1 2 3 4 ]
- /trunk/reviewboard/reviews/managers.py: 1 change [ new content ]
- /trunk/reviewboard/reviews/models.py: 31 changes [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ]
- /trunk/reviewboard/reviews/views.py: 6 changes [ 1 2 3 4 5 6 ]
- /trunk/reviewboard/reviews/management/commands/index.py: 1 change [ 1 ]
- /trunk/reviewboard/reviews/templatetags/reviewtags.py: 5 changes [ 1 2 3 4 5 ]
- /trunk/reviewboard/scmtools/models.py: 1 change [ 1 ]
- /trunk/reviewboard/templates/diffviewer/view_diff.html: 2 changes [ 1 2 ]
- /trunk/reviewboard/templates/iphone/dashboard.html: 1 change [ 1 ]
- /trunk/reviewboard/templates/reviews/dashboard.html: 1 change [ 1 ]
- /trunk/reviewboard/templates/reviews/review_detail.html: 2 changes [ 1 2 ]
- /trunk/reviewboard/webapi/json.py: 9 changes [ 1 2 3 4 5 6 7 8 9 ]
- /trunk/reviewboard/webapi/tests.py: 13 changes [ 1 2 3 4 5 6 7 8 9 10 11 12 13 ]
| /trunk/reviewboard/accounts/views.py | |||
|---|---|---|---|
| Revision 1384 | New Change | ||
| ... | 34 lines hidden [Expand] | ||
| 35 | request.user.password = newpassword |
35 | request.user.password = newpassword |
| 36 | 36 | ||
| 37 | request.user.first_name = form.cleaned_data['first_name'] |
37 | request.user.first_name = form.cleaned_data['first_name'] |
| 38 | request.user.last_name = form.cleaned_data['last_name'] |
38 | request.user.last_name = form.cleaned_data['last_name'] |
| 39 | request.user.email = form.cleaned_data['email'] |
39 | request.user.email = form.cleaned_data['email'] |
| 40 | request.user.group_set = form.cleaned_data['groups'] |
40 | request.user.review_groups = form.cleaned_data['groups'] |
| 41 | request.user.save() |
41 | request.user.save() |
| 42 | 42 | ||
| 43 | profile.first_time_setup_done = True |
43 | profile.first_time_setup_done = True |
| 44 | profile.syntax_highlighting = \ |
44 | profile.syntax_highlighting = \ |
| 45 | form.cleaned_data['syntax_highlighting'] |
45 | form.cleaned_data['syntax_highlighting'] |
| ... | 6 lines hidden [Expand] | ||
| 52 | 'redirect_to': redirect_to, |
52 | 'redirect_to': redirect_to, |
| 53 | 'first_name': request.user.first_name, |
53 | 'first_name': request.user.first_name, |
| 54 | 'last_name': request.user.last_name, |
54 | 'last_name': request.user.last_name, |
| 55 | 'email': request.user.email, |
55 | 'email': request.user.email, |
| 56 | 'syntax_highlighting': profile.syntax_highlighting, |
56 | 'syntax_highlighting': profile.syntax_highlighting, |
| 57 | 'groups': [g.id for g in request.user.group_set.all()], |
57 | 'groups': [g.id for g in request.user.review_groups.all()], |
| 58 | }) |
58 | }) |
| 59 | 59 | ||
| 60 | return render_to_response(template_name, RequestContext(request, { |
60 | return render_to_response(template_name, RequestContext(request, { |
| 61 | 'form': form, |
61 | 'form': form, |
| 62 | 'settings': settings, |
62 | 'settings': settings, |
| 63 | 'must_configure': must_configure, |
63 | 'must_configure': must_configure, |
| 64 | })) |
64 | })) |
| /trunk/reviewboard/contrib/db/db2wiki.py | |||
|---|---|---|---|
| Revision 1384 | New Change | ||
| ... | 80 lines hidden [Expand] | ||
| 81 | ('target_groups', [g.name for g in o.target_groups.all()]), |
81 | ('target_groups', [g.name for g in o.target_groups.all()]), |
| 82 | ('target_people', [u.username for u in o.target_people.all()]), |
82 | ('target_people', [u.username for u in o.target_people.all()]), |
| 83 | ('bugs_closed', o.get_bug_list()), |
83 | ('bugs_closed', o.get_bug_list()), |
| 84 | ('public', o.public), |
84 | ('public', o.public), |
| 85 | ('status', o.status), |
85 | ('status', o.status), |
| 86 | ('diff', o.diffset_history.diffset_set.latest().name), |
86 | ('diff', o.diffset_history.diffsets.latest().name), |
| 87 | ('reviews', [(review.user.username, get_object_info(review)) |
87 | ('reviews', [(review.user.username, get_object_info(review)) |
| 88 | for review in o.review_set.all()]), |
88 | for review in o.reviews.all()]), |
| 89 | ] |
89 | ] |
| 90 | elif isinstance(o, Review): |
90 | elif isinstance(o, Review): |
| 91 | info = [ |
91 | info = [ |
| 92 | ('user', o.user.username), |
92 | ('user', o.user.username), |
| 93 | ] |
93 | ] |
| ... | 76 lines hidden [Expand] | ||
| /trunk/reviewboard/diffviewer/models.py | |||
|---|---|---|---|
| Revision 1384 | New Change | ||
| ... | 51 lines hidden [Expand] | ||
| 52 | name = models.CharField(_('name'), max_length=256, core=True) |
52 | name = models.CharField(_('name'), max_length=256, core=True) |
| 53 | revision = models.IntegerField(_("revision"), core=True) |
53 | revision = models.IntegerField(_("revision"), core=True) |
| 54 | timestamp = models.DateTimeField(_("timestamp"), default=datetime.now) |
54 | timestamp = models.DateTimeField(_("timestamp"), default=datetime.now) |
| 55 | history = models.ForeignKey('DiffSetHistory', null=True, core=True, |
55 | history = models.ForeignKey('DiffSetHistory', null=True, core=True, |
| 56 | raw_id_admin=True, |
56 | raw_id_admin=True, |
| 57 | related_name="diffsets", |
||
| 57 | verbose_name=_("diff set history")) |
58 | verbose_name=_("diff set history")) |
| 58 | repository = models.ForeignKey(Repository, verbose_name=_("repository")) |
59 | repository = models.ForeignKey(Repository, related_name="diffsets", |
| 60 | verbose_name=_("repository")) |
||
| 59 | diffcompat = models.IntegerField( |
61 | diffcompat = models.IntegerField( |
| 60 | _('differ compatibility version'), |
62 | _('differ compatibility version'), |
| 61 | default=0, |
63 | default=0, |
| 62 | help_text=_("The diff generator compatibility version to use. " |
64 | help_text=_("The diff generator compatibility version to use. " |
| 63 | "This can and should be ignored.")) |
65 | "This can and should be ignored.")) |
| ... | 5 lines hidden [Expand] | ||
| 69 | This will set an initial revision of 1 if this is the first diffset |
71 | This will set an initial revision of 1 if this is the first diffset |
| 70 | in the history, and will set it to on more than the most recent |
72 | in the history, and will set it to on more than the most recent |
| 71 | diffset otherwise. |
73 | diffset otherwise. |
| 72 | """ |
74 | """ |
| 73 | if self.revision == 0 and self.history != None: |
75 | if self.revision == 0 and self.history != None: |
| 74 | if self.history.diffset_set.count() == 0: |
76 | if self.history.diffsets.count() == 0: |
| 75 | # Start on revision 1. It's more human-grokable. |
77 | # Start on revision 1. It's more human-grokable. |
| 76 | self.revision = 1 |
78 | self.revision = 1 |
| 77 | else: |
79 | else: |
| 78 | self.revision = self.history.diffset_set.latest().revision + 1 |
80 | self.revision = self.history.diffsets.latest().revision + 1 |
| 79 | 81 | ||
| 80 | super(DiffSet, self).save() |
82 | super(DiffSet, self).save() |
| 81 | 83 | ||
| 82 | def __unicode__(self): |
84 | def __unicode__(self): |
| 83 | return u"[%s] %s r%s" % (self.id, self.name, self.revision) |
85 | return u"[%s] %s r%s" % (self.id, self.name, self.revision) |
| ... | 15 lines hidden [Expand] | ||
| 99 | """ |
101 | """ |
| 100 | name = models.CharField(_('name'), max_length=256) |
102 | name = models.CharField(_('name'), max_length=256) |
| 101 | timestamp = models.DateTimeField(_("timestamp"), default=datetime.now) |
103 | timestamp = models.DateTimeField(_("timestamp"), default=datetime.now) |
| 102 | 104 | ||
| 103 | def __unicode__(self): |
105 | def __unicode__(self): |
| 104 | return u'Diff Set History (%s revisions)' % (self.diffset_set.count()) |
106 | return u'Diff Set History (%s revisions)' % self.diffsets.count() |
| 105 | 107 | ||
| 106 | class Admin: |
108 | class Admin: |
| 107 | pass |
109 | pass |
| /trunk/reviewboard/diffviewer/templatetags/difftags.py | |||
|---|---|---|---|
| Revision 1384 | New Change | ||
| ... | 123 lines hidden [Expand] | ||
| 124 | """ |
124 | """ |
| 125 | Returns a list of revisions in the specified diffset history, indicating |
125 | Returns a list of revisions in the specified diffset history, indicating |
| 126 | which of the revisions is already selected, as determined by the current |
126 | which of the revisions is already selected, as determined by the current |
| 127 | diffset pair. |
127 | diffset pair. |
| 128 | """ |
128 | """ |
| 129 | for diffset in history.diffset_set.all(): |
129 | for diffset in history.diffsets.all(): |
| 130 | yield { |
130 | yield { |
| 131 | 'revision': diffset.revision, |
131 | 'revision': diffset.revision, |
| 132 | 'is_current': current_pair[0] == diffset and |
132 | 'is_current': current_pair[0] == diffset and |
| 133 | current_pair[1] == None |
133 | current_pair[1] == None |
| 134 | } |
134 | } |
| 135 | 135 | ||
| 136 | 136 | ||
| 137 | @register.filter |
137 | @register.filter |
| 138 | def interdiff_link_list(history, current_pair): |
138 | def interdiff_link_list(history, current_pair): |
| 139 | """ |
139 | """ |
| 140 | Returns a list of revisions in the specified diffset history based on |
140 | Returns a list of revisions in the specified diffset history based on |
| 141 | the passed interdiff pair. |
141 | the passed interdiff pair. |
| 142 | """ |
142 | """ |
| 143 | for diffset in history.diffset_set.all(): |
143 | for diffset in history.diffsets.all(): |
| 144 | if current_pair[0].revision < diffset.revision: |
144 | if current_pair[0].revision < diffset.revision: |
| 145 | path = "%s-%s" % (current_pair[0].revision, diffset.revision) |
145 | path = "%s-%s" % (current_pair[0].revision, diffset.revision) |
| 146 | else: |
146 | else: |
| 147 | path = "%s-%s" % (diffset.revision, current_pair[0].revision) |
147 | path = "%s-%s" % (diffset.revision, current_pair[0].revision) |
| 148 | 148 | ||
| ... | 96 lines hidden [Expand] | ||
| /trunk/reviewboard/reviews/datagrids.py | |||
|---|---|---|---|
| Revision 1384 | New Change | ||
| ... | 75 lines hidden [Expand] | ||
| 76 | 76 | ||
| 77 | def render_data(self, review_request): |
77 | def render_data(self, review_request): |
| 78 | user = self.datagrid.request.user |
78 | user = self.datagrid.request.user |
| 79 | image_url = None |
79 | image_url = None |
| 80 | image_alt = None |
80 | image_alt = None |
| 81 | reviews = review_request.review_set.filter(user=user) |
81 | reviews = review_request.reviews.filter(user=user) |
| 82 | 82 | ||
| 83 | if reviews.filter(public=False).count() > 0: |
83 | if reviews.filter(public=False).count() > 0: |
| 84 | # Remind about drafts over finished comments |
84 | # Remind about drafts over finished comments |
| 85 | image_url = self.image_url |
85 | image_url = self.image_url |
| 86 | image_alt = _("Comments drafted") |
86 | image_alt = _("Comments drafted") |
| ... | 46 lines hidden [Expand] | ||
| 133 | if not summary: |
133 | if not summary: |
| 134 | summary = ' <i>No Summary</i>' |
134 | summary = ' <i>No Summary</i>' |
| 135 | 135 | ||
| 136 | if review_request.submitter == self.datagrid.request.user: |
136 | if review_request.submitter == self.datagrid.request.user: |
| 137 | try: |
137 | try: |
| 138 | draft = review_request.reviewrequestdraft_set.get() |
138 | draft = review_request.draft.get() |
| 139 | summary = conditional_escape(draft.summary) |
||
| 139 | return "<span class=\"draftlabel\">[Draft]</span> " + \ |
140 | return "<span class=\"draftlabel\">[Draft]</span> " + \ |
| 140 | summary |
141 | summary |
| 141 | except ReviewRequestDraft.DoesNotExist: |
142 | except ReviewRequestDraft.DoesNotExist: |
| 142 | pass |
143 | pass |
| 143 | 144 | ||
| ... | 16 lines hidden [Expand] | ||
| 160 | """ |
161 | """ |
| 161 | def __init__(self, *args, **kwargs): |
162 | def __init__(self, *args, **kwargs): |
| 162 | Column.__init__(self, *args, **kwargs) |
163 | Column.__init__(self, *args, **kwargs) |
| 163 | 164 | ||
| 164 | def render_data(self, obj): |
165 | def render_data(self, obj): |
| 165 | return str(obj.reviewrequest_set.filter(public=True, |
166 | return str(getattr(obj, self.field_name).filter(public=True, |
| 166 | status='P').count()) |
167 | status='P').count()) |
| 167 | 168 | ||
| 168 | 169 | ||
| 169 | class ReviewCountColumn(Column): |
170 | class ReviewCountColumn(Column): |
| 170 | """ |
171 | """ |
| ... | 182 lines hidden [Expand] | ||
| 353 | A datagrid showing a list of submitters. |
354 | A datagrid showing a list of submitters. |
| 354 | """ |
355 | """ |
| 355 | username = Column(_("Username"), link=True, sortable=True) |
356 | username = Column(_("Username"), link=True, sortable=True) |
| 356 | fullname = Column(_("Full Name"), field_name="get_full_name", |
357 | fullname = Column(_("Full Name"), field_name="get_full_name", |
| 357 | link=True, expand=True) |
358 | link=True, expand=True) |
| 358 | pending_count = PendingCountColumn(_("Pending Reviews"), shrink=True) |
359 | pending_count = PendingCountColumn(_("Pending Reviews"), |
| 360 | field_name="directed_review_requests", |
||
| 361 | shrink=True) |
||
| 359 | 362 | ||
| 360 | def __init__(self, request): |
363 | def __init__(self, request): |
| 361 | DataGrid.__init__(self, request, User.objects.filter(is_active=True), |
364 | DataGrid.__init__(self, request, User.objects.filter(is_active=True), |
| 362 | _("All submitters")) |
365 | _("All submitters")) |
| 363 | self.default_sort = ["username"] |
366 | self.default_sort = ["username"] |
| 364 | self.profile_sort_field = 'sort_submitter_columns' |
367 | self.profile_sort_field = 'sort_submitter_columns' |
| 365 | self.profile_columns_field = 'submitter_columns' |
368 | self.profile_columns_field = 'submitter_columns' |
| 366 | self.default_columns = [ |
369 | self.default_columns = [ |
| 367 | "username", "fullname", "pending_reviews" |
370 | "username", "fullname", "pending_count" |
| 368 | ] |
371 | ] |
| 369 | 372 | ||
| 370 | @staticmethod |
373 | @staticmethod |
| 371 | def link_to_object(obj, value): |
374 | def link_to_object(obj, value): |
| 372 | return reverse("user", args=[obj.username]) |
375 | return reverse("user", args=[obj.username]) |
| ... | 5 lines hidden [Expand] | ||
| 378 | """ |
381 | """ |
| 379 | star = StarColumn() |
382 | star = StarColumn() |
| 380 | name = Column(_("Group ID"), link=True, sortable=True) |
383 | name = Column(_("Group ID"), link=True, sortable=True) |
| 381 | displayname = Column(_("Group Name"), field_name="display_name", |
384 | displayname = Column(_("Group Name"), field_name="display_name", |
| 382 | link=True, expand=True) |
385 | link=True, expand=True) |
| 383 | pending_count = PendingCountColumn(_("Pending Reviews"), shrink=True) |
386 | pending_count = PendingCountColumn(_("Pending Reviews"), |
| 387 | field_name="review_requests", |
||
| 388 | shrink=True) |
||
| 384 | 389 | ||
| 385 | def __init__(self, request, title=_("All groups")): |
390 | def __init__(self, request, title=_("All groups")): |
| 386 | DataGrid.__init__(self, request, Group.objects.all(), title) |
391 | DataGrid.__init__(self, request, Group.objects.all(), title) |
| 387 | self.profile_sort_field = 'sort_group_columns' |
392 | self.profile_sort_field = 'sort_group_columns' |
| 388 | self.profile_columns_field = 'group_columns' |
393 | self.profile_columns_field = 'group_columns' |
| 389 | self.default_sort = ["name"] |
394 | self.default_sort = ["name"] |
| 390 | self.default_columns = [ |
395 | self.default_columns = [ |
| 391 | "star", "name", "displayname", "pending_reviews" |
396 | "star", "name", "displayname", "pending_count" |
| 392 | ] |
397 | ] |
| 393 | 398 | ||
| 394 | 399 | ||
| 395 | class WatchedGroupDataGrid(GroupDataGrid): |
400 | class WatchedGroupDataGrid(GroupDataGrid): |
| 396 | """ |
401 | """ |
| ... | 10 lines hidden [Expand] | ||
| /trunk/reviewboard/reviews/email.py | |||
|---|---|---|---|
| Revision 1384 | New Change | ||
| ... | 112 lines hidden [Expand] | ||
| 113 | Returns a list of all people who have been involved in a discussion on |
113 | Returns a list of all people who have been involved in a discussion on |
| 114 | a review request. |
114 | a review request. |
| 115 | """ |
115 | """ |
| 116 | # See the comment in harvest_people_from_review for this list |
116 | # See the comment in harvest_people_from_review for this list |
| 117 | # comprehension. |
117 | # comprehension. |
| 118 | return [u for review in review_request.review_set.all() |
118 | return [u for review in review_request.reviews.all() |
| 119 | for u in harvest_people_from_review(review)] |
119 | for u in harvest_people_from_review(review)] |
| 120 | 120 | ||
| 121 | 121 | ||
| 122 | def mail_review_request(user, review_request, changes=None): |
122 | def mail_review_request(user, review_request, changes=None): |
| 123 | """Send an e-mail representing the supplied review request. |
123 | """Send an e-mail representing the supplied review request. |
| ... | 76 lines hidden [Expand] | ||
| /trunk/reviewboard/reviews/forms.py | |||
|---|---|---|---|
| Revision 1384 | New Change | ||
| 1 |
|
1 |
|
| 2 | 2 | ||
| 3 | from django import newforms as forms |
3 | from django import newforms as forms |
| 4 | from django.utils.translation import ugettext as _ |
4 | from django.utils.translation import ugettext as _ |
| 5 | from PIL import Image |
5 | from PIL import Image |
| 6 | 6 | ||
| 7 | from reviewboard.diffviewer.forms import UploadDiffForm, EmptyDiffError |
7 | from reviewboard.diffviewer.forms import UploadDiffForm, EmptyDiffError |
| 8 | from reviewboard.reviews.errors import ChangeNumberInUseError, \ |
||
| 9 | ChangeSetError, \ |
||
| 10 | OwnershipError |
||
| 8 | from reviewboard.reviews.models import ReviewRequest, \ |
11 | from reviewboard.reviews.models import ReviewRequest, \ |
| 9 | ReviewRequestDraft, Screenshot, \ |
12 | ReviewRequestDraft, Screenshot |
| 10 | ChangeNumberInUseError |
||
| 11 | from reviewboard.scmtools.models import Repository |
13 | from reviewboard.scmtools.models import Repository |
| 12 | 14 | ||
| 13 | 15 | ||
| 14 | class ChangeSetError(ValueError): |
||
| 15 | pass |
||
| 16 | |||
| 17 | |||
| 18 | class OwnershipError(ValueError): |
||
| 19 | pass |
||
| 20 | |||
| 21 | |||
| 22 | class NewReviewRequestForm(forms.Form): |
16 | class NewReviewRequestForm(forms.Form): |
| 23 | """ |
17 | """ |
| 24 | A form that handles creationg of new review requests. These take |
18 | A form that handles creationg of new review requests. These take |
| 25 | information on the diffs, the repository the diffs are against, and |
19 | information on the diffs, the repository the diffs are against, and |
| 26 | optionally a changelist number (for use in certain repository types |
20 | optionally a changelist number (for use in certain repository types |
| ... | 122 lines hidden [Expand] | ||