Merge lp:~canonical-isd-hackers/ubuntu-webcatalog/useragent_778562 into lp:ubuntu-webcatalog
- useragent_778562
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Danny Tamez | ||||
Approved revision: | 26 | ||||
Merged at revision: | 26 | ||||
Proposed branch: | lp:~canonical-isd-hackers/ubuntu-webcatalog/useragent_778562 | ||||
Merge into: | lp:ubuntu-webcatalog | ||||
Diff against target: |
507 lines (+217/-60) 10 files modified
django_project/config/main.cfg (+1/-0) src/webcatalog/models.py (+5/-5) src/webcatalog/schema.py (+1/-0) src/webcatalog/templates/webcatalog/application_detail.html (+10/-1) src/webcatalog/templates/webcatalog/application_overview_snippet.html (+1/-1) src/webcatalog/tests/factory.py (+3/-3) src/webcatalog/tests/test_models.py (+3/-3) src/webcatalog/tests/test_views.py (+111/-34) src/webcatalog/urls.py (+5/-4) src/webcatalog/views.py (+77/-9) |
||||
To merge this branch: | bzr merge lp:~canonical-isd-hackers/ubuntu-webcatalog/useragent_778562 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
David Owen (community) | Approve | ||
Review via email: mp+65553@code.launchpad.net |
Commit message
Enhances the application details page to show more helpful messages based on the useragent of the request.
Description of the change
This branch adds support for the application details page to display more helpful messages. In particular, the useragent in the request is examined to determine the user's OS and distroseries. Based on this information the app details page will display alternative links to other distros or a link to the ubuntu download page if the OS detected is not Linux. At this point there is no way to actually determine the distro the user is running so a default guess is used (which is configured in the settings).
ISD Branch Mangler (isd-branches-mangler) wrote : | # |
Attempt to merge into lp:ubuntu-webcatalog failed due to conflicts:
text conflict in src/webcatalog/
text conflict in src/webcatalog/
text conflict in src/webcatalog/
text conflict in src/webcatalog/
text conflict in src/webcatalog/
Michael Nelson (michael.nelson) wrote : | # |
Hey Danny! I was just pulling this up to find out why it hadn't landed yet (argh, conflicts), but noticed that you're not grabbing the distroseries from the user-agent when present... just wondering why?
Here's a screenshot showing Ubuntu/11.04 for me with chromium:
http://
It won't be available in all browsers, but those that are patched by ubuntu should have it.
I really don't think we should be guessing at all, as it could provide a very confusing user experience. Either we know their distroseries and take advantage of that, or we don't and do some baseline functionality.
Michael Nelson (michael.nelson) wrote : | # |
> Here's a screenshot showing Ubuntu/11.04 for me with chromium:
> http://
>
> It won't be available in all browsers, but those that are patched by ubuntu
> should have it.
I just found bug 709125 which says that it'll no longer be supported in FF, but that ubufox package can add it for certain websites (as they have done for apt.ubuntu.com.
If we did ask them to also include (eventually) the web catalog, would it be SRUd to older series? Hrm.
- 26. By Danny Tamez
-
Merged trunk and resolved conflicts.
Preview Diff
1 | === modified file 'django_project/config/main.cfg' |
2 | --- django_project/config/main.cfg 2011-06-23 12:38:12 +0000 |
3 | +++ django_project/config/main.cfg 2011-06-28 15:06:35 +0000 |
4 | @@ -93,6 +93,7 @@ |
5 | serve_site_media = True |
6 | sca_api_url = https://sc.staging.ubuntu.com/api/2.0/ |
7 | disk_apt_cache_location = /tmp/webcat_cache |
8 | +default_distro = natty |
9 | |
10 | [google] |
11 | google_analytics_id = UA-1018242-24 |
12 | |
13 | === modified file 'src/webcatalog/models.py' |
14 | --- src/webcatalog/models.py 2011-06-23 14:20:52 +0000 |
15 | +++ src/webcatalog/models.py 2011-06-28 15:06:35 +0000 |
16 | @@ -62,7 +62,7 @@ |
17 | popcon = models.IntegerField() |
18 | channel = models.CharField(max_length=255, blank=True) |
19 | screenshot_url = models.URLField(blank=True, |
20 | - help_text="Only use this if it is other than the normal screenshot url.") |
21 | + help_text="Only use this if it is other than the normal screenshot url.") |
22 | mimetype = models.CharField(max_length=2048, blank=True) |
23 | architectures = models.CharField(max_length=255, blank=True) |
24 | keywords = models.CharField(max_length=255, blank=True) |
25 | @@ -73,6 +73,9 @@ |
26 | icon_name = models.CharField(max_length=255, blank=True) |
27 | icon = models.ImageField(upload_to='icons/%Y/%m', max_length=200, |
28 | null=True, blank=True) |
29 | + for_purchase = models.BooleanField(default=False) |
30 | + archive_id = models.CharField(max_length=64, null=True, |
31 | + db_index=True, blank=True, unique=True) |
32 | |
33 | # Other desktop fields used by s-c |
34 | # x-gnome-fullname |
35 | @@ -83,9 +86,6 @@ |
36 | # (using python-apt - as above we'll need access to info from different |
37 | # series etc.) |
38 | description = models.TextField(blank=True) |
39 | - for_purchase = models.BooleanField(default=False) |
40 | - archive_id = models.CharField(max_length=64, null=True, |
41 | - db_index=True, blank=True, unique=True) |
42 | |
43 | def __unicode__(self): |
44 | return u"{0} ({1})".format(self.name, self.package_name) |
45 | @@ -127,7 +127,7 @@ |
46 | else: |
47 | crumbs = [{'name': 'Get Software', 'url': reverse('wc-index')}] |
48 | crumbs.append({'name': self.name, 'url': reverse('wc-package-detail', |
49 | - args=[self.package_name])}) |
50 | + args=[self.distroseries.code_name, self.package_name])}) |
51 | return crumbs |
52 | |
53 | class Department(models.Model): |
54 | |
55 | === modified file 'src/webcatalog/schema.py' |
56 | --- src/webcatalog/schema.py 2011-06-27 12:07:30 +0000 |
57 | +++ src/webcatalog/schema.py 2011-06-28 15:06:35 +0000 |
58 | @@ -47,6 +47,7 @@ |
59 | webcatalog.serve_site_media = BoolConfigOption(default=True) |
60 | webcatalog.sca_api_url = StringConfigOption() |
61 | webcatalog.disk_apt_cache_location = StringConfigOption() |
62 | + webcatalog.default_distro = StringConfigOption() |
63 | webcatalog.page_batch_size = IntConfigOption(default=20) |
64 | |
65 | google = ConfigSection() |
66 | |
67 | === modified file 'src/webcatalog/templates/webcatalog/application_detail.html' |
68 | --- src/webcatalog/templates/webcatalog/application_detail.html 2011-06-23 14:20:52 +0000 |
69 | +++ src/webcatalog/templates/webcatalog/application_detail.html 2011-06-28 15:06:35 +0000 |
70 | @@ -27,7 +27,16 @@ |
71 | <img src="http://screenshots.ubuntu.com/thumbnail-with-version/{{ application.package_name }}/ignored" /> |
72 | </div> |
73 | <p>{{ application.description }}</p> |
74 | - <a href="apt://{{ application.package_name }}" class="awesome">{%if application.for_purchase %}Install{% else %}Download{% endif %} {{ application.name }}</a> |
75 | + {% if hide_button %} |
76 | + {{ message_text }} |
77 | + {% else %} |
78 | + <a href="apt://{{ application.package_name }}" class="awesome">{{ button_text }} {{ application.name }}</a> |
79 | + {% endif %} |
80 | + {% if links %} |
81 | + {% for text, link in links %} |
82 | + <br><a href="{{link}}" class="awesome">{{ text }}</a> |
83 | + {% endfor %} |
84 | + {% endif %} |
85 | </div> |
86 | <div class="license"> |
87 | <table> |
88 | |
89 | === modified file 'src/webcatalog/templates/webcatalog/application_overview_snippet.html' |
90 | --- src/webcatalog/templates/webcatalog/application_overview_snippet.html 2011-06-23 14:20:52 +0000 |
91 | +++ src/webcatalog/templates/webcatalog/application_overview_snippet.html 2011-06-28 15:06:35 +0000 |
92 | @@ -5,7 +5,7 @@ |
93 | <img src="{{ STATIC_URL }}images/noicon_32.png"/> |
94 | {% endif %} |
95 | <h3> |
96 | - <a href="{% url wc-package-detail app.package_name %}">{{ app.name }}</a> |
97 | + <a href="{% url wc-package-detail app.distroseries.code_name app.package_name %}">{{ app.name }}</a> |
98 | </h3> |
99 | <p>{{ app.comment }}</p> |
100 | </div> |
101 | |
102 | === modified file 'src/webcatalog/tests/factory.py' |
103 | --- src/webcatalog/tests/factory.py 2011-05-06 09:46:17 +0000 |
104 | +++ src/webcatalog/tests/factory.py 2011-06-28 15:06:35 +0000 |
105 | @@ -24,7 +24,7 @@ |
106 | import os |
107 | from itertools import count |
108 | |
109 | -from django.core.files.images import ImageFile |
110 | +from django.contrib.auth.models import User |
111 | from django.test import TestCase |
112 | |
113 | from webcatalog.models import ( |
114 | @@ -76,7 +76,7 @@ |
115 | |
116 | def make_application(self, package_name=None, name=None, |
117 | comment=None, description=None, icon_name='', icon=None, |
118 | - distroseries=None): |
119 | + distroseries=None, arch='i686'): |
120 | if name is None: |
121 | name = self.get_unique_string(prefix='Readable Name') |
122 | if package_name is None: |
123 | @@ -91,7 +91,7 @@ |
124 | return Application.objects.create( |
125 | package_name=package_name, name=name, comment=comment, |
126 | description=description, popcon=999, icon=icon, |
127 | - icon_name=icon_name, distroseries=distroseries) |
128 | + icon_name=icon_name, distroseries=distroseries, architectures=arch) |
129 | |
130 | def make_department(self, name, parent=None): |
131 | return Department.objects.create(name=name, parent=parent) |
132 | |
133 | === modified file 'src/webcatalog/tests/test_models.py' |
134 | --- src/webcatalog/tests/test_models.py 2011-06-23 14:49:53 +0000 |
135 | +++ src/webcatalog/tests/test_models.py 2011-06-28 15:06:35 +0000 |
136 | @@ -65,7 +65,7 @@ |
137 | self.assertEquals([], list(app.departments.all())) |
138 | expected = [{'name': 'Get Software', 'url': reverse('wc-index')}, |
139 | {'name': app.name, 'url': reverse('wc-package-detail', |
140 | - args=[app.package_name])}] |
141 | + args=[app.distroseries.code_name, app.package_name])}] |
142 | |
143 | self.assertEquals(expected, app.crumbs()) |
144 | |
145 | @@ -78,7 +78,7 @@ |
146 | {'name': dept.name, 'url': reverse('wc-department', |
147 | args=[dept.id])}, |
148 | {'name': app.name, 'url': reverse('wc-package-detail', |
149 | - args=[app.package_name])}] |
150 | + args=[app.distroseries.code_name, app.package_name])}] |
151 | |
152 | self.assertEquals(expected, app.crumbs()) |
153 | |
154 | @@ -93,7 +93,7 @@ |
155 | {'name': dept.name, 'url': reverse('wc-department', |
156 | args=[dept.id])}, |
157 | {'name': app.name, 'url': reverse('wc-package-detail', |
158 | - args=[app.package_name])}] |
159 | + args=[app.distroseries.code_name, app.package_name])}] |
160 | |
161 | self.assertEquals(expected, app.crumbs()) |
162 | |
163 | |
164 | === modified file 'src/webcatalog/tests/test_views.py' |
165 | --- src/webcatalog/tests/test_views.py 2011-06-27 13:39:39 +0000 |
166 | +++ src/webcatalog/tests/test_views.py 2011-06-28 15:06:35 +0000 |
167 | @@ -22,8 +22,12 @@ |
168 | with_statement, |
169 | ) |
170 | |
171 | +from django.conf import settings |
172 | from django.core.urlresolvers import reverse |
173 | |
174 | +from mock import patch |
175 | + |
176 | +from webcatalog.models import DistroSeries |
177 | from webcatalog.tests.factory import TestCaseWithFactory |
178 | from webcatalog.tests.helpers import patch_settings |
179 | |
180 | @@ -35,23 +39,52 @@ |
181 | ] |
182 | |
183 | |
184 | +WINDOWS_USERAGENT = ('Mozilla/5.0 (Windows NT 5.1; rv:2.0) ' |
185 | + 'Gecko/20100101 Firefox/4.0') |
186 | + |
187 | +UBUNTU_USERAGENT = ('Mozilla/5.0 (X11; Linux x86_64; rv:2.0.1) ' |
188 | + 'Gecko/20100101 Firefox/4.0.1') |
189 | + |
190 | + |
191 | class PackageDetailTestCase(TestCaseWithFactory): |
192 | |
193 | + def get_app_and_response(self, code_name='natty', version='11.04', |
194 | + arch='x86_64', name=None, comment=None, |
195 | + description=None, detail_distro=None, |
196 | + detail_package=None, for_purchase=False, |
197 | + useragent=UBUNTU_USERAGENT): |
198 | + series = DistroSeries(code_name=code_name, version=version) |
199 | + series.save() |
200 | + app = self.factory.make_application(package_name='pkgfoo', |
201 | + distroseries=series, arch=arch, |
202 | + name=name, comment=comment, |
203 | + description=description) |
204 | + if for_purchase: |
205 | + app.for_purchase = True |
206 | + app.save() |
207 | + if not detail_distro: |
208 | + detail_distro = app.distroseries.code_name |
209 | + if not detail_package: |
210 | + detail_package = app.package_name |
211 | + |
212 | + url = reverse('wc-package-detail', args=[detail_distro, detail_package]) |
213 | + |
214 | + if useragent: |
215 | + response = self.client.get(url, HTTP_USER_AGENT=useragent) |
216 | + else: |
217 | + response = self.client.get(url) |
218 | + return response, app |
219 | + |
220 | def test_renders_correct_template(self): |
221 | - self.factory.make_application(package_name='pkgfoo') |
222 | - url = reverse('wc-package-detail', args=['pkgfoo']) |
223 | - |
224 | - response = self.client.get(url) |
225 | + response, app = self.get_app_and_response() |
226 | |
227 | self.assertTemplateUsed(response, 'webcatalog/application_detail.html') |
228 | |
229 | def test_includes_application_details(self): |
230 | # The details of an application are included in the rendered html. |
231 | - self.factory.make_application(package_name='pkgfoo', name="My app foo", |
232 | - comment="The best app eva.", description="A long description.") |
233 | - url = reverse('wc-package-detail', args=['pkgfoo']) |
234 | - |
235 | - response = self.client.get(url) |
236 | + response, app = self.get_app_and_response(name='My app foo', |
237 | + comment='The best app eva.', |
238 | + description='A long description.') |
239 | |
240 | self.assertContains(response, "My app foo") |
241 | self.assertContains(response, "The best app eva.") |
242 | @@ -59,40 +92,83 @@ |
243 | |
244 | def test_screenshot_thumbnail_url(self): |
245 | # The thumbnail link to screenshots is included. |
246 | - self.factory.make_application(package_name='pkgfoo') |
247 | - url = reverse('wc-package-detail', args=['pkgfoo']) |
248 | - |
249 | - response = self.client.get(url) |
250 | + response, app = self.get_app_and_response() |
251 | |
252 | self.assertContains( |
253 | response, '<img src="http://screenshots.ubuntu.com/' |
254 | 'thumbnail-with-version/pkgfoo/ignored"') |
255 | |
256 | def test_link_to_apt_package(self): |
257 | - self.factory.make_application(package_name='pkgfoo') |
258 | - url = reverse('wc-package-detail', args=['pkgfoo']) |
259 | - |
260 | - response = self.client.get(url) |
261 | - |
262 | - self.assertContains( response, '<a href="apt://pkgfoo"') |
263 | + response, app = self.get_app_and_response() |
264 | + |
265 | + self.assertContains(response, '<a href="apt://pkgfoo"') |
266 | |
267 | def test_button_for_non_puchase_app(self): |
268 | - app = self.factory.make_application(package_name='pkgfoo') |
269 | - url = reverse('wc-package-detail', args=['pkgfoo']) |
270 | - |
271 | - response = self.client.get(url) |
272 | - |
273 | - self.assertContains( response, 'Download %s' % app.name) |
274 | + response, app = self.get_app_and_response() |
275 | + |
276 | + self.assertContains(response, 'Install %s' % app.name) |
277 | + self.assertNotContains(response, 'Purcchase %s' % app.name) |
278 | |
279 | def test_button_for_for_puchase_app(self): |
280 | - app = self.factory.make_application(package_name='pkgfoo') |
281 | - app.for_purchase = True |
282 | - app.save() |
283 | - url = reverse('wc-package-detail', args=['pkgfoo']) |
284 | - |
285 | - response = self.client.get(url) |
286 | - |
287 | - self.assertContains( response, 'Install %s' % app.name) |
288 | + response, app = self.get_app_and_response(for_purchase=True) |
289 | + |
290 | + self.assertContains(response, 'Purchase %s' % app.name) |
291 | + self.assertNotContains(response, 'Install %s' % app.name) |
292 | + |
293 | + def test_button_for_matching_distroseries(self): |
294 | + response, app = self.get_app_and_response(for_purchase=True) |
295 | + |
296 | + self.assertContains(response, 'Purchase %s' % app.name) |
297 | + self.assertNotContains(response, 'Install %s' % app.name) |
298 | + |
299 | + def test_button_for_non_matching_distroseries_but_available(self): |
300 | + series = DistroSeries(code_name='natty', version='11.04') |
301 | + series.save() |
302 | + app2 = self.factory.make_application(package_name='pkgfoo', |
303 | + distroseries=series, |
304 | + arch='x86_64') |
305 | + app2.save() |
306 | + response, app = self.get_app_and_response(code_name='oneric', |
307 | + version='11.10', |
308 | + for_purchase=True, |
309 | + detail_distro='oneric') |
310 | + |
311 | + self.assertContains(response, 'Not running %s?' % |
312 | + settings.DEFAULT_DISTRO) |
313 | + self.assertContains(response, 'Purchase %s for oneric' % app.name) |
314 | + self.assertContains(response, '/cat/applications/oneric/pkgfoo/') |
315 | + |
316 | + @patch('webcatalog.views.get_user_os') |
317 | + def test_button_for_non_matching_distroseries_and_unavailable(self, |
318 | + mock_get_user_os): |
319 | + # patch user agent check so we can have distro is a guess be False |
320 | + # otherwise we'll get the 'Not using natty?' message |
321 | + fake = {'is_linux': True, 'distro': 'natty', 'distro_is_a_guess': False, |
322 | + 'arch': 'x86_64'} |
323 | + mock_get_user_os.return_value = fake |
324 | + response, app = self.get_app_and_response(code_name='oneric', |
325 | + version='11.10', |
326 | + for_purchase=True, |
327 | + detail_distro='oneric') |
328 | + |
329 | + self.assertNotContains(response, 'Purchase %s' % app.name) |
330 | + not_avail_msg = 'Not available for your version of Ubuntu' |
331 | + self.assertContains(response, not_avail_msg) |
332 | + |
333 | + def test_button_for_non_matching_platform(self): |
334 | + response, app = self.get_app_and_response(useragent=WINDOWS_USERAGENT) |
335 | + |
336 | + self.assertNotContains(response, 'Purchase %s' % app.name) |
337 | + self.assertContains(response, 'Not available for your platform') |
338 | + self.assertContains(response, 'http://www.ubuntu.com/download') |
339 | + self.assertContains(response, 'Download Ubuntu') |
340 | + |
341 | + def test_app_detail_with_no_useragent(self): |
342 | + # don't set the useragent |
343 | + response, app = self.get_app_and_response(useragent=None) |
344 | + |
345 | + self.assertNotContains(response, 'Purchase %s' % app.name) |
346 | + |
347 | |
348 | |
349 | class SearchTestCase(TestCaseWithFactory): |
350 | @@ -201,6 +277,7 @@ |
351 | self.assertEqual(1, page.number) |
352 | |
353 | |
354 | + |
355 | class OverviewTestCase(TestCaseWithFactory): |
356 | def test_index_contains_links_to_departments(self): |
357 | dept = self.factory.make_department('foo') |
358 | @@ -227,7 +304,7 @@ |
359 | response = self.client.get(reverse('wc-department', args=[dept.id])) |
360 | |
361 | self.assertContains(response, reverse('wc-package-detail', |
362 | - args=[app.package_name])) |
363 | + args=[app.distroseries.code_name, app.package_name])) |
364 | |
365 | def test_department_with_no_subdepts_doesnt_contain_header(self): |
366 | dept = self.factory.make_department('bar') |
367 | |
368 | === modified file 'src/webcatalog/urls.py' |
369 | --- src/webcatalog/urls.py 2011-06-23 14:20:52 +0000 |
370 | +++ src/webcatalog/urls.py 2011-06-28 15:06:35 +0000 |
371 | @@ -22,9 +22,8 @@ |
372 | with_statement, |
373 | ) |
374 | from django.conf.urls.defaults import patterns, url |
375 | -from django.views.generic.detail import DetailView |
376 | |
377 | -from webcatalog.models import Application |
378 | +from webcatalog.views import application_detail, application_detail_no_distro |
379 | |
380 | __metaclass__ = type |
381 | __all__ = [ |
382 | @@ -36,7 +35,9 @@ |
383 | url(r'^$', 'index', name='wc-index'), |
384 | url(r'^department/(?P<dept_id>\d+)/$', 'department_overview', |
385 | name='wc-department'), |
386 | - url(r'^applications/(?P<package_name>[-.+\w]+)/$', 'application_detail', |
387 | - name="wc-package-detail"), |
388 | + url(r'^applications/(?P<distro>[-.+\w]+)/(?P<slug>[-.+\w]+)/$', |
389 | + application_detail, name="wc-package-detail"), |
390 | + url(r'^applications/(?P<slug>[-.+\w]+)/$', application_detail_no_distro, |
391 | + name="wc-package-detail-no-distro"), |
392 | url(r'^search/$', 'search', name="wc-search"), |
393 | ) |
394 | |
395 | === modified file 'src/webcatalog/views.py' |
396 | --- src/webcatalog/views.py 2011-06-27 14:08:41 +0000 |
397 | +++ src/webcatalog/views.py 2011-06-28 15:06:35 +0000 |
398 | @@ -55,6 +55,7 @@ |
399 | return int(page_num) |
400 | return 1 |
401 | |
402 | + |
403 | def search(request): |
404 | apps = [] |
405 | query = '' |
406 | @@ -82,12 +83,14 @@ |
407 | return render_to_response('webcatalog/search_results.html', |
408 | context_instance=context) |
409 | |
410 | + |
411 | def index(request): |
412 | depts = Department.objects.filter(parent=None).order_by('name') |
413 | context = RequestContext(request, dict={'depts': depts}) |
414 | return render_to_response('webcatalog/index.html', |
415 | context_instance=context) |
416 | |
417 | + |
418 | def department_overview(request, dept_id): |
419 | dept = get_object_or_404(Department, pk=dept_id) |
420 | subdepts = Department.objects.filter(parent=dept) |
421 | @@ -104,12 +107,77 @@ |
422 | context_instance=context) |
423 | |
424 | |
425 | -def application_detail(request, package_name): |
426 | - app = get_object_or_404(Application, package_name=package_name) |
427 | - |
428 | - context = RequestContext(request, { |
429 | - 'application': app, |
430 | - 'breadcrumbs': app.crumbs(), |
431 | - }) |
432 | - return render_to_response('webcatalog/application_detail.html', |
433 | - context_instance=context) |
434 | +def application_detail_no_distro(request, slug): |
435 | + default_distro = settings.DEFAULT_DISTRO |
436 | + return application_detail(request, default_distro, slug) |
437 | + |
438 | + |
439 | +def application_detail(request, distro, slug): |
440 | + os = get_user_os(request) |
441 | + app = get_object_or_404(Application, package_name=slug, |
442 | + distroseries__code_name=distro) |
443 | + button_text = 'Purchase' if app.for_purchase else 'Install' |
444 | + right_platform = os['is_linux'] |
445 | + right_arch = app.architectures.find(os['arch']) > -1 |
446 | + right_distro = os['distro'].find(app.distroseries.code_name) > -1 |
447 | + perfect_match = (right_platform and right_distro and right_arch) |
448 | + message_text = 'Not available for your version of Ubuntu' |
449 | + links = [] |
450 | + if not perfect_match: |
451 | + if not right_platform: |
452 | + message_text = "Not available for your platform" |
453 | + links.append(('Download Ubuntu', 'http://www.ubuntu.com/download')) |
454 | + elif not right_distro and os['distro_is_a_guess']: |
455 | + # see if we have this package for *other* distros |
456 | + apps_found = Application.objects.filter(package_name=slug).exclude( |
457 | + distroseries__code_name=os['distro']) |
458 | + if apps_found: |
459 | + message_text = ('Not running %s?' % os['distro']) |
460 | + for app_found in apps_found: |
461 | + args = [app.distroseries.code_name, app.package_name] |
462 | + url = reverse('wc-package-detail', args=args) |
463 | + text = "%s %s for %s" % (button_text, app.name, |
464 | + app_found.distroseries.code_name) |
465 | + links.append((text, url)) |
466 | + elif not right_distro: |
467 | + app_found = Application.objects.filter(package_name=slug, |
468 | + distroseries__code_name=os['distro']) |
469 | + if app_found: |
470 | + args = [app.distroseries.code_name, app.package_name] |
471 | + url = reverse('wc-package-detail', args=args) |
472 | + message_text = ('%s is also available for your version ' |
473 | + 'of Ubuntu' % app.name) |
474 | + links.append(("%s for os['distro']" % button_text, url)) |
475 | + |
476 | + ctx = {'application': app, 'button_text': button_text, |
477 | + 'hide_button': not perfect_match, 'message_text': message_text, |
478 | + 'breadcrumbs': app.crumbs(), 'links': links} |
479 | + |
480 | + context = RequestContext(request, dict=ctx) |
481 | + return render_to_response('webcatalog/application_detail.html', context) |
482 | + |
483 | + |
484 | +def get_user_os(request): |
485 | + os = {'is_linux': False, 'distro': 'unknown', 'arch': 'unknown'} |
486 | + try: |
487 | + ua = request.META['HTTP_USER_AGENT'] |
488 | + except KeyError: |
489 | + return os |
490 | + os['is_linux'] = ua.find('X11; Linux') > -1 |
491 | + # Until we can figure out a way to actually get the distro we'll |
492 | + # assume a default distro |
493 | + if os['is_linux']: |
494 | + os['distro'] = settings.DEFAULT_DISTRO |
495 | + os['distro_is_a_guess'] = True |
496 | + else: |
497 | + os['distro'] = '' |
498 | + os['distro_is_a_guess'] = False |
499 | + |
500 | + is_x86_64 = ua.find('x86_64') |
501 | + is_686 = ua.find('i686') |
502 | + if is_x86_64: |
503 | + os['arch'] = 'x86_64' |
504 | + elif is_686: |
505 | + os['arch'] = 'i686' |
506 | + # TODO: DT Get other architectures |
507 | + return os |
I really like how you factored the tests!
Approved, with recommendation that Linux fields not be set in get_user_os() when not a Linux browser.