migrate migrations; split fields into `fields.py`
This commit is contained in:
parent
fe4c876fdc
commit
601449ce08
|
@ -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]
|
|
@ -7,7 +7,7 @@ import sync.models
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('sync', '0014_alter_media_media_file'),
|
('sync', '0015_auto_20230213_0603'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
|
@ -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 = [
|
|
||||||
]
|
|
|
@ -1,5 +1,4 @@
|
||||||
import os
|
import os
|
||||||
from typing import Any, Optional, Dict
|
|
||||||
import uuid
|
import uuid
|
||||||
import json
|
import json
|
||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
|
@ -8,7 +7,6 @@ from datetime import datetime, timedelta
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.forms import MultipleChoiceField, CheckboxSelectMultiple, Field, TypedMultipleChoiceField
|
|
||||||
from django.core.files.storage import FileSystemStorage
|
from django.core.files.storage import FileSystemStorage
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django.utils import timezone
|
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,
|
from .matching import (get_best_combined_format, get_best_audio_format,
|
||||||
get_best_video_format)
|
get_best_video_format)
|
||||||
from .mediaservers import PlexMediaServer
|
from .mediaservers import PlexMediaServer
|
||||||
|
from .fields import CommaSepChoiceField
|
||||||
|
|
||||||
media_file_storage = FileSystemStorage(location=str(settings.DOWNLOAD_ROOT), base_url='/media-data/')
|
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):
|
class Source(models.Model):
|
||||||
'''
|
'''
|
||||||
A Source is a source of media. Currently, this is either a YouTube channel
|
A Source is a source of media. Currently, this is either a YouTube channel
|
||||||
|
|
Loading…
Reference in New Issue