From 601449ce08a187c0aa132ae89a6d78eaa07f20f5 Mon Sep 17 00:00:00 2001 From: KuhnChris Date: Sun, 19 Feb 2023 23:44:48 +0100 Subject: [PATCH] migrate migrations; split fields into `fields.py` --- tubesync/sync/fields.py | 109 ++++++++++++++++++ ...214_2052.py => 0016_auto_20230214_2052.py} | 2 +- ...o_20230213_0603_0015_auto_20230214_2052.py | 14 --- tubesync/sync/models.py | 107 +---------------- 4 files changed, 111 insertions(+), 121 deletions(-) create mode 100644 tubesync/sync/fields.py rename tubesync/sync/migrations/{0015_auto_20230214_2052.py => 0016_auto_20230214_2052.py} (96%) delete mode 100644 tubesync/sync/migrations/0016_merge_0015_auto_20230213_0603_0015_auto_20230214_2052.py diff --git a/tubesync/sync/fields.py b/tubesync/sync/fields.py new file mode 100644 index 0000000..0038ab1 --- /dev/null +++ b/tubesync/sync/fields.py @@ -0,0 +1,109 @@ +from django.forms import MultipleChoiceField, CheckboxSelectMultiple, Field, TypedMultipleChoiceField +from django.db import models +from typing import Any, Optional, Dict +from django.utils.translation import gettext_lazy as _ + +# this is a form field! +class CustomCheckboxSelectMultiple(CheckboxSelectMultiple): + template_name = 'widgets/checkbox_select.html' + option_template_name = 'widgets/checkbox_option.html' + + def get_context(self, name: str, value: Any, attrs) -> Dict[str, Any]: + ctx = super().get_context(name, value, attrs)['widget'] + ctx["multipleChoiceProperties"] = [] + for _group, options, _index in ctx["optgroups"]: + for option in options: + if not isinstance(value,str) and not isinstance(value,list) and ( option["value"] in value.selected_choices or ( value.allow_all and value.all_choice in value.selected_choices ) ): + checked = True + else: + checked = False + + ctx["multipleChoiceProperties"].append({ + "template_name": option["template_name"], + "type": option["type"], + "value": option["value"], + "label": option["label"], + "name": option["name"], + "checked": checked}) + + return { 'widget': ctx } + +# this is a database field! +class CommaSepChoiceField(models.Field): + "Implements comma-separated storage of lists" + + def __init__(self, separator=",", possible_choices=(("","")), all_choice="", all_label="All", allow_all=False, *args, **kwargs): + self.separator = separator + self.possible_choices = possible_choices + self.selected_choices = [] + self.allow_all = allow_all + self.all_label = all_label + self.all_choice = all_choice + super().__init__(*args, **kwargs) + + def deconstruct(self): + name, path, args, kwargs = super().deconstruct() + if self.separator != ",": + kwargs['separator'] = self.separator + kwargs['possible_choices'] = self.possible_choices + return name, path, args, kwargs + + def db_type(self, _connection): + return 'char(1024)' + + def get_my_choices(self): + choiceArray = [] + if self.possible_choices is None: + return choiceArray + if self.allow_all: + choiceArray.append((self.all_choice, _(self.all_label))) + + for t in self.possible_choices: + choiceArray.append(t) + + return choiceArray + + def formfield(self, **kwargs): + # This is a fairly standard way to set up some defaults + # while letting the caller override them. + defaults = {'form_class': MultipleChoiceField, + 'choices': self.get_my_choices, + 'widget': CustomCheckboxSelectMultiple, + 'label': '', + 'required': False} + defaults.update(kwargs) + #del defaults.required + return super().formfield(**defaults) + + def deconstruct(self): + name, path, args, kwargs = super().deconstruct() + # Only include kwarg if it's not the default + if self.separator != ",": + kwargs['separator'] = self.separator + return name, path, args, kwargs + + def from_db_value(self, value, expr, conn): + if value is None: + self.selected_choices = [] + else: + self.selected_choices = value.split(",") + + return self + + def get_prep_value(self, value): + if value is None: + return "" + if not isinstance(value,list): + return "" + + if self.all_choice not in value: + return ",".join(value) + else: + return self.all_choice + + def get_text_for_value(self, val): + fval = [i for i in self.possible_choices if i[0] == val] + if len(fval) <= 0: + return [] + else: + return fval[0][1] diff --git a/tubesync/sync/migrations/0015_auto_20230214_2052.py b/tubesync/sync/migrations/0016_auto_20230214_2052.py similarity index 96% rename from tubesync/sync/migrations/0015_auto_20230214_2052.py rename to tubesync/sync/migrations/0016_auto_20230214_2052.py index aab006f..ffba195 100644 --- a/tubesync/sync/migrations/0015_auto_20230214_2052.py +++ b/tubesync/sync/migrations/0016_auto_20230214_2052.py @@ -7,7 +7,7 @@ import sync.models class Migration(migrations.Migration): dependencies = [ - ('sync', '0014_alter_media_media_file'), + ('sync', '0015_auto_20230213_0603'), ] operations = [ diff --git a/tubesync/sync/migrations/0016_merge_0015_auto_20230213_0603_0015_auto_20230214_2052.py b/tubesync/sync/migrations/0016_merge_0015_auto_20230213_0603_0015_auto_20230214_2052.py deleted file mode 100644 index 8b7618b..0000000 --- a/tubesync/sync/migrations/0016_merge_0015_auto_20230213_0603_0015_auto_20230214_2052.py +++ /dev/null @@ -1,14 +0,0 @@ -# Generated by Django 3.2.18 on 2023-02-18 10:49 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('sync', '0015_auto_20230213_0603'), - ('sync', '0015_auto_20230214_2052'), - ] - - operations = [ - ] diff --git a/tubesync/sync/models.py b/tubesync/sync/models.py index a40970f..0ecb0a6 100644 --- a/tubesync/sync/models.py +++ b/tubesync/sync/models.py @@ -1,5 +1,4 @@ import os -from typing import Any, Optional, Dict import uuid import json from xml.etree import ElementTree @@ -8,7 +7,6 @@ from datetime import datetime, timedelta from pathlib import Path from django.conf import settings from django.db import models -from django.forms import MultipleChoiceField, CheckboxSelectMultiple, Field, TypedMultipleChoiceField from django.core.files.storage import FileSystemStorage from django.utils.text import slugify from django.utils import timezone @@ -21,113 +19,10 @@ from .utils import seconds_to_timestr, parse_media_format from .matching import (get_best_combined_format, get_best_audio_format, get_best_video_format) from .mediaservers import PlexMediaServer - +from .fields import CommaSepChoiceField media_file_storage = FileSystemStorage(location=str(settings.DOWNLOAD_ROOT), base_url='/media-data/') -class CustomCheckboxSelectMultiple(CheckboxSelectMultiple): - template_name = 'widgets/checkbox_select.html' - option_template_name = 'widgets/checkbox_option.html' - - def get_context(self, name: str, value: Any, attrs) -> Dict[str, Any]: - ctx = super().get_context(name, value, attrs)['widget'] - ctx["multipleChoiceProperties"] = [] - for _group, options, _index in ctx["optgroups"]: - for option in options: - if not isinstance(value,str) and not isinstance(value,list) and ( option["value"] in value.selected_choices or ( value.allow_all and value.all_choice in value.selected_choices ) ): - checked = True - else: - checked = False - - ctx["multipleChoiceProperties"].append({ - "template_name": option["template_name"], - "type": option["type"], - "value": option["value"], - "label": option["label"], - "name": option["name"], - "checked": checked}) - - return { 'widget': ctx } - -class CommaSepChoiceField(models.Field): - "Implements comma-separated storage of lists" - - def __init__(self, separator=",", possible_choices=(("","")), all_choice="", all_label="All", allow_all=False, *args, **kwargs): - self.separator = separator - self.possible_choices = possible_choices - self.selected_choices = [] - self.allow_all = allow_all - self.all_label = all_label - self.all_choice = all_choice - super().__init__(*args, **kwargs) - - def deconstruct(self): - name, path, args, kwargs = super().deconstruct() - if self.separator != ",": - kwargs['separator'] = self.separator - kwargs['possible_choices'] = self.possible_choices - return name, path, args, kwargs - - def db_type(self, _connection): - return 'char(1024)' - - def get_my_choices(self): - choiceArray = [] - if self.possible_choices is None: - return choiceArray - if self.allow_all: - choiceArray.append((self.all_choice, _(self.all_label))) - - for t in self.possible_choices: - choiceArray.append(t) - - return choiceArray - - def formfield(self, **kwargs): - # This is a fairly standard way to set up some defaults - # while letting the caller override them. - defaults = {'form_class': MultipleChoiceField, - 'choices': self.get_my_choices, - 'widget': CustomCheckboxSelectMultiple, - 'label': '', - 'required': False} - defaults.update(kwargs) - #del defaults.required - return super().formfield(**defaults) - - def deconstruct(self): - name, path, args, kwargs = super().deconstruct() - # Only include kwarg if it's not the default - if self.separator != ",": - kwargs['separator'] = self.separator - return name, path, args, kwargs - - def from_db_value(self, value, expr, conn): - if value is None: - self.selected_choices = [] - else: - self.selected_choices = value.split(",") - - return self - - def get_prep_value(self, value): - if value is None: - return "" - if not isinstance(value,list): - return "" - - if self.all_choice not in value: - return ",".join(value) - else: - return self.all_choice - - def get_text_for_value(self, val): - fval = [i for i in self.possible_choices if i[0] == val] - if len(fval) <= 0: - return [] - else: - return fval[0][1] - class Source(models.Model): ''' A Source is a source of media. Currently, this is either a YouTube channel