Merge lp:~milo/linaro-ci-dashboard/linkify-next-loop into lp:linaro-ci-dashboard

Proposed by Milo Casagrande
Status: Merged
Merged at revision: 46
Proposed branch: lp:~milo/linaro-ci-dashboard/linkify-next-loop
Merge into: lp:linaro-ci-dashboard
Diff against target: 440 lines (+127/-77)
22 files modified
dashboard/frontend/android_build/models/android_loop.py (+12/-0)
dashboard/frontend/android_build/templates/android_loop_detail.html (+0/-7)
dashboard/frontend/android_build/tests/test_android_build_clientresponse.py (+1/-2)
dashboard/frontend/android_build/tests/test_android_build_views.py (+2/-0)
dashboard/frontend/android_build/views/android_loop_detail_view.py (+0/-2)
dashboard/frontend/android_textfield_loop/models/android_textfield_loop.py (+13/-0)
dashboard/frontend/android_textfield_loop/templates/android_textfield_loop_detail.html (+0/-7)
dashboard/frontend/android_textfield_loop/tests/test_android_textfield_clientresponse.py (+1/-2)
dashboard/frontend/android_textfield_loop/views/android_textfield_loop_detail_view.py (+1/-2)
dashboard/frontend/integration_loop/models/integration_loop.py (+13/-2)
dashboard/frontend/integration_loop/templates/integration_loop_detail.html (+0/-7)
dashboard/frontend/integration_loop/views/integration_loop_detail_view.py (+0/-2)
dashboard/frontend/kernel_build/models/kernel_loop.py (+12/-0)
dashboard/frontend/kernel_build/templates/kernel_loop_detail.html (+0/-7)
dashboard/frontend/kernel_build/tests/test_kernel_build_clientresponse.py (+1/-2)
dashboard/frontend/kernel_build/views/kernel_loop_detail_view.py (+0/-2)
dashboard/frontend/models/loop.py (+15/-2)
dashboard/frontend/models/textfield_loop.py (+1/-1)
dashboard/frontend/templates/loop_detail.html (+21/-2)
dashboard/frontend/templates/textfield_loop_detail.html (+2/-21)
dashboard/frontend/tests/test_clientresponse.py (+1/-2)
dashboard/frontend/views/loop_detail_view.py (+31/-5)
To merge this branch: bzr merge lp:~milo/linaro-ci-dashboard/linkify-next-loop
Reviewer Review Type Date Requested Status
Stevan Radaković Approve
Review via email: mp+123800@code.launchpad.net

Description of the change

Thsi is a tentative implementation of the final detail of the detail view.
At the moment it works only for the textfield-based views, but if the implementation looks good enough, it can be extended to the others too.

The code added is commented, so should be clear what has been done.
Basically, I resolved this using the @permalink annotation in the model, and retrieving the correct instance from the generic Loop model from the fields.

The same approach might be used also in the JavaScript that creates the link for the 'build' path in the detail view.

To post a comment you must log in.
45. By Milo Casagrande

Fixed problem with link.

Revision history for this message
Stevan Radaković (stevanr) wrote :

Hey Milo, looks nice!

Is there anyway we can move the get_next_loop model in the view tho?
Also, since we don't need any of the other permalink methods except detail and build, let's remove them.
And as we've spoken on IRC, let's remove everything related to the build_path now...

review: Needs Fixing
46. By Milo Casagrande

Added permaling method, simplified templates, removed not necessary ones.

47. By Milo Casagrande

Moved get_next_loop function in the view.

48. By Milo Casagrande

Fixed part of the tests.

Revision history for this message
Stevan Radaković (stevanr) wrote :

Looks good.
Thanks.
Approve +1

review: Approve
49. By Milo Casagrande

Fixed test failing, added note.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'dashboard/frontend/android_build/models/android_loop.py'
--- dashboard/frontend/android_build/models/android_loop.py 2012-09-11 14:34:59 +0000
+++ dashboard/frontend/android_build/models/android_loop.py 2012-09-12 14:34:19 +0000
@@ -139,3 +139,15 @@
139 exclude=exclude,139 exclude=exclude,
140 capitalize=capitalize,140 capitalize=capitalize,
141 upper=True)141 upper=True)
142
143 @models.permalink
144 def get_detail_url(self):
145 return 'AndroidLoopDetail', (), {'slug': self.name}
146
147 @models.permalink
148 def get_build_url(self):
149 return 'AndroidLoopBuild', (), {'slug': self.name}
150
151 @models.permalink
152 def get_update_url(self):
153 return 'AndroidLoopUpdate', (), {'slug': self.name}
142154
=== removed file 'dashboard/frontend/android_build/templates/android_loop_detail.html'
--- dashboard/frontend/android_build/templates/android_loop_detail.html 2012-09-07 15:36:09 +0000
+++ dashboard/frontend/android_build/templates/android_loop_detail.html 1970-01-01 00:00:00 +0000
@@ -1,7 +0,0 @@
1{% extends "loop_detail.html" %}
2{% block scripts %}
3{{ block.super }}
4$("#update_button").click(function() {
5 window.location.href = "{% url AndroidLoopUpdate loop_detail.name %}";
6});
7{% endblock scripts %}
80
=== modified file 'dashboard/frontend/android_build/tests/test_android_build_clientresponse.py'
--- dashboard/frontend/android_build/tests/test_android_build_clientresponse.py 2012-09-10 08:04:06 +0000
+++ dashboard/frontend/android_build/tests/test_android_build_clientresponse.py 2012-09-12 14:34:19 +0000
@@ -66,8 +66,7 @@
66 # Assert template names for detail page.66 # Assert template names for detail page.
67 template_names = [template.name for template in67 template_names = [template.name for template in
68 response.templates]68 response.templates]
69 self.assertEquals(template_names, ["android_loop_detail.html",69 self.assertEquals(template_names, ["loop_detail.html",
70 "loop_detail.html",
71 "base.html",70 "base.html",
72 "login.html",71 "login.html",
73 ])72 ])
7473
=== modified file 'dashboard/frontend/android_build/tests/test_android_build_views.py'
--- dashboard/frontend/android_build/tests/test_android_build_views.py 2012-09-10 08:04:06 +0000
+++ dashboard/frontend/android_build/tests/test_android_build_views.py 2012-09-12 14:34:19 +0000
@@ -33,6 +33,8 @@
33 self.mock_loop.loop_ptr.id = 033 self.mock_loop.loop_ptr.id = 0
34 self.mock_loop.loop_ptr.loopbuild_set = MagicMock()34 self.mock_loop.loop_ptr.loopbuild_set = MagicMock()
35 self.mock_loop.loop_ptr.loopbuild_set.all = MagicMock()35 self.mock_loop.loop_ptr.loopbuild_set.all = MagicMock()
36 self.mock_loop.next_loop = MagicMock()
37 self.mock_loop.next_loop.id = 1
3638
37 def test_create_view_get_context_data(self):39 def test_create_view_get_context_data(self):
38 android_loop_create_view = AndroidLoopCreateView()40 android_loop_create_view = AndroidLoopCreateView()
3941
=== modified file 'dashboard/frontend/android_build/views/android_loop_detail_view.py'
--- dashboard/frontend/android_build/views/android_loop_detail_view.py 2012-09-07 15:08:52 +0000
+++ dashboard/frontend/android_build/views/android_loop_detail_view.py 2012-09-12 14:34:19 +0000
@@ -22,5 +22,3 @@
22class AndroidLoopDetailView(LoopDetailView):22class AndroidLoopDetailView(LoopDetailView):
2323
24 model = AndroidLoop24 model = AndroidLoop
25 template_name = "android_loop_detail.html"
26 build_path = 'android'
2725
=== modified file 'dashboard/frontend/android_textfield_loop/models/android_textfield_loop.py'
--- dashboard/frontend/android_textfield_loop/models/android_textfield_loop.py 2012-09-07 12:49:10 +0000
+++ dashboard/frontend/android_textfield_loop/models/android_textfield_loop.py 2012-09-12 14:34:19 +0000
@@ -17,6 +17,7 @@
1717
18from frontend.models.textfield_loop import TextFieldLoop18from frontend.models.textfield_loop import TextFieldLoop
19from frontend.models.loop_reference import ANDROID_LOOP19from frontend.models.loop_reference import ANDROID_LOOP
20from django.db.models import permalink
2021
2122
22class AndroidTextFieldLoop(TextFieldLoop):23class AndroidTextFieldLoop(TextFieldLoop):
@@ -34,3 +35,15 @@
34 def can_chain_into():35 def can_chain_into():
35 chain = [ANDROID_LOOP]36 chain = [ANDROID_LOOP]
36 return chain37 return chain
38
39 @permalink
40 def get_detail_url(self):
41 return 'AndroidTextFieldLoopDetail', (), {'slug': self.name}
42
43 @permalink
44 def get_build_url(self):
45 return 'AndroidTextFieldLoopBuild', (), {'slug': self.name}
46
47 @permalink
48 def get_update_url(self):
49 return 'AndroidTextFieldLoopUpdate', (), {'slug': self.name}
3750
=== removed file 'dashboard/frontend/android_textfield_loop/templates/android_textfield_loop_detail.html'
--- dashboard/frontend/android_textfield_loop/templates/android_textfield_loop_detail.html 2012-09-10 13:30:37 +0000
+++ dashboard/frontend/android_textfield_loop/templates/android_textfield_loop_detail.html 1970-01-01 00:00:00 +0000
@@ -1,7 +0,0 @@
1{% extends "textfield_loop_detail.html" %}
2{% block scripts %}
3{{ block.super }}
4$("#update_button").click(function() {
5 window.location.href = "{% url AndroidTextFieldLoopUpdate loop_detail.name %}";
6});
7{% endblock scripts %}
80
=== modified file 'dashboard/frontend/android_textfield_loop/tests/test_android_textfield_clientresponse.py'
--- dashboard/frontend/android_textfield_loop/tests/test_android_textfield_clientresponse.py 2012-09-10 13:30:37 +0000
+++ dashboard/frontend/android_textfield_loop/tests/test_android_textfield_clientresponse.py 2012-09-12 14:34:19 +0000
@@ -65,8 +65,7 @@
65 template_names = [template.name for template in65 template_names = [template.name for template in
66 response.templates]66 response.templates]
67 self.assertEquals(template_names,67 self.assertEquals(template_names,
68 ["android_textfield_loop_detail.html",68 ["textfield_loop_detail.html",
69 "textfield_loop_detail.html",
70 "loop_detail.html",69 "loop_detail.html",
71 "base.html",70 "base.html",
72 "login.html",71 "login.html",
7372
=== modified file 'dashboard/frontend/android_textfield_loop/views/android_textfield_loop_detail_view.py'
--- dashboard/frontend/android_textfield_loop/views/android_textfield_loop_detail_view.py 2012-09-10 13:30:37 +0000
+++ dashboard/frontend/android_textfield_loop/views/android_textfield_loop_detail_view.py 2012-09-12 14:34:19 +0000
@@ -23,5 +23,4 @@
23class AndroidTextFieldLoopDetailView(LoopDetailView):23class AndroidTextFieldLoopDetailView(LoopDetailView):
2424
25 model = AndroidTextFieldLoop25 model = AndroidTextFieldLoop
26 template_name = 'android_textfield_loop_detail.html'26 template_name = 'textfield_loop_detail.html'
27 build_path = 'android-text'
2827
=== modified file 'dashboard/frontend/integration_loop/models/integration_loop.py'
--- dashboard/frontend/integration_loop/models/integration_loop.py 2012-08-31 13:34:41 +0000
+++ dashboard/frontend/integration_loop/models/integration_loop.py 2012-09-12 14:34:19 +0000
@@ -42,5 +42,16 @@
42 pass42 pass
4343
44 def __repr__(self):44 def __repr__(self):
45 return "IntegrationLoop(id=%d, branch=%s, ...)" % (self.id,45 return "IntegrationLoop(id=%d, branch=%s)" % (self.id, self.branch)
46 self.branch)46
47 @models.permalink
48 def get_detail_url(self):
49 return 'IntegrationLoopDetail', (), {'slug': self.name}
50
51 @models.permalink
52 def get_build_url(self):
53 return 'IntegrationLoopBuild', (), {'slug': self.name}
54
55 @models.permalink
56 def get_update_url(self):
57 return 'IntegrationLoopUpdate', (), {'slug': self.name}
4758
=== removed file 'dashboard/frontend/integration_loop/templates/integration_loop_detail.html'
--- dashboard/frontend/integration_loop/templates/integration_loop_detail.html 2012-09-07 15:40:57 +0000
+++ dashboard/frontend/integration_loop/templates/integration_loop_detail.html 1970-01-01 00:00:00 +0000
@@ -1,7 +0,0 @@
1{% extends "loop_detail.html" %}
2{% block scripts %}
3{{ block.super }}
4$("#update_button").click(function() {
5 window.location.href = "{% url IntegrationLoopUpdate loop_detail.name %}";
6});
7{% endblock scripts %}
80
=== modified file 'dashboard/frontend/integration_loop/views/integration_loop_detail_view.py'
--- dashboard/frontend/integration_loop/views/integration_loop_detail_view.py 2012-09-07 15:40:57 +0000
+++ dashboard/frontend/integration_loop/views/integration_loop_detail_view.py 2012-09-12 14:34:19 +0000
@@ -22,5 +22,3 @@
22class IntegrationLoopDetailView(LoopDetailView):22class IntegrationLoopDetailView(LoopDetailView):
2323
24 model = IntegrationLoop24 model = IntegrationLoop
25 template_name = "integration_loop_detail.html"
26 build_path = 'integration_loop'
2725
=== modified file 'dashboard/frontend/kernel_build/models/kernel_loop.py'
--- dashboard/frontend/kernel_build/models/kernel_loop.py 2012-08-30 21:49:13 +0000
+++ dashboard/frontend/kernel_build/models/kernel_loop.py 2012-09-12 14:34:19 +0000
@@ -123,3 +123,15 @@
123 except:123 except:
124 # TODO: Log error.124 # TODO: Log error.
125 pass125 pass
126
127 @models.permalink
128 def get_detail_url(self):
129 return 'KernelLoopDetail', (), {'slug': self.name}
130
131 @models.permalink
132 def get_build_url(self):
133 return 'KernelLoopBuild', (), {'slug': self.name}
134
135 @models.permalink
136 def get_update_url(self):
137 return 'KernelLoopUpdate', (), {'slug': self.name}
126138
=== removed file 'dashboard/frontend/kernel_build/templates/kernel_loop_detail.html'
--- dashboard/frontend/kernel_build/templates/kernel_loop_detail.html 2012-09-11 12:36:18 +0000
+++ dashboard/frontend/kernel_build/templates/kernel_loop_detail.html 1970-01-01 00:00:00 +0000
@@ -1,7 +0,0 @@
1{% extends "loop_detail.html" %}
2{% block scripts %}
3{{ block.super }}
4$("#update_button").click(function() {
5 window.location.href = "{% url KernelLoopUpdate loop_detail.name %}";
6});
7{% endblock scripts %}
80
=== modified file 'dashboard/frontend/kernel_build/tests/test_kernel_build_clientresponse.py'
--- dashboard/frontend/kernel_build/tests/test_kernel_build_clientresponse.py 2012-09-10 07:43:51 +0000
+++ dashboard/frontend/kernel_build/tests/test_kernel_build_clientresponse.py 2012-09-12 14:34:19 +0000
@@ -70,8 +70,7 @@
70 # Assert template names for detail page.70 # Assert template names for detail page.
71 template_names = [template.name for template in71 template_names = [template.name for template in
72 response.templates]72 response.templates]
73 self.assertEquals(template_names, ["kernel_loop_detail.html",73 self.assertEquals(template_names, ["loop_detail.html",
74 "loop_detail.html",
75 "base.html",74 "base.html",
76 "login.html",75 "login.html",
77 ])76 ])
7877
=== modified file 'dashboard/frontend/kernel_build/views/kernel_loop_detail_view.py'
--- dashboard/frontend/kernel_build/views/kernel_loop_detail_view.py 2012-09-07 15:43:36 +0000
+++ dashboard/frontend/kernel_build/views/kernel_loop_detail_view.py 2012-09-12 14:34:19 +0000
@@ -22,5 +22,3 @@
22class KernelLoopDetailView(LoopDetailView):22class KernelLoopDetailView(LoopDetailView):
2323
24 model = KernelLoop24 model = KernelLoop
25 template_name = 'kernel_loop_detail.html'
26 build_path = 'kernel'
2725
=== modified file 'dashboard/frontend/models/loop.py'
--- dashboard/frontend/models/loop.py 2012-09-11 14:34:59 +0000
+++ dashboard/frontend/models/loop.py 2012-09-12 14:34:19 +0000
@@ -39,7 +39,7 @@
39 next_loop = models.OneToOneField('self', blank=True, null=True,39 next_loop = models.OneToOneField('self', blank=True, null=True,
40 unique=True, on_delete=models.SET_NULL,40 unique=True, on_delete=models.SET_NULL,
41 related_name='previous_loop',41 related_name='previous_loop',
42 verbose_name='Next loop in chain')42 verbose_name='Next loop')
4343
44 def __init__(self, *args, **kwargs):44 def __init__(self, *args, **kwargs):
45 self.log = Logger.getClassLogger(self)45 self.log = Logger.getClassLogger(self)
@@ -237,7 +237,8 @@
237237
238 :return A list of tuples.238 :return A list of tuples.
239 """239 """
240 excluded_fields = ['name', 'server', 'type', 'id', 'loop_ptr']240 excluded_fields = ['name', 'server', 'type', 'id', 'loop_ptr',
241 'next_loop']
241 return self._get_wanted_fields(exclude=excluded_fields,242 return self._get_wanted_fields(exclude=excluded_fields,
242 verbose_name=True,243 verbose_name=True,
243 capitalize=True)244 capitalize=True)
@@ -259,3 +260,15 @@
259 This method should be overridden by subclasses.260 This method should be overridden by subclasses.
260 """261 """
261 return configuration262 return configuration
263
264 @models.permalink
265 def get_detail_url(self):
266 return ()
267
268 @models.permalink
269 def get_build_url(self):
270 return ()
271
272 @models.permalink
273 def get_update_url(self):
274 return ()
262275
=== modified file 'dashboard/frontend/models/textfield_loop.py'
--- dashboard/frontend/models/textfield_loop.py 2012-09-11 07:29:13 +0000
+++ dashboard/frontend/models/textfield_loop.py 2012-09-12 14:34:19 +0000
@@ -155,7 +155,7 @@
155 # and define a separate functions to retrieve the lines from the155 # and define a separate functions to retrieve the lines from the
156 # HTML template.156 # HTML template.
157 excluded_fields = ['name', 'server', 'type', 'id', 'loop_ptr',157 excluded_fields = ['name', 'server', 'type', 'id', 'loop_ptr',
158 'values']158 'values', 'next_loop']
159 return self._get_wanted_fields(exclude=excluded_fields,159 return self._get_wanted_fields(exclude=excluded_fields,
160 verbose_name=True,160 verbose_name=True,
161 capitalize=True)161 capitalize=True)
162162
=== modified file 'dashboard/frontend/templates/loop_detail.html'
--- dashboard/frontend/templates/loop_detail.html 2012-09-10 13:30:37 +0000
+++ dashboard/frontend/templates/loop_detail.html 2012-09-12 14:34:19 +0000
@@ -9,7 +9,23 @@
9 {% for name, value in loop_detail.get_details %}9 {% for name, value in loop_detail.get_details %}
10 <div>{{ name }}&#58;&nbsp;{{ value }}</div>10 <div>{{ name }}&#58;&nbsp;{{ value }}</div>
11 {% endfor %}11 {% endfor %}
12 {% for verbose_name, name, obj in next_loop %}
13 <div>
14 {% if name == None %}
15 {{ verbose_name }}&#58;&nbsp;{{ name }}
16 {% else %}
17 {{ verbose_name }}&#58;&nbsp;<a href="{{ obj.get_detail_url }}">{{ name }}</a>
18 {% endif %}
19 </div>
20 {% endfor %}
12 </div>21 </div>
22 {% block values %}
23 {% comment %}
24 This is used in the textfield detail views, to give a spece
25 to represent the key<>value values inserte by the user in a better
26 way.
27 {% endcomment %}
28 {% endblock values %}
13 <div>29 <div>
14 <button type="button" id="update_button">Update loop configuration</button>30 <button type="button" id="update_button">Update loop configuration</button>
15 </div>31 </div>
@@ -25,8 +41,11 @@
25{% endblock content %}41{% endblock content %}
26{% block scripts %}42{% block scripts %}
27$("#schedule_button").click(function() {43$("#schedule_button").click(function() {
28 $.get("{% if request.is_secure %}https{% else %}http{% endif %}://{{ request.get_host }}/{{ build_path }}/build/{{ loop_detail.name }}/", function(data) {44 $.get("{% if request.is_secure %}https{% else %}http{% endif %}://{{ request.get_host }}/{{ loop_detail.get_build_url }}", function(data) {
29 $(data).prependTo($("#builds"));45 $(data).prependTo($("#builds"));
30 });46 });
31});47});
32{% endblock scripts %}
33\ No newline at end of file48\ No newline at end of file
49$("#update_button").click(function() {
50 window.location.href = "{{ loop_detail.get_update_url }}";
51});
52{% endblock scripts %}
3453
=== modified file 'dashboard/frontend/templates/textfield_loop_detail.html'
--- dashboard/frontend/templates/textfield_loop_detail.html 2012-09-10 13:30:37 +0000
+++ dashboard/frontend/templates/textfield_loop_detail.html 2012-09-12 14:34:19 +0000
@@ -1,28 +1,9 @@
1{% extends "loop_detail.html" %}1{% extends "loop_detail.html" %}
2{% block content %}2{% block values %}
3 <div class="header"><h2>Loop {{ loop_detail.name }}</h2></div>
4 <div class="header"><h4>Details</h4></div>
5 <div>
6 {% for name, value in loop_detail.get_details %}
7 <div>{{ name }}&#58;&nbsp;{{ value }}</div>
8 {% endfor %}
9 </div>
10 <div class="header"><h4>Values</h4></div>3 <div class="header"><h4>Values</h4></div>
11 <div class="textfield">4 <div class="textfield">
12 {% for value in loop_detail.get_values %}5 {% for value in loop_detail.get_values %}
13 <div>{{ value }}</div>6 <div>{{ value }}</div>
14 {% endfor %}7 {% endfor %}
15 </div>8 </div>
16 <div>9{% endblock values %}
17 <button type="button" id="update_button">Update loop configuration</button>
18 </div>
19 <div class="header"><h4>Builds</h4></div>
20 <div id="builds">
21 {% for build in builds %}
22 {% include "build.html" %}
23 {% endfor %}
24 </div>
25 <div>
26 <button type="button" id="schedule_button">Schedule new build</button>
27 </div>
28{% endblock content %}
2910
=== modified file 'dashboard/frontend/tests/test_clientresponse.py'
--- dashboard/frontend/tests/test_clientresponse.py 2012-09-10 08:21:41 +0000
+++ dashboard/frontend/tests/test_clientresponse.py 2012-09-12 14:34:19 +0000
@@ -108,8 +108,7 @@
108 # Assert template names for detail page.108 # Assert template names for detail page.
109 template_names = [template.name for template in109 template_names = [template.name for template in
110 response.templates]110 response.templates]
111 self.assertEquals(template_names, ["integration_loop_detail.html",111 self.assertEquals(template_names, ["loop_detail.html",
112 "loop_detail.html",
113 "base.html",112 "base.html",
114 "login.html",113 "login.html",
115 ])114 ])
116115
=== modified file 'dashboard/frontend/views/loop_detail_view.py'
--- dashboard/frontend/views/loop_detail_view.py 2012-09-10 07:36:24 +0000
+++ dashboard/frontend/views/loop_detail_view.py 2012-09-12 14:34:19 +0000
@@ -20,6 +20,7 @@
20from django.utils.decorators import method_decorator20from django.utils.decorators import method_decorator
21from frontend.models.loop import Loop21from frontend.models.loop import Loop
2222
23
23class LoopDetailView(DetailView):24class LoopDetailView(DetailView):
2425
25 # These two fields should *never* be overridden.26 # These two fields should *never* be overridden.
@@ -28,19 +29,44 @@
28 # The following fields have to be overridden in each sub-class.29 # The following fields have to be overridden in each sub-class.
29 model = Loop30 model = Loop
30 template_name = 'loop_detail.html'31 template_name = 'loop_detail.html'
31 # This is necessary for each loop to define the URL path for the build
32 # view. This must be overridden.
33 build_path = 'loop'
3432
35 @method_decorator(login_required)33 @method_decorator(login_required)
36 def dispatch(self, *args, **kwargs):34 def dispatch(self, *args, **kwargs):
37 return super(LoopDetailView, self).dispatch(*args, **kwargs)35 return super(LoopDetailView, self).dispatch(*args, **kwargs)
3836
39 def get_context_data(self, **kwargs):37 def get_context_data(self, **kwargs):
40 '''Get the context data passed to template.'''38 """Get the context data passed to template."""
41 context = super(LoopDetailView, self).get_context_data(**kwargs)39 context = super(LoopDetailView, self).get_context_data(**kwargs)
42 loop_pointer = self.object.loop_ptr40 loop_pointer = self.object.loop_ptr
43 context['request'] = self.request41 context['request'] = self.request
44 context['builds'] = loop_pointer.loopbuild_set.all()42 context['builds'] = loop_pointer.loopbuild_set.all()
45 context['build_path'] = self.build_path43 context['next_loop'] = self._get_next_loop()
46 return context44 return context
45
46 def _get_next_loop(self):
47 """
48 Retrieves all the necessary information to visualize the next loop as
49 a link.
50
51 :return A list with a three-element tuple containing the verbose name
52 of the field, the name of the pointed loop, and the actual instance of
53 the pointed loop.
54 """
55 field = self.object._meta.get_field('next_loop')
56 pk = self.object.next_loop_id
57 verbose_name = field.verbose_name.capitalize()
58 # XXX changed to isinstance, since tests were failing: we need to
59 # mock Loop, not the model variable, in a better way in our tests.
60 if isinstance(pk, int):
61 # Get the pointer to the object we want to retrieve, and retrieve
62 # the actual instance. We can do this since all our loops inherits
63 # from the same base class (Loop), and we have the information
64 # about the loop type (in type). Django has a feature to retrieve
65 # the correct object using the lower-case version of the class
66 # name.
67 ptr = Loop.objects.get(pk=pk)
68 obj = getattr(ptr, ptr.type.lower())
69 other_loop = [(verbose_name, ptr.name, obj)]
70 else:
71 other_loop = [(verbose_name, None, None)]
72 return other_loop

Subscribers

People subscribed via source and target branches