mirror of
https://github.com/Alexander-D-Karpov/akarpov
synced 2024-11-27 10:03:43 +03:00
Compare commits
22 Commits
2b2c16db2d
...
4aa1d207aa
Author | SHA1 | Date | |
---|---|---|---|
4aa1d207aa | |||
f5545ed7d4 | |||
1fb6219b7c | |||
b4124d90bb | |||
a6740c4faf | |||
67dc026c7e | |||
7e188865cc | |||
4a2b86509e | |||
c6063942c2 | |||
0fa2d34e2f | |||
f6e2d1fe4b | |||
9dd23e1a01 | |||
6bce18344f | |||
c772c1a97b | |||
709bda158a | |||
e9dcccbced | |||
06afed5882 | |||
2cce8813e9 | |||
d49be5c42e | |||
64f28fc1c8 | |||
b148a3d591 | |||
00668b6f18 |
|
@ -30,6 +30,7 @@
|
||||||
)
|
)
|
||||||
from akarpov.music.services.search import search_song
|
from akarpov.music.services.search import search_song
|
||||||
from akarpov.music.tasks import listen_to_song
|
from akarpov.music.tasks import listen_to_song
|
||||||
|
from akarpov.users.models import User
|
||||||
|
|
||||||
|
|
||||||
class LikedSongsContextMixin(generics.GenericAPIView):
|
class LikedSongsContextMixin(generics.GenericAPIView):
|
||||||
|
@ -391,12 +392,27 @@ def get_queryset(self):
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
serializer = self.get_serializer(data=request.data)
|
serializer = self.get_serializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=False)
|
serializer.is_valid(raise_exception=False)
|
||||||
data = serializer.validated_data
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
song = Song.objects.cache().get(slug=data["song"])
|
song = Song.objects.cache().get(slug=self.request.data.get("song", ""))
|
||||||
except Song.DoesNotExist:
|
except Song.DoesNotExist:
|
||||||
return Response(status=404)
|
return Response(status=404)
|
||||||
|
|
||||||
|
try:
|
||||||
|
user_id = self.request.data.get("user_id", None)
|
||||||
|
if user_id:
|
||||||
|
user_id_int = None
|
||||||
|
try:
|
||||||
|
user_id_int = int(user_id)
|
||||||
|
except ValueError:
|
||||||
|
...
|
||||||
|
if user_id_int:
|
||||||
|
user = User.objects.cache().get(id=user_id_int)
|
||||||
|
if user != self.request.user:
|
||||||
|
return Response(status=403)
|
||||||
|
except User.DoesNotExist:
|
||||||
|
...
|
||||||
|
|
||||||
if self.request.user.is_authenticated:
|
if self.request.user.is_authenticated:
|
||||||
listen_to_song.apply_async(
|
listen_to_song.apply_async(
|
||||||
kwargs={
|
kwargs={
|
||||||
|
@ -406,11 +422,11 @@ def post(self, request, *args, **kwargs):
|
||||||
},
|
},
|
||||||
countdown=2,
|
countdown=2,
|
||||||
)
|
)
|
||||||
elif "user_id" in data:
|
elif "user_id" in self.request.data:
|
||||||
listen_to_song.apply_async(
|
listen_to_song.apply_async(
|
||||||
kwargs={
|
kwargs={
|
||||||
"song_id": song.id,
|
"song_id": song.id,
|
||||||
"user_id": data["user_id"],
|
"user_id": self.request.data.get("user_id", None),
|
||||||
"anon": True,
|
"anon": True,
|
||||||
},
|
},
|
||||||
countdown=2,
|
countdown=2,
|
||||||
|
|
|
@ -35,9 +35,11 @@ class SongDocument(Document):
|
||||||
name = fields.TextField(
|
name = fields.TextField(
|
||||||
attr="name",
|
attr="name",
|
||||||
fields={
|
fields={
|
||||||
"raw": fields.KeywordField(normalizer="lowercase"),
|
"raw": fields.KeywordField(),
|
||||||
|
"exact": fields.KeywordField(normalizer="lowercase"),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
suggest = fields.CompletionField()
|
||||||
|
|
||||||
meta = fields.ObjectField(dynamic=True)
|
meta = fields.ObjectField(dynamic=True)
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,11 @@ def album_name(self):
|
||||||
def artists_names(self):
|
def artists_names(self):
|
||||||
return cache_model_property(self, "_authors_names")
|
return cache_model_property(self, "_authors_names")
|
||||||
|
|
||||||
|
def get_first_author_name(self):
|
||||||
|
if self.authors:
|
||||||
|
return self.authors.first().name
|
||||||
|
return ""
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,11 @@
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from deep_translator import GoogleTranslator
|
|
||||||
|
try:
|
||||||
|
from deep_translator import GoogleTranslator # TODO: move to another service
|
||||||
|
except requests.exceptions.JSONDecodeError:
|
||||||
|
print("Failed to initialize GoogleTranslator due to external API issues.")
|
||||||
from django.core.files import File
|
from django.core.files import File
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
|
@ -122,12 +126,15 @@ def load_track(
|
||||||
album=album,
|
album=album,
|
||||||
):
|
):
|
||||||
return sng.first()
|
return sng.first()
|
||||||
|
try:
|
||||||
if not path.endswith(".mp3"):
|
if not path.endswith(".mp3"):
|
||||||
mp3_path = path.replace(path.split(".")[-1], "mp3")
|
mp3_path = path.replace(path.split(".")[-1], "mp3")
|
||||||
AudioSegment.from_file(path).export(mp3_path)
|
AudioSegment.from_file(path).export(mp3_path)
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
path = mp3_path
|
path = mp3_path
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return Song.objects.none()
|
||||||
|
|
||||||
tag = MP3(path, ID3=ID3)
|
tag = MP3(path, ID3=ID3)
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import spotipy
|
import spotipy
|
||||||
from deep_translator import GoogleTranslator
|
|
||||||
|
try:
|
||||||
|
from deep_translator import GoogleTranslator
|
||||||
|
except requests.exceptions.JSONDecodeError:
|
||||||
|
print("Failed to initialize GoogleTranslator due to external API issues.")
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.files import File
|
from django.core.files import File
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
from django.core.cache import cache
|
||||||
from django.db.models import Case, When
|
from django.db.models import Case, When
|
||||||
|
from django_elasticsearch_dsl.registries import registry
|
||||||
from elasticsearch_dsl import Q as ES_Q
|
from elasticsearch_dsl import Q as ES_Q
|
||||||
|
|
||||||
from akarpov.music.documents import SongDocument
|
from akarpov.music.documents import SongDocument
|
||||||
|
@ -10,33 +12,60 @@ def search_song(query):
|
||||||
search_query = ES_Q(
|
search_query = ES_Q(
|
||||||
"bool",
|
"bool",
|
||||||
should=[
|
should=[
|
||||||
|
ES_Q("match", name=query),
|
||||||
|
ES_Q("match", name__russian=query),
|
||||||
ES_Q(
|
ES_Q(
|
||||||
"multi_match",
|
"multi_match",
|
||||||
query=query,
|
query=query,
|
||||||
fields=["name^5", "authors.name^3", "album.name^3"],
|
fields=[
|
||||||
|
"name^5",
|
||||||
|
"name.russian^5",
|
||||||
|
"authors.name^3",
|
||||||
|
"authors.name.raw^3",
|
||||||
|
"album.name^3",
|
||||||
|
"album.name.raw^3",
|
||||||
|
"name.raw^2",
|
||||||
|
],
|
||||||
|
type="best_fields",
|
||||||
fuzziness="AUTO",
|
fuzziness="AUTO",
|
||||||
),
|
),
|
||||||
ES_Q("wildcard", name__raw=f"*{query.lower()}*"),
|
|
||||||
ES_Q(
|
ES_Q(
|
||||||
"nested",
|
"nested",
|
||||||
path="authors",
|
path="authors",
|
||||||
query=ES_Q("wildcard", authors__name__raw=f"*{query.lower()}*"),
|
query=ES_Q(
|
||||||
|
"multi_match",
|
||||||
|
query=query,
|
||||||
|
fields=["authors.name", "authors.name.raw"],
|
||||||
|
fuzziness="AUTO",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
# Correcting wildcard queries with the proper syntax:
|
||||||
|
ES_Q("wildcard", **{"name.raw": f"*{query.lower()}*"}),
|
||||||
ES_Q(
|
ES_Q(
|
||||||
"nested",
|
"nested",
|
||||||
path="album",
|
path="album",
|
||||||
query=ES_Q("wildcard", album__name__raw=f"*{query.lower()}*"),
|
query=ES_Q(
|
||||||
|
"multi_match",
|
||||||
|
query=query,
|
||||||
|
fields=["album.name", "album.name.raw"],
|
||||||
|
fuzziness="AUTO",
|
||||||
|
),
|
||||||
),
|
),
|
||||||
ES_Q("wildcard", meta__raw=f"*{query.lower()}*"),
|
# Ensuring the nested wildcard query is properly structured
|
||||||
|
ES_Q(
|
||||||
|
"nested",
|
||||||
|
path="album",
|
||||||
|
query=ES_Q("wildcard", **{"album.name.raw": f"*{query.lower()}*"}),
|
||||||
|
),
|
||||||
|
# Correcting the wildcard query for `meta.raw`
|
||||||
|
ES_Q("wildcard", **{"meta.raw": f"*{query.lower()}*"}),
|
||||||
],
|
],
|
||||||
minimum_should_match=1,
|
minimum_should_match=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
search = search.query(search_query)
|
search = search.query(search_query).extra(size=20)
|
||||||
|
|
||||||
response = search.execute()
|
response = search.execute()
|
||||||
|
|
||||||
# Check for hits and get song instances
|
|
||||||
if response.hits:
|
if response.hits:
|
||||||
hit_ids = [hit.meta.id for hit in response.hits]
|
hit_ids = [hit.meta.id for hit in response.hits]
|
||||||
songs = Song.objects.filter(id__in=hit_ids).order_by(
|
songs = Song.objects.filter(id__in=hit_ids).order_by(
|
||||||
|
@ -46,3 +75,24 @@ def search_song(query):
|
||||||
return songs
|
return songs
|
||||||
|
|
||||||
return Song.objects.none()
|
return Song.objects.none()
|
||||||
|
|
||||||
|
|
||||||
|
def autocomplete_search(query):
|
||||||
|
s = SongDocument.search()
|
||||||
|
s = s.suggest("song_suggest", query, completion={"field": "suggest"})
|
||||||
|
suggestions = s.execute().suggest.song_suggest[0].options
|
||||||
|
return [option.text for option in suggestions]
|
||||||
|
|
||||||
|
|
||||||
|
def get_popular_songs():
|
||||||
|
if "popular_songs" in cache:
|
||||||
|
return cache.get("popular_songs")
|
||||||
|
else:
|
||||||
|
songs = Song.objects.filter(played__gt=300).order_by("-played")[:10]
|
||||||
|
cache.set("popular_songs", songs, timeout=3600)
|
||||||
|
return songs
|
||||||
|
|
||||||
|
|
||||||
|
def bulk_update_index(model_class):
|
||||||
|
qs = model_class.objects.all()
|
||||||
|
registry.update(qs, bulk_size=100)
|
||||||
|
|
|
@ -75,13 +75,40 @@ def load_file_meta(track: int, user_id: int) -> str:
|
||||||
return str(song)
|
return str(song)
|
||||||
|
|
||||||
|
|
||||||
def load_playlist(link: str, user_id: int):
|
def load_url(link: str, user_id: int):
|
||||||
author = link.split("/")[4]
|
|
||||||
playlist_id = link.split("/")[-1]
|
|
||||||
|
|
||||||
client = login()
|
client = login()
|
||||||
playlist = client.users_playlists(int(playlist_id), author) # type: Playlist
|
obj_id = link.split("/")[-1]
|
||||||
for track in playlist.fetch_tracks():
|
obj_id = obj_id.split("?")[0]
|
||||||
|
try:
|
||||||
|
obj_id = int(obj_id)
|
||||||
|
except ValueError:
|
||||||
|
print("Invalid link")
|
||||||
|
return None
|
||||||
|
|
||||||
|
if "/playlists/" in link:
|
||||||
|
author = link.split("/")[4]
|
||||||
|
|
||||||
|
playlist = client.users_playlists(obj_id, author) # type: Playlist
|
||||||
|
for track in playlist.fetch_tracks():
|
||||||
|
tasks.load_ym_file_meta.apply_async(
|
||||||
|
kwargs={"track": track.track.id, "user_id": user_id}
|
||||||
|
)
|
||||||
|
elif "/album/" in link:
|
||||||
|
album = client.albums_with_tracks(obj_id)
|
||||||
|
for volume in album.volumes:
|
||||||
|
for track in volume:
|
||||||
|
tasks.load_ym_file_meta.apply_async(
|
||||||
|
kwargs={"track": track.id, "user_id": user_id}
|
||||||
|
)
|
||||||
|
elif "/artist/" in link:
|
||||||
|
artist = client.artists(obj_id)[0]
|
||||||
|
albums = artist.get_albums(page_size=100)
|
||||||
|
for album in albums:
|
||||||
|
for track in album.fetch_tracks():
|
||||||
|
tasks.load_ym_file_meta.apply_async(
|
||||||
|
kwargs={"track": track.id, "user_id": user_id}
|
||||||
|
)
|
||||||
|
else:
|
||||||
tasks.load_ym_file_meta.apply_async(
|
tasks.load_ym_file_meta.apply_async(
|
||||||
kwargs={"track": track.track.id, "user_id": user_id}
|
kwargs={"track": obj_id, "user_id": user_id}
|
||||||
)
|
)
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@shared_task(soft_time_limit=60 * 20, time_limit=60 * 30)
|
@shared_task(soft_time_limit=60 * 60, time_limit=60 * 120)
|
||||||
def list_tracks(url, user_id):
|
def list_tracks(url, user_id):
|
||||||
if "music.youtube.com" in url or "youtu.be" in url:
|
if "music.youtube.com" in url or "youtu.be" in url:
|
||||||
url = url.replace("music.youtube.com", "youtube.com")
|
url = url.replace("music.youtube.com", "youtube.com")
|
||||||
|
@ -37,7 +37,7 @@ def list_tracks(url, user_id):
|
||||||
if "spotify.com" in url:
|
if "spotify.com" in url:
|
||||||
spotify.download_url(url, user_id)
|
spotify.download_url(url, user_id)
|
||||||
elif "music.yandex.ru" in url:
|
elif "music.yandex.ru" in url:
|
||||||
yandex.load_playlist(url, user_id)
|
yandex.load_url(url, user_id)
|
||||||
if "youtube.com" in url:
|
if "youtube.com" in url:
|
||||||
if "channel" in url or "/c/" in url:
|
if "channel" in url or "/c/" in url:
|
||||||
ytmusic = ytmusicapi.YTMusic()
|
ytmusic = ytmusicapi.YTMusic()
|
||||||
|
@ -211,11 +211,18 @@ def listen_to_song(song_id, user_id=None, anon=True):
|
||||||
session_key=lastfm_token,
|
session_key=lastfm_token,
|
||||||
)
|
)
|
||||||
song = Song.objects.get(id=song_id)
|
song = Song.objects.get(id=song_id)
|
||||||
artist_name = song.artists_names
|
artist_name = song.get_first_author_name()
|
||||||
track_name = song.name
|
track_name = song.name
|
||||||
|
album_name = song.album.name
|
||||||
timestamp = int(timezone.now().timestamp())
|
timestamp = int(timezone.now().timestamp())
|
||||||
network.scrobble(
|
network.scrobble(
|
||||||
artist=artist_name, title=track_name, timestamp=timestamp
|
artist=artist_name,
|
||||||
|
title=track_name,
|
||||||
|
timestamp=timestamp,
|
||||||
|
album=album_name,
|
||||||
|
)
|
||||||
|
network.update_now_playing(
|
||||||
|
artist=artist_name, title=track_name, album=album_name
|
||||||
)
|
)
|
||||||
except UserMusicProfile.DoesNotExist:
|
except UserMusicProfile.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Welcome to music app</h1>
|
<h1>Welcome to music app</h1>
|
||||||
<p>This is mainly the backend of music, you should consider using side clients like: <a href="https://next.akarpov.ru/music">otomir23's client</a></p>
|
<p>This is mainly the backend of music, you should consider using side clients like: <a href="https://next.akarpov.ru/music">otomir23's client</a> or my <a href="https://t.me/akarpov_music_bot">inline telegram bot</a></p>
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
{% if last_fm_account %}
|
{% if last_fm_account %}
|
||||||
<p>Last.fm connected to {{ last_fm_account }}, <a href="{% url 'music:lastfm_connect' %}">reconnect</a></p>
|
<p>Last.fm connected to {{ last_fm_account }}, <a href="{% url 'music:lastfm_connect' %}">reconnect</a></p>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
from drf_spectacular.extensions import OpenApiAuthenticationExtension
|
||||||
|
from drf_spectacular.plumbing import build_bearer_security_scheme_object
|
||||||
from rest_framework.authentication import BaseAuthentication
|
from rest_framework.authentication import BaseAuthentication
|
||||||
|
|
||||||
from akarpov.users.models import UserAPIToken
|
from akarpov.users.models import User, UserAPIToken
|
||||||
from akarpov.users.tasks import set_last_active_token
|
from akarpov.users.tasks import set_last_active_token
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,4 +21,14 @@ def authenticate(self, request):
|
||||||
return None
|
return None
|
||||||
set_last_active_token.delay(token.token)
|
set_last_active_token.delay(token.token)
|
||||||
|
|
||||||
return token.user, token
|
return User.objects.cache().get(id=token.user_id), token
|
||||||
|
|
||||||
|
|
||||||
|
class UserTokenAuthenticationExtension(OpenApiAuthenticationExtension):
|
||||||
|
target_class = "akarpov.users.api.authentification.UserTokenAuthentication"
|
||||||
|
name = "UserTokenAuthentication"
|
||||||
|
|
||||||
|
def get_security_definition(self, auto_schema):
|
||||||
|
return build_bearer_security_scheme_object(
|
||||||
|
header_name="Authorization", token_prefix="Bearer"
|
||||||
|
)
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
)
|
)
|
||||||
from akarpov.users.models import User
|
from akarpov.users.models import User
|
||||||
|
|
||||||
|
from .authentification import UserTokenAuthentication # noqa: F401
|
||||||
|
|
||||||
|
|
||||||
class UserRegisterAPIViewSet(generics.CreateAPIView):
|
class UserRegisterAPIViewSet(generics.CreateAPIView):
|
||||||
"""Creates new user and sends verification email"""
|
"""Creates new user and sends verification email"""
|
||||||
|
|
|
@ -214,23 +214,16 @@ def list_tokens(request):
|
||||||
@login_required
|
@login_required
|
||||||
def create_token(request):
|
def create_token(request):
|
||||||
initial_data = {}
|
initial_data = {}
|
||||||
|
|
||||||
# Обработка параметров 'name' и 'active_until'
|
|
||||||
if "name" in request.GET:
|
if "name" in request.GET:
|
||||||
initial_data["name"] = request.GET["name"]
|
initial_data["name"] = request.GET["name"]
|
||||||
if "active_until" in request.GET:
|
if "active_until" in request.GET:
|
||||||
initial_data["active_until"] = request.GET["active_until"]
|
initial_data["active_until"] = request.GET["active_until"]
|
||||||
|
|
||||||
# Создаем QueryDict для разрешений, чтобы правильно обработать повторяющиеся ключи
|
|
||||||
permissions_query_dict = QueryDict("", mutable=True)
|
permissions_query_dict = QueryDict("", mutable=True)
|
||||||
|
|
||||||
# Разбор параметров разрешений
|
|
||||||
permissions = request.GET.getlist("permissions")
|
permissions = request.GET.getlist("permissions")
|
||||||
for perm in permissions:
|
for perm in permissions:
|
||||||
category, permission = perm.split(".")
|
category, permission = perm.split(".")
|
||||||
permissions_query_dict.update({f"permissions_{category}": [permission]})
|
permissions_query_dict.update({f"permissions_{category}": [permission]})
|
||||||
|
|
||||||
# Переводим QueryDict в обычный словарь для использования в initial
|
|
||||||
permissions_data = {key: value for key, value in permissions_query_dict.lists()}
|
permissions_data = {key: value for key, value in permissions_query_dict.lists()}
|
||||||
|
|
||||||
initial_data.update(permissions_data)
|
initial_data.update(permissions_data)
|
||||||
|
@ -242,7 +235,6 @@ def create_token(request):
|
||||||
initial=initial_data, permissions_context=UserAPIToken.permission_template
|
initial=initial_data, permissions_context=UserAPIToken.permission_template
|
||||||
)
|
)
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
print(request.POST)
|
|
||||||
form = TokenCreationForm(request.POST)
|
form = TokenCreationForm(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
new_token = form.save(commit=False)
|
new_token = form.save(commit=False)
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
"music.*": {"ops": ("fetch", "get", "list"), "timeout": 60 * 15},
|
"music.*": {"ops": ("fetch", "get", "list"), "timeout": 60 * 15},
|
||||||
"otp_totp.totpdevice": {"ops": "all", "timeout": 15 * 60},
|
"otp_totp.totpdevice": {"ops": "all", "timeout": 15 * 60},
|
||||||
"users.userapitoken": {"ops": "all", "timeout": 20 * 60},
|
"users.userapitoken": {"ops": "all", "timeout": 20 * 60},
|
||||||
|
"users.user": {"ops": "all", "timeout": 5 * 60},
|
||||||
}
|
}
|
||||||
CACHEOPS_REDIS = env.str("REDIS_URL")
|
CACHEOPS_REDIS = env.str("REDIS_URL")
|
||||||
|
|
||||||
|
@ -528,6 +529,11 @@
|
||||||
{"url": "http://127.0.0.1:8000", "description": "Local Development server"},
|
{"url": "http://127.0.0.1:8000", "description": "Local Development server"},
|
||||||
{"url": "https://new.akarpov.ru", "description": "Production server"},
|
{"url": "https://new.akarpov.ru", "description": "Production server"},
|
||||||
],
|
],
|
||||||
|
"EXTENSIONS": {
|
||||||
|
"authentication": [
|
||||||
|
"akarpov.users.api.authentification.UserTokenAuthenticationExtension"
|
||||||
|
],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# CKEDITOR
|
# CKEDITOR
|
||||||
|
@ -748,6 +754,7 @@
|
||||||
ELASTICSEARCH_DSL = {
|
ELASTICSEARCH_DSL = {
|
||||||
"default": {"hosts": env("ELASTIC_SEARCH", default="http://127.0.0.1:9200/")},
|
"default": {"hosts": env("ELASTIC_SEARCH", default="http://127.0.0.1:9200/")},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
USE_DEBUG_TOOLBAR = False
|
USE_DEBUG_TOOLBAR = False
|
||||||
|
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
||||||
|
USE_X_FORWARDED_HOST = True
|
||||||
|
USE_X_FORWARDED_PORT = True
|
||||||
|
|
Loading…
Reference in New Issue
Block a user