Procházet zdrojové kódy

added production settings and database settings for pythonanywhere/azure

sleepytaco před 3 roky
rodič
revize
520ef480ba

+ 3 - 4
.gitignore

@@ -1,15 +1,14 @@
 /venv/
+.azure
 /UnTube/client_secrets.json
 /db.sqlite3
-/modules/t.json
-/modules/you.py
-/modules/youtube-api.py
-/modules/youtube-api-oauth.py
+/modules
 /.idea/
 __pycache__/
 *.log
 *.pot
 *.pyc
 /static/
+.staticfiles
 .env
 

+ 0 - 2
Procfile

@@ -1,2 +0,0 @@
-release: python manage.py migrate
-web: gunicorn UnTube.wsgi --log-file -

+ 4 - 1
UnTube/asgi.py

@@ -11,6 +11,9 @@ import os
 
 from django.core.asgi import get_asgi_application
 
-os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'UnTube.settings')
+# If WEBSITE_HOSTNAME is defined as an environment variable, then we're running
+# on Azure App Service and should use the production settings in production.py.
+settings_module = "UnTube.production" if 'WEBSITE_HOSTNAME' in os.environ else 'UnTube.settings'
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', settings_module)
 
 application = get_asgi_application()

+ 57 - 0
UnTube/production.py

@@ -0,0 +1,57 @@
+from .settings import *
+import os
+
+DEBUG = False
+CSRF_COOKIE_SECURE = True
+SESSION_COOKIE_SECURE = True
+SECURE_SSL_REDIRECT = True
+
+# Configure the domain name using the environment variable
+# that Azure automatically creates for us.
+# ALLOWED_HOSTS = [os.environ['WEBSITE_HOSTNAME'], '127.0.0.1'] if 'WEBSITE_HOSTNAME' in os.environ else []
+
+# configure the domain name using the environment variable found on pythonanywhere
+ALLOWED_HOSTS = ['bakaabu.pythonanywhere.com'] if 'PYTHONANYWHERE_SITE' in os.environ else []
+SITE_ID = 8
+
+# WhiteNoise configuration
+MIDDLEWARE = [
+    'django.middleware.security.SecurityMiddleware',
+    # Add whitenoise middleware after the security middleware
+    'whitenoise.middleware.WhiteNoiseMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
+STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
+
+# DBHOST is only the server name, not the full URL (azure)
+hostname = os.environ['DBHOST']
+
+# Configure Postgres database; the full username is username@servername,
+# which we construct using the DBHOST value.
+# DATABASES = {
+#    'default': {
+#        'ENGINE': 'django.db.backends.postgresql',
+#        'NAME': os.environ['DBNAME'],
+#        'HOST': hostname + ".postgres.database.azure.com",
+#        'USER': os.environ['DBUSER'] + "@" + hostname,
+#        'PASSWORD': os.environ['DBPASS']
+#    }
+# }
+
+# Configure MySQL database on pythonanywhere
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.mysql',
+        'NAME': f'{os.environ["DBUSER"]}${os.environ["DBNAME"]}',
+        'USER': f'{os.environ["DBUSER"]}',
+        'PASSWORD': f'{os.environ["DBPASS"]}',
+        'HOST': hostname,
+    }
+}

+ 1 - 5
UnTube/settings.py

@@ -29,7 +29,7 @@ YOUTUBE_V3_API_KEY = SECRETS['YOUTUBE_V3_API_KEY']
 # SECURITY WARNING: don't run with debug turned on in production!
 DEBUG = True
 
-ALLOWED_HOSTS = ['127.0.0.1', 'bakaabu.pythonanywhere.com']
+ALLOWED_HOSTS = ['127.0.0.1']
 
 # Application definition
 INSTALLED_APPS = [
@@ -169,7 +169,3 @@ STATIC_ROOT = os.path.join(BASE_DIR, 'static')
 # Default primary key field type
 # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
 DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
-
-# django_heroku.settings(locals())
-# options = DATABASES['default'].get('OPTIONS', {})
-# options.pop('sslmode', None)

+ 4 - 1
UnTube/wsgi.py

@@ -11,6 +11,9 @@ import os
 
 from django.core.wsgi import get_wsgi_application
 
-os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'UnTube.settings')
+# If WEBSITE_HOSTNAME is defined as an environment variable, then we're running
+# on Azure App Service and should use the production settings in production.py.
+settings_module = "UnTube.production" if 'WEBSITE_HOSTNAME' in os.environ else 'UnTube.settings'
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', settings_module)
 
 application = get_wsgi_application()

+ 76 - 0
apps/main/migrations/0049_auto_20210803_2233.py

@@ -0,0 +1,76 @@
+# Generated by Django 3.2.6 on 2021-08-04 03:33
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('main', '0048_video_is_planned_to_watch'),
+    ]
+
+    operations = [
+        migrations.DeleteModel(
+            name='Channel',
+        ),
+        migrations.AlterField(
+            model_name='playlist',
+            name='channel_id',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='playlist',
+            name='channel_name',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='playlist',
+            name='description',
+            field=models.TextField(default='No description'),
+        ),
+        migrations.AlterField(
+            model_name='playlist',
+            name='playlist_yt_player_HTML',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='playlist',
+            name='thumbnail_url',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='playlist',
+            name='user_notes',
+            field=models.TextField(default=''),
+        ),
+        migrations.AlterField(
+            model_name='video',
+            name='channel_id',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='video',
+            name='channel_name',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='video',
+            name='description',
+            field=models.TextField(default=''),
+        ),
+        migrations.AlterField(
+            model_name='video',
+            name='thumbnail_url',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='video',
+            name='user_notes',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AlterField(
+            model_name='video',
+            name='yt_player_HTML',
+            field=models.TextField(blank=True),
+        ),
+    ]

+ 17 - 32
apps/main/models.py

@@ -152,7 +152,7 @@ class PlaylistManager(models.Manager):
             playlist_ids.append(playlist_id)
 
             # check if this playlist already exists in user's untube collection
-            if user.playlists.filter(playlist_id=playlist_id).exists():
+            if user.playlists.filter(Q(playlist_id=playlist_id) & Q(is_in_db=True)).exists():
                 playlist = user.playlists.get(playlist_id=playlist_id)
                 print(f"PLAYLIST {playlist.name} ({playlist_id}) ALREADY EXISTS IN DB")
 
@@ -169,6 +169,9 @@ class PlaylistManager(models.Manager):
                     return result
             else:  # no such playlist in database
                 print(f"CREATING {item['snippet']['title']} ({playlist_id})")
+                if user.playlists.filter(Q(playlist_id=playlist_id) & Q(is_in_db=False)).exists():
+                    unimported_playlist = user.playlists.filter(Q(playlist_id=playlist_id) & Q(is_in_db=False)).first()
+                    unimported_playlist.delete()
 
                 ### MAKE THE PLAYLIST AND LINK IT TO CURRENT_USER
                 playlist = Playlist(  # create the playlist and link it to current user
@@ -979,7 +982,7 @@ class PlaylistManager(models.Manager):
 
                 if not playlist.playlist_items.filter(video__video_id=video.video_id).exists():
                     playlist.videos.remove(video)
-                    #if video.playlists.all().count() == 0:  # also delete the video if it is not found in other playlists
+                    # if video.playlists.all().count() == 0:  # also delete the video if it is not found in other playlists
                     #    video.delete()
 
                 if playlist_id == "LL":
@@ -1256,24 +1259,6 @@ class Tag(models.Model):
     updated_at = models.DateTimeField(auto_now=True)
 
 
-class Channel(models.Model):
-    channel_id = models.CharField(max_length=420, default="")
-    name = models.CharField(max_length=420, default="")
-    description = models.CharField(max_length=420, default="No description")
-    thumbnail_url = models.CharField(max_length=420, blank=True)
-    published_at = models.DateTimeField(blank=True)
-
-    # statistics
-    view_count = models.IntegerField(default=0)
-    subscriberCount = models.IntegerField(default=0)
-    hidden_subscriber_count = models.BooleanField(null=True)
-    video_ount = models.IntegerField(default=0)
-    is_private = models.BooleanField(null=True)
-
-    created_at = models.DateTimeField(auto_now_add=True)
-    updated_at = models.DateTimeField(auto_now=True)
-
-
 class Video(models.Model):
     untube_user = models.ForeignKey(User, related_name="videos", on_delete=models.CASCADE, null=True)
 
@@ -1282,9 +1267,9 @@ class Video(models.Model):
     name = models.CharField(max_length=100, blank=True)
     duration = models.CharField(max_length=100, blank=True)
     duration_in_seconds = models.IntegerField(default=0)
-    thumbnail_url = models.CharField(max_length=420, blank=True)
+    thumbnail_url = models.TextField(blank=True)
     published_at = models.DateTimeField(blank=True, null=True)
-    description = models.CharField(max_length=420, default="")
+    description = models.TextField(default="")
     has_cc = models.BooleanField(default=False, blank=True, null=True)
     liked = models.BooleanField(default=False)  # whether this video liked on YouTube by user or not
 
@@ -1295,12 +1280,12 @@ class Video(models.Model):
     dislike_count = models.IntegerField(default=0)
     comment_count = models.IntegerField(default=0)
 
-    yt_player_HTML = models.CharField(max_length=420, blank=True)
+    yt_player_HTML = models.TextField(blank=True)
 
     # video is made by this channel
     # channel = models.ForeignKey(Channel, related_name="videos", on_delete=models.CASCADE)
-    channel_id = models.CharField(max_length=420, blank=True)
-    channel_name = models.CharField(max_length=420, blank=True)
+    channel_id = models.TextField(blank=True)
+    channel_name = models.TextField(blank=True)
 
     # which playlist this video belongs to, and position of that video in the playlist (i.e ALL videos belong to some pl)
     # playlist = models.ForeignKey(Playlist, related_name="videos", on_delete=models.CASCADE)
@@ -1324,7 +1309,7 @@ class Video(models.Model):
     is_favorite = models.BooleanField(default=False, blank=True)  # mark video as favorite
     num_of_accesses = models.IntegerField(default=0)  # tracks num of times this video was clicked on by user
     user_label = models.CharField(max_length=100, blank=True)  # custom user given name for this video
-    user_notes = models.CharField(max_length=420, blank=True)  # user can take notes on the video and save them
+    user_notes = models.TextField(blank=True)  # user can take notes on the video and save them
 
     created_at = models.DateTimeField(auto_now_add=True)
     updated_at = models.DateTimeField(auto_now=True)
@@ -1340,22 +1325,22 @@ class Playlist(models.Model):
     untube_user = models.ForeignKey(User, related_name="playlists", on_delete=models.CASCADE, null=True)
 
     # playlist is made by this channel
-    channel_id = models.CharField(max_length=420, blank=True)
-    channel_name = models.CharField(max_length=420, blank=True)
+    channel_id = models.TextField(blank=True)
+    channel_name = models.TextField(blank=True)
 
     # playlist details
     is_yt_mix = models.BooleanField(default=False)
     playlist_id = models.CharField(max_length=150)
     name = models.CharField(max_length=150, blank=True)  # YT PLAYLIST NAMES CAN ONLY HAVE MAX OF 150 CHARS
-    thumbnail_url = models.CharField(max_length=420, blank=True)
-    description = models.CharField(max_length=420, default="No description")
+    thumbnail_url = models.TextField(blank=True)
+    description = models.TextField(default="No description")
     video_count = models.IntegerField(default=0)
     published_at = models.DateTimeField(blank=True)
     is_private_on_yt = models.BooleanField(default=False)
     videos = models.ManyToManyField(Video, related_name="playlists")
 
     # eg. "<iframe width=\"640\" height=\"360\" src=\"http://www.youtube.com/embed/videoseries?list=PLFuZstFnF1jFwMDffUhV81h0xeff0TXzm\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>"
-    playlist_yt_player_HTML = models.CharField(max_length=420, blank=True)
+    playlist_yt_player_HTML = models.TextField(blank=True)
 
     playlist_duration = models.CharField(max_length=69, blank=True)  # string version of playlist dureation
     playlist_duration_in_seconds = models.IntegerField(default=0)
@@ -1366,7 +1351,7 @@ class Playlist(models.Model):
     last_watched = models.DateTimeField(auto_now_add=True, null=True)
 
     # manage playlist
-    user_notes = models.CharField(max_length=420, default="")  # user can take notes on the playlist and save them
+    user_notes = models.TextField(default="")  # user can take notes on the playlist and save them
     user_label = models.CharField(max_length=100, default="")  # custom user given name for this playlist
     marked_as = models.CharField(default="none",
                                  max_length=100)  # can be set to "none", "watching", "on-hold", "plan-to-watch"

+ 1 - 1
apps/main/templates/home.html

@@ -8,7 +8,7 @@
             <p>
                 There's no playlists in your UnTube right now. You can change that by heading over to <a href="{% url 'manage_playlists' %}" class="btn btn-sm btn-primary">Manage</a> to import some public playlists into your UnTube.
                 {% if not user.profile.imported_yt_playlists %}
-                    Or you could always head over to your <a href="{% url 'profile' %}" class="btn btn-sm btn-primary">Profile</a> to import all of your public/private YouTube playlists.
+                    Or you could always head over to your <a href="{% url 'settings' %}" class="btn btn-sm btn-primary">Profile</a> to import all of your public/private YouTube playlists.
                 {% else %}
                     Keep in mind that your own YouTube playlists will automatically be imported into UnTube.
                 {% endif %}

+ 28 - 0
apps/users/migrations/0014_auto_20210803_2233.py

@@ -0,0 +1,28 @@
+# Generated by Django 3.2.6 on 2021-08-04 03:33
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('users', '0013_remove_profile_auto_check_for_updates'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='profile',
+            old_name='user',
+            new_name='untube_user',
+        ),
+        migrations.AlterField(
+            model_name='profile',
+            name='manage_playlists_import_textarea',
+            field=models.TextField(default=''),
+        ),
+        migrations.AlterField(
+            model_name='profile',
+            name='yt_channel_id',
+            field=models.TextField(default=''),
+        ),
+    ]

+ 6 - 6
apps/users/models.py

@@ -20,7 +20,7 @@ class Untube(models.Model):
 
 # extension of the built in User model made by Django
 class Profile(models.Model):
-    user = models.OneToOneField(User, on_delete=models.CASCADE)
+    untube_user = models.OneToOneField(User, on_delete=models.CASCADE)
 
     created_at = models.DateTimeField(auto_now_add=True)
     updated_at = models.DateTimeField(auto_now=True)
@@ -43,7 +43,7 @@ class Profile(models.Model):
     # manage user
     objects = ProfileManager()
     show_import_page = models.BooleanField(default=True)  # shows the user tips for a week
-    yt_channel_id = models.CharField(max_length=420, default='')
+    yt_channel_id = models.TextField(default='')
     import_in_progress = models.BooleanField(
         default=False)  # if True, will not let the user access main site until they import their YT playlists
     imported_yt_playlists = models.BooleanField(default=False)  # True if user imported all their YT playlists
@@ -54,7 +54,7 @@ class Profile(models.Model):
     expires_at = models.DateTimeField(blank=True, null=True)
 
     # import playlist page
-    manage_playlists_import_textarea = models.CharField(max_length=420, default="")
+    manage_playlists_import_textarea = models.TextField(default="")
 
     # create playlist page
     create_playlist_name = models.CharField(max_length=50, default="")
@@ -65,7 +65,7 @@ class Profile(models.Model):
 
     def get_channels_list(self):
         channels_list = []
-        videos = self.user.videos.filter(Q(is_unavailable_on_yt=False) & Q(was_deleted_on_yt=False))
+        videos = self.untube_user.videos.filter(Q(is_unavailable_on_yt=False) & Q(was_deleted_on_yt=False))
 
         queryset = videos.values(
             'channel_name').annotate(channel_videos_count=Count('video_id')).order_by('-channel_videos_count')
@@ -76,13 +76,13 @@ class Profile(models.Model):
         return channels_list
 
     def get_playlists_list(self):
-        return self.user.playlists.all().filter(is_in_db=True)
+        return self.untube_user.playlists.all().filter(is_in_db=True)
 
 # as soon as one User object is created, create an associated profile object
 @receiver(post_save, sender=User)
 def create_user_profile(sender, instance, created, **kwargs):
     if created:
-        Profile.objects.create(user=instance)
+        Profile.objects.create(untube_user=instance)
 
 
 # whenever User.save() happens, Profile.save() also happens

+ 2 - 1
manage.py

@@ -6,7 +6,8 @@ import sys
 
 def main():
     """Run administrative tasks."""
-    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'UnTube.settings')
+    settings_module = "UnTube.production" if 'WEBSITE_HOSTNAME' in os.environ else 'UnTube.settings'
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', settings_module)
     try:
         from django.core.management import execute_from_command_line
     except ImportError as exc:

binární
requirements.txt


+ 1 - 3
templates/base.html

@@ -1,5 +1,4 @@
 {% load static %}
-{% with domain="http://127.0.0.1:8000/" %}
 <!doctype html>
 <html lang="en">
     <head>
@@ -131,7 +130,7 @@
 
 
         {% if user.profile.show_import_page %}
-            <meta http-equiv="refresh" content="0;url={{ domain }}import/init" />
+            <meta http-equiv="refresh" content="0;url=/import/init" />
         {% endif %}
         <nav class="navbar navbar-expand-lg navbar-light" id="navbar">
             <div class="container-fluid">
@@ -280,4 +279,3 @@
 
     </body>
 </html>
-{% endwith %}