Merge branch 'more-performant-favorites' into 'develop'
More performant favorites See merge request funkwhale/funkwhale!522
This commit is contained in:
commit
53ade20722
3
.env.dev
3
.env.dev
|
@ -12,3 +12,6 @@ MUSIC_DIRECTORY_PATH=/music
|
||||||
BROWSABLE_API_ENABLED=True
|
BROWSABLE_API_ENABLED=True
|
||||||
FORWARDED_PROTO=http
|
FORWARDED_PROTO=http
|
||||||
LDAP_ENABLED=False
|
LDAP_ENABLED=False
|
||||||
|
|
||||||
|
# Uncomment this if you're using traefik/https
|
||||||
|
# FORCE_HTTPS_URLS=True
|
||||||
|
|
|
@ -14,6 +14,7 @@ from .common import * # noqa
|
||||||
# DEBUG
|
# DEBUG
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
DEBUG = env.bool("DJANGO_DEBUG", default=True)
|
DEBUG = env.bool("DJANGO_DEBUG", default=True)
|
||||||
|
FORCE_HTTPS_URLS = env.bool("FORCE_HTTPS_URLS", default=False)
|
||||||
TEMPLATES[0]["OPTIONS"]["debug"] = DEBUG
|
TEMPLATES[0]["OPTIONS"]["debug"] = DEBUG
|
||||||
|
|
||||||
# SECRET CONFIGURATION
|
# SECRET CONFIGURATION
|
||||||
|
@ -80,3 +81,5 @@ CSRF_TRUSTED_ORIGINS = [o for o in ALLOWED_HOSTS]
|
||||||
if env.bool("WEAK_PASSWORDS", default=False):
|
if env.bool("WEAK_PASSWORDS", default=False):
|
||||||
# Faster during tests
|
# Faster during tests
|
||||||
PASSWORD_HASHERS = ("django.contrib.auth.hashers.MD5PasswordHasher",)
|
PASSWORD_HASHERS = ("django.contrib.auth.hashers.MD5PasswordHasher",)
|
||||||
|
|
||||||
|
MIDDLEWARE = ("funkwhale_api.common.middleware.DevHttpsMiddleware",) + MIDDLEWARE
|
||||||
|
|
|
@ -135,3 +135,25 @@ class SPAFallbackMiddleware:
|
||||||
return serve_spa(request)
|
return serve_spa(request)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
class DevHttpsMiddleware:
|
||||||
|
"""
|
||||||
|
In development, it's sometimes difficult to have django use HTTPS
|
||||||
|
when we have django behind nginx behind traefix.
|
||||||
|
|
||||||
|
We thus use a simple setting (in dev ONLY) to control that.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, get_response):
|
||||||
|
self.get_response = get_response
|
||||||
|
|
||||||
|
def __call__(self, request):
|
||||||
|
if settings.FORCE_HTTPS_URLS:
|
||||||
|
setattr(request.__class__, "scheme", "https")
|
||||||
|
setattr(
|
||||||
|
request,
|
||||||
|
"get_host",
|
||||||
|
lambda: request.__class__.get_host(request).replace(":80", ":443"),
|
||||||
|
)
|
||||||
|
return self.get_response(request)
|
||||||
|
|
|
@ -71,3 +71,19 @@ class TrackFavoriteViewSet(
|
||||||
return Response({}, status=400)
|
return Response({}, status=400)
|
||||||
favorite.delete()
|
favorite.delete()
|
||||||
return Response([], status=status.HTTP_204_NO_CONTENT)
|
return Response([], status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
|
@list_route(methods=["get"])
|
||||||
|
def all(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Return all the favorites of the current user, with only limited data
|
||||||
|
to have a performant endpoint and avoid lots of queries just to display
|
||||||
|
favorites status in the UI
|
||||||
|
"""
|
||||||
|
if not request.user.is_authenticated:
|
||||||
|
return Response({"results": [], "count": 0}, status=200)
|
||||||
|
|
||||||
|
favorites = list(
|
||||||
|
request.user.track_favorites.values("id", "track").order_by("id")
|
||||||
|
)
|
||||||
|
payload = {"results": favorites, "count": len(favorites)}
|
||||||
|
return Response(payload, status=200)
|
||||||
|
|
|
@ -39,6 +39,18 @@ def test_user_can_get_his_favorites(api_request, factories, logged_in_client, cl
|
||||||
assert response.data["results"] == expected
|
assert response.data["results"] == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_user_can_retrieve_all_favorites_at_once(
|
||||||
|
api_request, factories, logged_in_client, client
|
||||||
|
):
|
||||||
|
favorite = factories["favorites.TrackFavorite"](user=logged_in_client.user)
|
||||||
|
factories["favorites.TrackFavorite"]()
|
||||||
|
url = reverse("api:v1:favorites:tracks-all")
|
||||||
|
response = logged_in_client.get(url, {"user": logged_in_client.user.pk})
|
||||||
|
expected = [{"track": favorite.track.id, "id": favorite.id}]
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.data["results"] == expected
|
||||||
|
|
||||||
|
|
||||||
def test_user_can_add_favorite_via_api(factories, logged_in_client, activity_muted):
|
def test_user_can_add_favorite_via_api(factories, logged_in_client, activity_muted):
|
||||||
track = factories["music.Track"]()
|
track = factories["music.Track"]()
|
||||||
url = reverse("api:v1:favorites:tracks-list")
|
url = reverse("api:v1:favorites:tracks-list")
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Performance improvement when fetching favorites, down to a single, small http request
|
|
@ -60,20 +60,12 @@ export default {
|
||||||
page_size: 50,
|
page_size: 50,
|
||||||
ordering: '-creation_date'
|
ordering: '-creation_date'
|
||||||
}
|
}
|
||||||
let promise
|
let promise = axios.get('favorites/tracks/all/', {params: params})
|
||||||
if (url) {
|
|
||||||
promise = axios.get(url)
|
|
||||||
} else {
|
|
||||||
promise = axios.get('favorites/tracks/', {params: params})
|
|
||||||
}
|
|
||||||
return promise.then((response) => {
|
return promise.then((response) => {
|
||||||
logger.default.info('Fetched a batch of ' + response.data.results.length + ' favorites')
|
logger.default.info('Fetched a batch of ' + response.data.results.length + ' favorites')
|
||||||
response.data.results.forEach(result => {
|
response.data.results.forEach(result => {
|
||||||
commit('track', {id: result.track.id, value: true})
|
commit('track', {id: result.track, value: true})
|
||||||
})
|
})
|
||||||
if (response.data.next) {
|
|
||||||
dispatch('fetch', response.data.next)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue