测试gitnore

This commit is contained in:
ladeng07
2022-05-06 15:45:57 +08:00
parent 12f390949b
commit 51552904f9
2347 changed files with 120102 additions and 53549 deletions
@@ -14,8 +14,7 @@ from django.urls.exceptions import NoReverseMatch
from django.utils.html import smart_urlquote
from django.utils.http import urlencode
from django.utils.text import Truncator
from django.utils.translation import get_language
from django.utils.translation import gettext as _
from django.utils.translation import get_language, gettext as _
class FilteredSelectMultiple(forms.SelectMultiple):
@@ -25,12 +24,11 @@ class FilteredSelectMultiple(forms.SelectMultiple):
Note that the resulting JavaScript assumes that the jsi18n
catalog has been loaded in the page
"""
class Media:
js = [
"admin/js/core.js",
"admin/js/SelectBox.js",
"admin/js/SelectFilter2.js",
'admin/js/core.js',
'admin/js/SelectBox.js',
'admin/js/SelectFilter2.js',
]
def __init__(self, verbose_name, is_stacked, attrs=None, choices=()):
@@ -40,35 +38,35 @@ class FilteredSelectMultiple(forms.SelectMultiple):
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
context["widget"]["attrs"]["class"] = "selectfilter"
context['widget']['attrs']['class'] = 'selectfilter'
if self.is_stacked:
context["widget"]["attrs"]["class"] += "stacked"
context["widget"]["attrs"]["data-field-name"] = self.verbose_name
context["widget"]["attrs"]["data-is-stacked"] = int(self.is_stacked)
context['widget']['attrs']['class'] += 'stacked'
context['widget']['attrs']['data-field-name'] = self.verbose_name
context['widget']['attrs']['data-is-stacked'] = int(self.is_stacked)
return context
class AdminDateWidget(forms.DateInput):
class Media:
js = [
"admin/js/calendar.js",
"admin/js/admin/DateTimeShortcuts.js",
'admin/js/calendar.js',
'admin/js/admin/DateTimeShortcuts.js',
]
def __init__(self, attrs=None, format=None):
attrs = {"class": "vDateField", "size": "10", **(attrs or {})}
attrs = {'class': 'vDateField', 'size': '10', **(attrs or {})}
super().__init__(attrs=attrs, format=format)
class AdminTimeWidget(forms.TimeInput):
class Media:
js = [
"admin/js/calendar.js",
"admin/js/admin/DateTimeShortcuts.js",
'admin/js/calendar.js',
'admin/js/admin/DateTimeShortcuts.js',
]
def __init__(self, attrs=None, format=None):
attrs = {"class": "vTimeField", "size": "8", **(attrs or {})}
attrs = {'class': 'vTimeField', 'size': '8', **(attrs or {})}
super().__init__(attrs=attrs, format=format)
@@ -76,8 +74,7 @@ class AdminSplitDateTime(forms.SplitDateTimeWidget):
"""
A SplitDateTime Widget that has some admin-specific styling.
"""
template_name = "admin/widgets/split_datetime.html"
template_name = 'admin/widgets/split_datetime.html'
def __init__(self, attrs=None):
widgets = [AdminDateWidget, AdminTimeWidget]
@@ -87,17 +84,17 @@ class AdminSplitDateTime(forms.SplitDateTimeWidget):
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
context["date_label"] = _("Date:")
context["time_label"] = _("Time:")
context['date_label'] = _('Date:')
context['time_label'] = _('Time:')
return context
class AdminRadioSelect(forms.RadioSelect):
template_name = "admin/widgets/radio.html"
template_name = 'admin/widgets/radio.html'
class AdminFileWidget(forms.ClearableFileInput):
template_name = "admin/widgets/clearable_file_input.html"
template_name = 'admin/widgets/clearable_file_input.html'
def url_params_from_lookup_dict(lookups):
@@ -106,14 +103,14 @@ def url_params_from_lookup_dict(lookups):
attribute to a dictionary of query parameters
"""
params = {}
if lookups and hasattr(lookups, "items"):
if lookups and hasattr(lookups, 'items'):
for k, v in lookups.items():
if callable(v):
v = v()
if isinstance(v, (tuple, list)):
v = ",".join(str(x) for x in v)
v = ','.join(str(x) for x in v)
elif isinstance(v, bool):
v = ("0", "1")[v]
v = ('0', '1')[v]
else:
v = str(v)
params[k] = v
@@ -125,8 +122,7 @@ class ForeignKeyRawIdWidget(forms.TextInput):
A Widget for displaying ForeignKeys in the "raw_id" interface rather than
in a <select> box.
"""
template_name = "admin/widgets/foreign_key_raw_id.html"
template_name = 'admin/widgets/foreign_key_raw_id.html'
def __init__(self, rel, admin_site, attrs=None, using=None):
self.rel = rel
@@ -140,8 +136,7 @@ class ForeignKeyRawIdWidget(forms.TextInput):
if rel_to in self.admin_site._registry:
# The related object is registered with the same AdminSite
related_url = reverse(
"admin:%s_%s_changelist"
% (
'admin:%s_%s_changelist' % (
rel_to._meta.app_label,
rel_to._meta.model_name,
),
@@ -150,19 +145,17 @@ class ForeignKeyRawIdWidget(forms.TextInput):
params = self.url_parameters()
if params:
related_url += "?" + urlencode(params)
context["related_url"] = related_url
context["link_title"] = _("Lookup")
related_url += '?' + urlencode(params)
context['related_url'] = related_url
context['link_title'] = _('Lookup')
# The JavaScript code looks for this class.
context["widget"]["attrs"].setdefault("class", "vForeignKeyRawIdAdminField")
context['widget']['attrs'].setdefault('class', 'vForeignKeyRawIdAdminField')
else:
context["related_url"] = None
if context["widget"]["value"]:
context["link_label"], context["link_url"] = self.label_and_url_for_value(
value
)
context['related_url'] = None
if context['widget']['value']:
context['link_label'], context['link_url'] = self.label_and_url_for_value(value)
else:
context["link_label"] = None
context['link_label'] = None
return context
def base_url_parameters(self):
@@ -173,7 +166,6 @@ class ForeignKeyRawIdWidget(forms.TextInput):
def url_parameters(self):
from django.contrib.admin.views.main import TO_FIELD_VAR
params = self.base_url_parameters()
params.update({TO_FIELD_VAR: self.rel.get_related_field().name})
return params
@@ -183,20 +175,19 @@ class ForeignKeyRawIdWidget(forms.TextInput):
try:
obj = self.rel.model._default_manager.using(self.db).get(**{key: value})
except (ValueError, self.rel.model.DoesNotExist, ValidationError):
return "", ""
return '', ''
try:
url = reverse(
"%s:%s_%s_change"
% (
'%s:%s_%s_change' % (
self.admin_site.name,
obj._meta.app_label,
obj._meta.object_name.lower(),
),
args=(obj.pk,),
args=(obj.pk,)
)
except NoReverseMatch:
url = "" # Admin not registered for target model.
url = '' # Admin not registered for target model.
return Truncator(obj).words(14), url
@@ -206,29 +197,28 @@ class ManyToManyRawIdWidget(ForeignKeyRawIdWidget):
A Widget for displaying ManyToMany ids in the "raw_id" interface rather than
in a <select multiple> box.
"""
template_name = "admin/widgets/many_to_many_raw_id.html"
template_name = 'admin/widgets/many_to_many_raw_id.html'
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
if self.rel.model in self.admin_site._registry:
# The related object is registered with the same AdminSite
context["widget"]["attrs"]["class"] = "vManyToManyRawIdAdminField"
context['widget']['attrs']['class'] = 'vManyToManyRawIdAdminField'
return context
def url_parameters(self):
return self.base_url_parameters()
def label_and_url_for_value(self, value):
return "", ""
return '', ''
def value_from_datadict(self, data, files, name):
value = data.get(name)
if value:
return value.split(",")
return value.split(',')
def format_value(self, value):
return ",".join(str(v) for v in value) if value else ""
return ','.join(str(v) for v in value) if value else ''
class RelatedFieldWidgetWrapper(forms.Widget):
@@ -236,19 +226,11 @@ class RelatedFieldWidgetWrapper(forms.Widget):
This class is a wrapper to a given widget to add the add icon for the
admin interface.
"""
template_name = 'admin/widgets/related_widget_wrapper.html'
template_name = "admin/widgets/related_widget_wrapper.html"
def __init__(
self,
widget,
rel,
admin_site,
can_add_related=None,
can_change_related=False,
can_delete_related=False,
can_view_related=False,
):
def __init__(self, widget, rel, admin_site, can_add_related=None,
can_change_related=False, can_delete_related=False,
can_view_related=False):
self.needs_multipart_form = widget.needs_multipart_form
self.attrs = widget.attrs
self.choices = widget.choices
@@ -260,10 +242,10 @@ class RelatedFieldWidgetWrapper(forms.Widget):
can_add_related = rel.model in admin_site._registry
self.can_add_related = can_add_related
# XXX: The UX does not support multiple selected values.
multiple = getattr(widget, "allow_multiple_selected", False)
multiple = getattr(widget, 'allow_multiple_selected', False)
self.can_change_related = not multiple and can_change_related
# XXX: The deletion UX can be confusing when dealing with cascading deletion.
cascade = getattr(rel, "on_delete", None) is CASCADE
cascade = getattr(rel, 'on_delete', None) is CASCADE
self.can_delete_related = not multiple and not cascade and can_delete_related
self.can_view_related = not multiple and can_view_related
# so we can check if the related object is registered with this AdminSite
@@ -285,46 +267,35 @@ class RelatedFieldWidgetWrapper(forms.Widget):
return self.widget.media
def get_related_url(self, info, action, *args):
return reverse(
"admin:%s_%s_%s" % (info + (action,)),
current_app=self.admin_site.name,
args=args,
)
return reverse("admin:%s_%s_%s" % (info + (action,)),
current_app=self.admin_site.name, args=args)
def get_context(self, name, value, attrs):
from django.contrib.admin.views.main import IS_POPUP_VAR, TO_FIELD_VAR
rel_opts = self.rel.model._meta
info = (rel_opts.app_label, rel_opts.model_name)
self.widget.choices = self.choices
url_params = "&".join(
"%s=%s" % param
for param in [
(TO_FIELD_VAR, self.rel.get_related_field().name),
(IS_POPUP_VAR, 1),
]
)
url_params = '&'.join("%s=%s" % param for param in [
(TO_FIELD_VAR, self.rel.get_related_field().name),
(IS_POPUP_VAR, 1),
])
context = {
"rendered_widget": self.widget.render(name, value, attrs),
"is_hidden": self.is_hidden,
"name": name,
"url_params": url_params,
"model": rel_opts.verbose_name,
"can_add_related": self.can_add_related,
"can_change_related": self.can_change_related,
"can_delete_related": self.can_delete_related,
"can_view_related": self.can_view_related,
'rendered_widget': self.widget.render(name, value, attrs),
'is_hidden': self.is_hidden,
'name': name,
'url_params': url_params,
'model': rel_opts.verbose_name,
'can_add_related': self.can_add_related,
'can_change_related': self.can_change_related,
'can_delete_related': self.can_delete_related,
'can_view_related': self.can_view_related,
}
if self.can_add_related:
context["add_related_url"] = self.get_related_url(info, "add")
context['add_related_url'] = self.get_related_url(info, 'add')
if self.can_delete_related:
context["delete_related_template_url"] = self.get_related_url(
info, "delete", "__fk__"
)
context['delete_related_template_url'] = self.get_related_url(info, 'delete', '__fk__')
if self.can_view_related or self.can_change_related:
context["change_related_template_url"] = self.get_related_url(
info, "change", "__fk__"
)
context['change_related_template_url'] = self.get_related_url(info, 'change', '__fk__')
return context
def value_from_datadict(self, data, files, name):
@@ -339,112 +310,67 @@ class RelatedFieldWidgetWrapper(forms.Widget):
class AdminTextareaWidget(forms.Textarea):
def __init__(self, attrs=None):
super().__init__(attrs={"class": "vLargeTextField", **(attrs or {})})
super().__init__(attrs={'class': 'vLargeTextField', **(attrs or {})})
class AdminTextInputWidget(forms.TextInput):
def __init__(self, attrs=None):
super().__init__(attrs={"class": "vTextField", **(attrs or {})})
super().__init__(attrs={'class': 'vTextField', **(attrs or {})})
class AdminEmailInputWidget(forms.EmailInput):
def __init__(self, attrs=None):
super().__init__(attrs={"class": "vTextField", **(attrs or {})})
super().__init__(attrs={'class': 'vTextField', **(attrs or {})})
class AdminURLFieldWidget(forms.URLInput):
template_name = "admin/widgets/url.html"
template_name = 'admin/widgets/url.html'
def __init__(self, attrs=None, validator_class=URLValidator):
super().__init__(attrs={"class": "vURLField", **(attrs or {})})
super().__init__(attrs={'class': 'vURLField', **(attrs or {})})
self.validator = validator_class()
def get_context(self, name, value, attrs):
try:
self.validator(value if value else "")
self.validator(value if value else '')
url_valid = True
except ValidationError:
url_valid = False
context = super().get_context(name, value, attrs)
context["current_label"] = _("Currently:")
context["change_label"] = _("Change:")
context["widget"]["href"] = (
smart_urlquote(context["widget"]["value"]) if value else ""
)
context["url_valid"] = url_valid
context['current_label'] = _('Currently:')
context['change_label'] = _('Change:')
context['widget']['href'] = smart_urlquote(context['widget']['value']) if value else ''
context['url_valid'] = url_valid
return context
class AdminIntegerFieldWidget(forms.NumberInput):
class_name = "vIntegerField"
class_name = 'vIntegerField'
def __init__(self, attrs=None):
super().__init__(attrs={"class": self.class_name, **(attrs or {})})
super().__init__(attrs={'class': self.class_name, **(attrs or {})})
class AdminBigIntegerFieldWidget(AdminIntegerFieldWidget):
class_name = "vBigIntegerField"
class_name = 'vBigIntegerField'
class AdminUUIDInputWidget(forms.TextInput):
def __init__(self, attrs=None):
super().__init__(attrs={"class": "vUUIDField", **(attrs or {})})
super().__init__(attrs={'class': 'vUUIDField', **(attrs or {})})
# Mapping of lowercase language codes [returned by Django's get_language()] to
# language codes supported by select2.
# See django/contrib/admin/static/admin/js/vendor/select2/i18n/*
SELECT2_TRANSLATIONS = {
x.lower(): x
for x in [
"ar",
"az",
"bg",
"ca",
"cs",
"da",
"de",
"el",
"en",
"es",
"et",
"eu",
"fa",
"fi",
"fr",
"gl",
"he",
"hi",
"hr",
"hu",
"id",
"is",
"it",
"ja",
"km",
"ko",
"lt",
"lv",
"mk",
"ms",
"nb",
"nl",
"pl",
"pt-BR",
"pt",
"ro",
"ru",
"sk",
"sr-Cyrl",
"sr",
"sv",
"th",
"tr",
"uk",
"vi",
]
}
SELECT2_TRANSLATIONS.update({"zh-hans": "zh-CN", "zh-hant": "zh-TW"})
SELECT2_TRANSLATIONS = {x.lower(): x for x in [
'ar', 'az', 'bg', 'ca', 'cs', 'da', 'de', 'el', 'en', 'es', 'et',
'eu', 'fa', 'fi', 'fr', 'gl', 'he', 'hi', 'hr', 'hu', 'id', 'is',
'it', 'ja', 'km', 'ko', 'lt', 'lv', 'mk', 'ms', 'nb', 'nl', 'pl',
'pt-BR', 'pt', 'ro', 'ru', 'sk', 'sr-Cyrl', 'sr', 'sv', 'th',
'tr', 'uk', 'vi',
]}
SELECT2_TRANSLATIONS.update({'zh-hans': 'zh-CN', 'zh-hant': 'zh-TW'})
class AutocompleteMixin:
@@ -454,8 +380,7 @@ class AutocompleteMixin:
Renders the necessary data attributes for select2 and adds the static form
media.
"""
url_name = "%s:autocomplete"
url_name = '%s:autocomplete'
def __init__(self, field, admin_site, attrs=None, choices=(), using=None):
self.field = field
@@ -463,7 +388,6 @@ class AutocompleteMixin:
self.db = using
self.choices = choices
self.attrs = {} if attrs is None else attrs.copy()
self.i18n_name = SELECT2_TRANSLATIONS.get(get_language())
def get_url(self):
return reverse(self.url_name % self.admin_site.name)
@@ -477,25 +401,20 @@ class AutocompleteMixin:
https://select2.org/configuration/data-attributes#nested-subkey-options
"""
attrs = super().build_attrs(base_attrs, extra_attrs=extra_attrs)
attrs.setdefault("class", "")
attrs.update(
{
"data-ajax--cache": "true",
"data-ajax--delay": 250,
"data-ajax--type": "GET",
"data-ajax--url": self.get_url(),
"data-app-label": self.field.model._meta.app_label,
"data-model-name": self.field.model._meta.model_name,
"data-field-name": self.field.name,
"data-theme": "admin-autocomplete",
"data-allow-clear": json.dumps(not self.is_required),
"data-placeholder": "", # Allows clearing of the input.
"lang": self.i18n_name,
"class": attrs["class"]
+ (" " if attrs["class"] else "")
+ "admin-autocomplete",
}
)
attrs.setdefault('class', '')
attrs.update({
'data-ajax--cache': 'true',
'data-ajax--delay': 250,
'data-ajax--type': 'GET',
'data-ajax--url': self.get_url(),
'data-app-label': self.field.model._meta.app_label,
'data-model-name': self.field.model._meta.model_name,
'data-field-name': self.field.name,
'data-theme': 'admin-autocomplete',
'data-allow-clear': json.dumps(not self.is_required),
'data-placeholder': '', # Allows clearing of the input.
'class': attrs['class'] + (' ' if attrs['class'] else '') + 'admin-autocomplete',
})
return attrs
def optgroups(self, name, value, attr=None):
@@ -504,57 +423,46 @@ class AutocompleteMixin:
groups = [default]
has_selected = False
selected_choices = {
str(v) for v in value if str(v) not in self.choices.field.empty_values
str(v) for v in value
if str(v) not in self.choices.field.empty_values
}
if not self.is_required and not self.allow_multiple_selected:
default[1].append(self.create_option(name, "", "", False, 0))
default[1].append(self.create_option(name, '', '', False, 0))
remote_model_opts = self.field.remote_field.model._meta
to_field_name = getattr(
self.field.remote_field, "field_name", remote_model_opts.pk.attname
)
to_field_name = getattr(self.field.remote_field, 'field_name', remote_model_opts.pk.attname)
to_field_name = remote_model_opts.get_field(to_field_name).attname
choices = (
(getattr(obj, to_field_name), self.choices.field.label_from_instance(obj))
for obj in self.choices.queryset.using(self.db).filter(
**{"%s__in" % to_field_name: selected_choices}
)
for obj in self.choices.queryset.using(self.db).filter(**{'%s__in' % to_field_name: selected_choices})
)
for option_value, option_label in choices:
selected = str(option_value) in value and (
has_selected is False or self.allow_multiple_selected
selected = (
str(option_value) in value and
(has_selected is False or self.allow_multiple_selected)
)
has_selected |= selected
index = len(default[1])
subgroup = default[1]
subgroup.append(
self.create_option(
name, option_value, option_label, selected_choices, index
)
)
subgroup.append(self.create_option(name, option_value, option_label, selected_choices, index))
return groups
@property
def media(self):
extra = "" if settings.DEBUG else ".min"
i18n_file = (
("admin/js/vendor/select2/i18n/%s.js" % self.i18n_name,)
if self.i18n_name
else ()
)
extra = '' if settings.DEBUG else '.min'
i18n_name = SELECT2_TRANSLATIONS.get(get_language())
i18n_file = ('admin/js/vendor/select2/i18n/%s.js' % i18n_name,) if i18n_name else ()
return forms.Media(
js=(
"admin/js/vendor/jquery/jquery%s.js" % extra,
"admin/js/vendor/select2/select2.full%s.js" % extra,
)
+ i18n_file
+ (
"admin/js/jquery.init.js",
"admin/js/autocomplete.js",
'admin/js/vendor/jquery/jquery%s.js' % extra,
'admin/js/vendor/select2/select2.full%s.js' % extra,
) + i18n_file + (
'admin/js/jquery.init.js',
'admin/js/autocomplete.js',
),
css={
"screen": (
"admin/css/vendor/select2/select2%s.css" % extra,
"admin/css/autocomplete.css",
'screen': (
'admin/css/vendor/select2/select2%s.css' % extra,
'admin/css/autocomplete.css',
),
},
)