fix up links, and changes in output

This commit is contained in:
Allen Short 2013-11-12 12:14:58 -08:00
Родитель d621458831
Коммит ab798c3e35
21 изменённых файлов: 360 добавлений и 72 удалений

Просмотреть файл

@ -1,5 +1,4 @@
from functools import partial
from mkt.api.base import CompatRelatedField
from rest_framework import fields, serializers

Просмотреть файл

@ -196,7 +196,7 @@ class TestInstalled(BaseOAuth):
self._allowed_verbs(self.list_url, ('get'))
def test_not_allowed(self):
eq_(self.anon.get(self.list_url).status_code, 401)
eq_(self.anon.get(self.list_url).status_code, 403)
def test_installed(self):
ins = Installed.objects.create(user=self.user, addon_id=337141)
@ -204,7 +204,7 @@ class TestInstalled(BaseOAuth):
eq_(res.status_code, 200, res.content)
data = json.loads(res.content)
eq_(data['meta']['total_count'], 1)
eq_(data['objects'][0]['id'], str(ins.addon.pk))
eq_(data['objects'][0]['id'], ins.addon.pk)
def not_there(self):
res = self.client.get(self.list_url)

Просмотреть файл

@ -27,7 +27,6 @@ class BaseAPI(TestCase):
res.status_code)
assert res.status_code in (401, 403, 405), msg
def get_error(self, response):
return json.loads(response.content)['error_message']

Просмотреть файл

@ -12,7 +12,9 @@ from tastypie.exceptions import ImmediateHttpResponse
from access.models import Group, GroupUser
from addons.models import AddonUser
from amo.helpers import absolutify
from amo.tests import app_factory, TestCase
from amo.urlresolvers import reverse
from test_utils import RequestFactory
from users.models import UserProfile
@ -95,9 +97,8 @@ class TestOAuthAuthentication(TestCase):
user=self.profile.user)
def call(self, client=None):
url = ('api_dispatch_list', {'resource_name': 'app'})
client = client or OAuthClient(self.access)
url = client.get_absolute_url(url)
url = absolutify(reverse('app-list'))
return RequestFactory().get(url,
HTTP_HOST='testserver',
HTTP_AUTHORIZATION=client.sign('GET', url)[1]['Authorization'])

Просмотреть файл

@ -203,7 +203,7 @@ class Test3LeggedOAuthFlow(TestCase):
return url, headers['Authorization']
def test_use_access_token(self):
url = get_absolute_url(('api_dispatch_list', {'resource_name': 'app'}))
url = absolutify(reverse('app-list'))
t = Token.generate_new(ACCESS_TOKEN, creds=self.access,
user=self.user2)
url, auth_header = self._oauth_request_info(
@ -217,7 +217,7 @@ class Test3LeggedOAuthFlow(TestCase):
eq_(req.user, self.user2)
def test_bad_access_token(self):
url = get_absolute_url(('api_dispatch_list', {'resource_name': 'app'}))
url = absolutify(reverse('app-list'))
Token.generate_new(ACCESS_TOKEN, creds=self.access, user=self.user2)
url, auth_header = self._oauth_request_info(
url, client_key=self.access.key,

Просмотреть файл

@ -23,7 +23,7 @@ from mkt.api.authorization import (AllowAppOwner, GroupPermission,
switch)
from mkt.api.authentication import (RestOAuthAuthentication,
RestSharedSecretAuthentication)
from mkt.api.base import AppViewSet, CompatRelatedField
from mkt.api.base import AppViewSet
from mkt.constants.payments import PAYMENT_STATUSES
from mkt.developers.forms_payments import (BangoPaymentAccountForm,
PaymentCheckForm)
@ -133,9 +133,7 @@ class PaymentViewSet(RetrieveModelMixin, GenericViewSet):
class UpsellSerializer(HyperlinkedModelSerializer):
free = premium = CompatRelatedField(
tastypie={'resource_name': 'app', 'api_name': 'apps'},
view_name='api_dispatch_detail')
free = premium = HyperlinkedRelatedField(view_name='app-detail')
class Meta:
model = AddonUpsell
@ -206,13 +204,9 @@ class AddonPaymentAccountPermission(BasePermission):
class AddonPaymentAccountSerializer(HyperlinkedModelSerializer):
addon = CompatRelatedField(
source='addon',
tastypie={'resource_name': 'app', 'api_name': 'apps'},
view_name='api_dispatch_detail')
addon = HyperlinkedRelatedField(view_name='app-detail')
payment_account = HyperlinkedRelatedField(
view_name='payment-account-detail')
class Meta:
model = AddonPaymentAccount
fields = ('addon', 'payment_account', 'provider',

Просмотреть файл

@ -54,7 +54,7 @@ payment_data.update(bank_data)
class UpsellCase(TestCase):
def url(self, app):
return get_absolute_url(get_url('app', pk=app.pk), absolute=False)
return reverse('app-detail', kwargs={'pk': app.pk})
def setUp(self):
self.free = Webapp.objects.get(pk=337141)

299
mkt/ratings/resources.py Normal file
Просмотреть файл

@ -0,0 +1,299 @@
from django.conf.urls import url
import commonware.log
from tastypie import fields, http, paginator
from tastypie.authorization import Authorization
from tastypie.bundle import Bundle
from tastypie.utils import trailing_slash
import amo
from amo import get_user
from lib.metrics import record_action
from mkt.api.authentication import (OptionalOAuthAuthentication,
SharedSecretAuthentication)
from mkt.api.authorization import (AnonymousReadOnlyAuthorization,
AppOwnerAuthorization,
OwnerAuthorization,
PermissionAuthorization)
from mkt.api.base import (CompatToOneField, CORSResource, http_error,
MarketplaceModelResource)
from mkt.ratings.forms import ReviewForm
from mkt.regions import get_region, REGIONS_DICT
from mkt.webapps.models import Webapp
from reviews.models import Review, ReviewFlag
log = commonware.log.getLogger('z.api')
class RatingPaginator(paginator.Paginator):
def get_count(self):
try:
r = self.objects[0]
except IndexError:
return 0
return r.addon.total_reviews
class RatingResource(CORSResource, MarketplaceModelResource):
app = CompatToOneField(None, 'addon', rest='app', readonly=True, null=True)
user = CompatToOneField(None, 'user', url_name='account-settings',
readonly=True, null=True,
extra_fields=('display_name',))
version = CompatToOneField(None, 'version', url_name='version-detail',
readonly=True, null=True,
extra_fields=('version',))
report_spam = fields.CharField()
class Meta(MarketplaceModelResource.Meta):
# Unfortunately, the model class name for ratings is "Review".
queryset = Review.objects.valid()
resource_name = 'rating'
list_allowed_methods = ['get', 'post']
detail_allowed_methods = ['get', 'put', 'delete']
always_return_data = True
authentication = (SharedSecretAuthentication(),
OptionalOAuthAuthentication())
authorization = AnonymousReadOnlyAuthorization()
fields = ['rating', 'body', 'modified', 'created']
paginator_class = RatingPaginator
filtering = {
'app': ('exact',),
'user': ('exact',),
'pk': ('exact',),
}
ordering = ['created']
def dehydrate(self, bundle):
bundle = super(RatingResource, self).dehydrate(bundle)
if bundle.request.amo_user:
amo_user = bundle.request.amo_user
bundle.data['is_author'] = bundle.obj.user.pk == amo_user.pk
bundle.data['has_flagged'] = (not bundle.data['is_author'] and
bundle.obj.reviewflag_set.filter(user=amo_user).exists())
return bundle
def dehydrate_report_spam(self, bundle):
return self._build_reverse_url(
'api_post_flag',
kwargs={'api_name': self._meta.api_name,
'resource_name': self._meta.resource_name,
'review_id': bundle.obj.pk})
def _review_data(self, request, app, form):
data = dict(addon_id=app.id, user_id=request.user.id,
ip_address=request.META.get('REMOTE_ADDR', ''))
if app.is_packaged:
data['version_id'] = app.current_version.id
data.update(**form.cleaned_data)
return data
def get_app(self, ident):
try:
app = Webapp.objects.valid().get(id=ident)
except (Webapp.DoesNotExist, ValueError):
try:
app = Webapp.objects.valid().get(app_slug=ident)
except Webapp.DoesNotExist:
raise self.non_form_errors([('app', 'Invalid app')])
if not app.listed_in(region=REGIONS_DICT[get_region()]):
raise self.non_form_errors([('app', 'Not available in this region')])
return app
def build_filters(self, filters=None):
"""
If `addon__exact` is a filter and its value cannot be coerced into an
int, assume that it's a slug lookup.
Run the query necessary to determine the app, and substitute the slug
with the PK in the filter so tastypie will continue doing its thing.
"""
built = super(RatingResource, self).build_filters(filters)
if 'addon__exact' in built:
try:
int(built['addon__exact'])
except ValueError:
app = self.get_app(built['addon__exact'])
if app:
built['addon__exact'] = str(app.pk)
if built.get('user__exact', None) == 'mine':
# This is a cheat. Would prefer /mine/ in the URL.
user = get_user()
if not user:
# You must be logged in to use "mine".
raise http_error(http.HttpUnauthorized, 'You must be logged in to access "mine".')
built['user__exact'] = user.pk
return built
def obj_create(self, bundle, request=None, **kwargs):
"""
Handle POST requests to the resource. If the data validates, create a
new Review from bundle data.
"""
form = ReviewForm(bundle.data)
if not form.is_valid():
raise self.form_errors(form)
app = self.get_app(bundle.data['app'])
# Return 409 if the user has already reviewed this app.
qs = self._meta.queryset.filter(addon=app, user=request.user)
if app.is_packaged:
qs = qs.filter(version_id=bundle.data.get('version',
app.current_version.id))
if qs.exists():
raise http_error(http.HttpConflict, 'You have already reviewed this app.')
# Return 403 if the user is attempting to review their own app:
if app.has_author(request.user):
raise http_error(http.HttpForbidden, 'You may not review your own app.')
# Return 403 if not a free app and the user hasn't purchased it.
if app.is_premium() and not app.is_purchased(request.amo_user):
raise http_error(
http.HttpForbidden,
"You may not review paid apps you haven't purchased.")
bundle.obj = Review.objects.create(**self._review_data(request, app,
form))
amo.log(amo.LOG.ADD_REVIEW, app, bundle.obj)
log.debug('[Review:%s] Created by user %s ' %
(bundle.obj.id, request.user.id))
record_action('new-review', request, {'app-id': app.id})
return bundle
def obj_update(self, bundle, request, **kwargs):
"""
Handle PUT requests to the resource. If authorized and the data
validates, update the indicated resource with bundle data.
"""
obj = self.get_by_resource_or_404(request, **kwargs)
if not OwnerAuthorization().is_authorized(request, object=obj):
raise http_error(
http.HttpForbidden,
'You do not have permission to update this review.')
form = ReviewForm(bundle.data)
if not form.is_valid():
raise self.form_errors(form)
if 'app' in bundle.data:
error = ('app', "Cannot update a rating's `app`")
raise self.non_form_errors([error])
sup = super(RatingResource, self).obj_update(bundle, request, **kwargs)
amo.log(amo.LOG.EDIT_REVIEW, bundle.obj.addon, bundle.obj)
log.debug('[Review:%s] Edited by %s' % (bundle.obj.id, request.user.id))
return sup
def obj_delete(self, request, **kwargs):
obj = self.get_by_resource_or_404(request, **kwargs)
if not (AppOwnerAuthorization().is_authorized(request,
object=obj.addon)
or OwnerAuthorization().is_authorized(request, object=obj)
or PermissionAuthorization('Users',
'Edit').is_authorized(request)
or PermissionAuthorization('Addons',
'Edit').is_authorized(request)):
raise http_error(
http.HttpForbidden,
'You do not have permission to delete this review.')
log.info('Rating %s deleted from addon %s' % (obj.pk, obj.addon.pk))
return super(RatingResource, self).obj_delete(request, **kwargs)
def get_object_list(self, request):
qs = MarketplaceModelResource.get_object_list(self, request)
# Mature regions show only reviews from within that region.
if not request.REGION.adolescent:
qs = qs.filter(client_data__region=request.REGION.id)
return qs
def alter_list_data_to_serialize(self, request, data):
if 'app' in request.GET:
addon = self.get_app(request.GET['app'])
data['info'] = {
'average': addon.average_rating,
'slug': addon.app_slug,
'current_version': addon.current_version.version
}
filters = dict(addon=addon)
if addon.is_packaged:
filters['version'] = addon.current_version
if not request.user.is_anonymous():
filters['user'] = request.user
existing_review = Review.objects.valid().filter(**filters)
if addon.is_premium():
can_rate = addon.has_purchased(request.amo_user)
else:
can_rate = not addon.has_author(request.user)
data['user'] = {'can_rate': can_rate,
'has_rated': existing_review.exists()}
else:
data['user'] = None
return data
def override_urls(self):
# Based on 'nested resource' example in tastypie cookbook.
return [
url(r'^(?P<resource_name>%s)/(?P<review_id>\w[\w/-]*)/flag%s$' %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('post_flag'), name='api_post_flag')
]
def post_flag(self, request, **kwargs):
return RatingFlagResource().dispatch('list', request,
review_id=kwargs['review_id'])
class FireplaceRatingResource(RatingResource):
class Meta(RatingResource.Meta):
pass
class RatingFlagResource(CORSResource, MarketplaceModelResource):
class Meta(MarketplaceModelResource.Meta):
queryset = ReviewFlag.objects.all()
resource_name = 'rating_flag'
list_allowed_methods = ['post']
detail_allowed_methods = []
authentication = (SharedSecretAuthentication(),
OptionalOAuthAuthentication())
authorization = Authorization()
fields = ['review', 'flag', 'note', 'user']
def get_resource_uri(self, bundle_or_obj):
if isinstance(bundle_or_obj, Bundle):
obj = bundle_or_obj.obj
else:
obj = bundle_or_obj
return '/api/apps/ratings/%s/flag/%s%s' % (obj.review_id, obj.pk,
trailing_slash())
def post_list(self, request, review_id=None, **kwargs):
if ReviewFlag.objects.filter(review_id=review_id,
user=request.amo_user).exists():
return http.HttpConflict()
return MarketplaceModelResource.post_list(
self, request, review_id=review_id, **kwargs)
def obj_create(self, bundle, request=None, review_id=None, **kwargs):
if 'note' in bundle.data and bundle.data['note'].strip():
bundle.data['flag'] = ReviewFlag.OTHER
Review.objects.filter(id=review_id).update(editorreview=True)
return MarketplaceModelResource.obj_create(
self, bundle, request=request, review_id=review_id,
user=request.amo_user)

Просмотреть файл

@ -6,7 +6,7 @@ from rest_framework.exceptions import PermissionDenied
from reviews.models import Review, ReviewFlag
from mkt.account.serializers import AccountSerializer
from mkt.api.base import CompatRelatedField
from mkt.api.fields import SlugOrPrimaryKeyRelatedField, SplitField
from mkt.api.exceptions import Conflict
from mkt.regions import get_region, REGIONS_DICT
from mkt.versions.api import SimpleVersionSerializer
@ -14,10 +14,13 @@ from mkt.webapps.models import Webapp
class RatingSerializer(serializers.ModelSerializer):
app = CompatRelatedField(tastypie={'resource_name': 'app',
'api_name': 'apps'},
source='addon',
slug_field='app_slug')
app = SplitField(
SlugOrPrimaryKeyRelatedField(slug_field='app_slug',
queryset=Webapp.objects.all(),
source='addon'),
serializers.HyperlinkedRelatedField(view_name='app-detail',
read_only=True,
source='addon'))
body = serializers.CharField()
user = AccountSerializer(read_only=True)
report_spam = serializers.SerializerMethodField('get_report_spam_link')
@ -102,10 +105,10 @@ class RatingSerializer(serializers.ModelSerializer):
def validate_app(self, attrs, source):
if not getattr(self, 'object'):
# The CompatRelatedField does part of the job for us, but our
# get_app_from_value does extra checks.
app = attrs[source]
attrs[source] = RatingSerializer.get_app_from_value(app.pk)
else:
attrs[source] = self.object.addon
return attrs

Просмотреть файл

@ -382,8 +382,10 @@ class TestRatingResource(RestOAuth, amo.tests.AMOPaths):
def test_update(self):
self._create_default_review()
new_data = {
'app': self.app.id,
'body': 'Totally rocking the free web.',
'rating': 4
'rating': 4,
'version': self.app.current_version.id
}
log_review_id = amo.LOG.EDIT_REVIEW.id
eq_(ActivityLog.objects.filter(action=log_review_id).count(), 0)

Просмотреть файл

@ -1,6 +1,5 @@
from rest_framework import serializers
from mkt.api.base import CompatRelatedField
from mkt.webapps.models import Webapp
@ -9,8 +8,6 @@ class ReviewingSerializer(serializers.ModelSerializer):
model = Webapp
fields = ('resource_uri', )
resource_uri = CompatRelatedField(
view_name='api_dispatch_detail', read_only=True,
tastypie={'resource_name': 'app',
'api_name': 'apps'},
source='*')
resource_uri = serializers.HyperlinkedRelatedField(view_name='app-detail',
read_only=True,
source='*')

Просмотреть файл

@ -14,10 +14,10 @@ import mkt.regions
from access.models import GroupUser
from addons.models import Category
from amo.tests import ESTestCase
from amo.urlresolvers import reverse
from mkt.api.tests.test_oauth import (BaseOAuth, get_absolute_url, OAuthClient,
RestOAuth)
from mkt.api.base import get_url, list_url
from mkt.api.tests.test_oauth import BaseOAuth, OAuthClient, RestOAuth
from mkt.api.base import list_url
from mkt.api.models import Access, generate
from mkt.constants.features import FeatureProfile
from mkt.reviewers.api import ReviewersSearchResource
@ -67,7 +67,7 @@ class TestReviewing(RestOAuth):
res = self.client.get(self.list_url)
data = json.loads(res.content)
eq_(data['objects'][0]['resource_uri'],
get_absolute_url(get_url('app', '337141'), absolute=False))
reverse('app-detail', kwargs={'pk': 337141}))
class TestApiReviewer(BaseOAuth, ESTestCase):

Просмотреть файл

@ -8,11 +8,13 @@ from django.core.urlresolvers import reverse
from mock import patch
import amo.tests
from addons.models import AddonUser
from files.models import FileUpload
from users.models import UserProfile
from mkt.api.tests.test_oauth import BaseOAuth, RestOAuth
from mkt.site.fixtures import fixture
from mkt.webapps.models import Webapp
@ -58,7 +60,7 @@ class TestAddValidationHandler(ValidationHandler):
obj = FileUpload.objects.get(uuid=content['id'])
eq_(obj.user, self.user)
@patch('mkt.api.resources.tasks.fetch_manifest')
@patch('mkt.webapps.api.tasks.fetch_manifest')
def test_fetch(self, fetch):
self.create()
assert fetch.called
@ -212,6 +214,7 @@ class TestAppStatusHandler(RestOAuth, amo.tests.AMOPaths):
data = json.loads(res.content)
return res, data
def test_verbs(self):
self._allowed_verbs(self.get_url, ['get', 'patch']) # FIXME disallow put

Просмотреть файл

@ -4,7 +4,6 @@ from rest_framework.exceptions import ParseError
import amo
from mkt.api.authorization import (AllowAppOwner, AllowReadOnly, AnyOf,
GroupPermission)
from mkt.api.base import CompatRelatedField
from mkt.constants import APP_FEATURES
from mkt.features.api import AppFeaturesSerializer
from versions.models import Version
@ -20,9 +19,8 @@ class SimpleVersionSerializer(serializers.ModelSerializer):
class VersionSerializer(serializers.ModelSerializer):
addon = CompatRelatedField(view_name='api_dispatch_detail', read_only=True,
tastypie={'resource_name': 'app',
'api_name': 'apps'})
addon = serializers.HyperlinkedRelatedField(view_name='app-detail',
read_only=True)
class Meta:
model = Version

Просмотреть файл

@ -37,11 +37,8 @@ class TestVersionSerializer(TestCase):
ok_(all(k in native for k in added_keys))
def test_addon(self):
eq_(self.native()['app'], reverse('api_dispatch_detail', kwargs={
'resource_name': 'app',
'api_name': 'apps',
'pk': self.app.pk}
))
eq_(self.native()['app'], reverse('app-detail',
kwargs={'pk': self.app.pk}))
def test_is_current_version(self):
old_version = Version.objects.create(addon=self.app, version='0.1')
@ -87,11 +84,8 @@ class TestVersionViewSet(RestOAuth):
eq_(data['developer_name'], version.developer_name)
eq_(data['is_current_version'],
version == self.app.current_version)
eq_(data['app'], reverse('api_dispatch_detail', kwargs={
'resource_name': 'app',
'api_name': 'apps',
'pk': self.app.pk}
))
eq_(data['app'], reverse('app-detail',
kwargs={'pk': self.app.pk}))
for key in features:
ok_(getattr(version.features, 'has_' + key))

Просмотреть файл

@ -21,7 +21,7 @@ from mkt.api.authentication import (RestOAuthAuthentication,
RestSharedSecretAuthentication,
RestAnonymousAuthentication)
from mkt.api.authorization import (AllowAppOwner, AllowReviewerReadOnly, AnyOf)
from mkt.api.base import (CompatRelatedField, CORSMixin, get_url, SlugOrIdMixin)
from mkt.api.base import CORSMixin, get_url, SlugOrIdMixin
from mkt.api.exceptions import HttpLegallyUnavailable
from mkt.api.fields import (LargeTextField, ReverseChoiceField,
TranslationSerializerField)
@ -113,9 +113,7 @@ class AppSerializer(serializers.ModelSerializer):
manifest_url = serializers.CharField(source='get_manifest_url',
read_only=True)
name = TranslationSerializerField(required=False)
payment_account = serializers.HyperlinkedRelatedField(
view_name='payment-account-detail',
source='app_payment_account')
payment_account = serializers.HyperlinkedRelatedField(view_name='payment-account-detail', source='app_payment_account', required=False)
payment_required = serializers.SerializerMethodField(
'get_payment_required')
premium_type = ReverseChoiceField(

Просмотреть файл

@ -240,13 +240,11 @@ class Webapp(Addon):
def get_api_url(self, action=None, api=None, resource=None, pk=False):
"""Reverse a URL for the API."""
kwargs = {'api_name': api or 'apps',
'resource_name': resource or 'app'}
if pk:
kwargs['pk'] = self.pk
key = self.pk
else:
kwargs['app_slug'] = self.app_slug
return reverse('api_dispatch_%s' % (action or 'detail'), kwargs=kwargs)
key = self.app_slug
return reverse('app-detail', kwargs={'pk': key})
def get_url_path(self, more=False, add_prefix=True, src=None):
# We won't have to do this when Marketplace absorbs all apps views,

Просмотреть файл

@ -139,6 +139,10 @@ class TestWebapp(amo.tests.TestCase):
webapp = Webapp(app_slug='woo', pk=1)
eq_(webapp.get_api_url(), '/api/v1/apps/app/woo/')
def test_get_api_url_pk(self):
webapp = Webapp(pk=1)
eq_(webapp.get_api_url(pk=True), '/api/v1/apps/app/1/')
def test_get_stats_url(self):
webapp = Webapp(app_slug='woo')

Просмотреть файл

@ -538,7 +538,7 @@ class TestDumpApps(amo.tests.TestCase):
def test_dump_app(self):
fn = dump_app(337141)
result = json.load(open(fn, 'r'))
eq_(result['id'], str(337141))
eq_(result['id'], 337141)
def test_zip_apps(self):
dump_app(337141)

Просмотреть файл

@ -124,7 +124,7 @@ class TestAppSerializer(amo.tests.TestCase):
ratingsbodies.CLASSIND: ratingsbodies.CLASSIND_18,
ratingsbodies.GENERIC: ratingsbodies.GENERIC_18,
})
res = app_to_dict(self.app)
res = self.serialize(self.app)
eq_(res['content_ratings']['ratings']['br'],
{'body': 'CLASSIND',
'body_label': 'classind',
@ -140,14 +140,14 @@ class TestAppSerializer(amo.tests.TestCase):
def test_content_descriptors(self):
self.app.set_descriptors(['has_esrb_blood', 'has_pegi_scary'])
res = app_to_dict(self.app)
res = self.serialize(self.app)
eq_(res['content_ratings']['descriptors'],
[{'label': 'esrb-blood', 'name': 'Blood', 'ratings_body': 'esrb'},
{'label': 'pegi-scary', 'name': 'Fear', 'ratings_body': 'pegi'}])
def test_interactive_elements(self):
self.app.set_interactives(['has_social_networking', 'has_shares_info'])
res = app_to_dict(self.app)
res = self.serialize(self.app)
eq_(res['content_ratings']['interactive_elements'],
[{'label': 'shares-info', 'name': 'Shares Info'},
{'label': 'social-networking', 'name': 'Social Networking'}])

Просмотреть файл

@ -7,7 +7,8 @@ import commonware.log
import amo
from addons.models import AddonUser
from amo.helpers import absolutify
from amo.utils import find_language, no_translation
from amo.utils import find_language
from amo.urlresolvers import reverse
from constants.applications import DEVICE_TYPES
from market.models import Price
from users.models import UserProfile
@ -74,8 +75,6 @@ def es_app_to_dict(obj, region=None, profile=None, request=None):
Return app data as dict for API where `app` is the elasticsearch result.
"""
# Circular import.
from mkt.api.base import GenericObject
from mkt.api.resources import AppResource, PrivacyPolicyResource
from mkt.developers.models import AddonPaymentAccount
from mkt.webapps.models import Installed, Webapp
@ -116,9 +115,8 @@ def es_app_to_dict(obj, region=None, profile=None, request=None):
'name': get_attr_lang(src, 'name', obj.default_locale),
'payment_required': False,
'premium_type': amo.ADDON_PREMIUM_API[src.get('premium_type')],
'privacy_policy': PrivacyPolicyResource().get_resource_uri(
GenericObject({'pk': obj._id})
),
'privacy_policy': reverse('app-privacy-policy-detail',
kwargs={'pk': obj._id}),
'public_stats': obj.has_public_stats,
'supported_locales': src.get('supported_locales', ''),
'slug': obj.app_slug,
@ -149,8 +147,9 @@ def es_app_to_dict(obj, region=None, profile=None, request=None):
exclusions = obj.upsell.get('region_exclusions')
if exclusions is not None and region not in exclusions:
data['upsell'] = obj.upsell
data['upsell']['resource_uri'] = AppResource().get_resource_uri(
Webapp(id=obj.upsell['id']))
data['upsell']['resource_uri'] = reverse(
'app-detail',
kwargs={'pk': obj.upsell['id']})
data['price'] = data['price_locale'] = None
try: