start-pack
This commit is contained in:
commit
3e1fa59b3d
5723 changed files with 757971 additions and 0 deletions
11
myenv/lib/python3.12/site-packages/django/forms/__init__.py
Normal file
11
myenv/lib/python3.12/site-packages/django/forms/__init__.py
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
"""
|
||||
Django validation and HTML form handling.
|
||||
"""
|
||||
|
||||
from django.core.exceptions import ValidationError # NOQA
|
||||
from django.forms.boundfield import * # NOQA
|
||||
from django.forms.fields import * # NOQA
|
||||
from django.forms.forms import * # NOQA
|
||||
from django.forms.formsets import * # NOQA
|
||||
from django.forms.models import * # NOQA
|
||||
from django.forms.widgets import * # NOQA
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
365
myenv/lib/python3.12/site-packages/django/forms/boundfield.py
Normal file
365
myenv/lib/python3.12/site-packages/django/forms/boundfield.py
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
import re
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms.utils import RenderableFieldMixin, pretty_name
|
||||
from django.forms.widgets import MultiWidget, Textarea, TextInput
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.html import format_html, html_safe
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
__all__ = ("BoundField",)
|
||||
|
||||
|
||||
class BoundField(RenderableFieldMixin):
|
||||
"A Field plus data"
|
||||
|
||||
def __init__(self, form, field, name):
|
||||
self.form = form
|
||||
self.field = field
|
||||
self.name = name
|
||||
self.html_name = form.add_prefix(name)
|
||||
self.html_initial_name = form.add_initial_prefix(name)
|
||||
self.html_initial_id = form.add_initial_prefix(self.auto_id)
|
||||
if self.field.label is None:
|
||||
self.label = pretty_name(name)
|
||||
else:
|
||||
self.label = self.field.label
|
||||
self.help_text = field.help_text or ""
|
||||
self.renderer = form.renderer
|
||||
|
||||
@cached_property
|
||||
def subwidgets(self):
|
||||
"""
|
||||
Most widgets yield a single subwidget, but others like RadioSelect and
|
||||
CheckboxSelectMultiple produce one subwidget for each choice.
|
||||
|
||||
This property is cached so that only one database query occurs when
|
||||
rendering ModelChoiceFields.
|
||||
"""
|
||||
id_ = self.field.widget.attrs.get("id") or self.auto_id
|
||||
attrs = {"id": id_} if id_ else {}
|
||||
attrs = self.build_widget_attrs(attrs)
|
||||
return [
|
||||
BoundWidget(self.field.widget, widget, self.form.renderer)
|
||||
for widget in self.field.widget.subwidgets(
|
||||
self.html_name, self.value(), attrs=attrs
|
||||
)
|
||||
]
|
||||
|
||||
def __bool__(self):
|
||||
# BoundField evaluates to True even if it doesn't have subwidgets.
|
||||
return True
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.subwidgets)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.subwidgets)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
# Prevent unnecessary reevaluation when accessing BoundField's attrs
|
||||
# from templates.
|
||||
if not isinstance(idx, (int, slice)):
|
||||
raise TypeError(
|
||||
"BoundField indices must be integers or slices, not %s."
|
||||
% type(idx).__name__
|
||||
)
|
||||
return self.subwidgets[idx]
|
||||
|
||||
@property
|
||||
def errors(self):
|
||||
"""
|
||||
Return an ErrorList (empty if there are no errors) for this field.
|
||||
"""
|
||||
return self.form.errors.get(
|
||||
self.name, self.form.error_class(renderer=self.form.renderer)
|
||||
)
|
||||
|
||||
@property
|
||||
def template_name(self):
|
||||
return self.field.template_name or self.form.renderer.field_template_name
|
||||
|
||||
def get_context(self):
|
||||
return {"field": self}
|
||||
|
||||
def as_widget(self, widget=None, attrs=None, only_initial=False):
|
||||
"""
|
||||
Render the field by rendering the passed widget, adding any HTML
|
||||
attributes passed as attrs. If a widget isn't specified, use the
|
||||
field's default widget.
|
||||
"""
|
||||
widget = widget or self.field.widget
|
||||
if self.field.localize:
|
||||
widget.is_localized = True
|
||||
attrs = attrs or {}
|
||||
attrs = self.build_widget_attrs(attrs, widget)
|
||||
if self.auto_id and "id" not in widget.attrs:
|
||||
attrs.setdefault(
|
||||
"id", self.html_initial_id if only_initial else self.auto_id
|
||||
)
|
||||
if only_initial and self.html_initial_name in self.form.data:
|
||||
# Propagate the hidden initial value.
|
||||
value = self.form._widget_data_value(
|
||||
self.field.hidden_widget(),
|
||||
self.html_initial_name,
|
||||
)
|
||||
else:
|
||||
value = self.value()
|
||||
return widget.render(
|
||||
name=self.html_initial_name if only_initial else self.html_name,
|
||||
value=value,
|
||||
attrs=attrs,
|
||||
renderer=self.form.renderer,
|
||||
)
|
||||
|
||||
def as_text(self, attrs=None, **kwargs):
|
||||
"""
|
||||
Return a string of HTML for representing this as an <input type="text">.
|
||||
"""
|
||||
return self.as_widget(TextInput(), attrs, **kwargs)
|
||||
|
||||
def as_textarea(self, attrs=None, **kwargs):
|
||||
"""Return a string of HTML for representing this as a <textarea>."""
|
||||
return self.as_widget(Textarea(), attrs, **kwargs)
|
||||
|
||||
def as_hidden(self, attrs=None, **kwargs):
|
||||
"""
|
||||
Return a string of HTML for representing this as an <input type="hidden">.
|
||||
"""
|
||||
return self.as_widget(self.field.hidden_widget(), attrs, **kwargs)
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
"""
|
||||
Return the data for this BoundField, or None if it wasn't given.
|
||||
"""
|
||||
return self.form._widget_data_value(self.field.widget, self.html_name)
|
||||
|
||||
def value(self):
|
||||
"""
|
||||
Return the value for this BoundField, using the initial value if
|
||||
the form is not bound or the data otherwise.
|
||||
"""
|
||||
data = self.initial
|
||||
if self.form.is_bound:
|
||||
data = self.field.bound_data(self.data, data)
|
||||
return self.field.prepare_value(data)
|
||||
|
||||
def _has_changed(self):
|
||||
field = self.field
|
||||
if field.show_hidden_initial:
|
||||
hidden_widget = field.hidden_widget()
|
||||
initial_value = self.form._widget_data_value(
|
||||
hidden_widget,
|
||||
self.html_initial_name,
|
||||
)
|
||||
try:
|
||||
initial_value = field.to_python(initial_value)
|
||||
except ValidationError:
|
||||
# Always assume data has changed if validation fails.
|
||||
return True
|
||||
else:
|
||||
initial_value = self.initial
|
||||
return field.has_changed(initial_value, self.data)
|
||||
|
||||
def label_tag(self, contents=None, attrs=None, label_suffix=None, tag=None):
|
||||
"""
|
||||
Wrap the given contents in a <label>, if the field has an ID attribute.
|
||||
contents should be mark_safe'd to avoid HTML escaping. If contents
|
||||
aren't given, use the field's HTML-escaped label.
|
||||
|
||||
If attrs are given, use them as HTML attributes on the <label> tag.
|
||||
|
||||
label_suffix overrides the form's label_suffix.
|
||||
"""
|
||||
contents = contents or self.label
|
||||
if label_suffix is None:
|
||||
label_suffix = (
|
||||
self.field.label_suffix
|
||||
if self.field.label_suffix is not None
|
||||
else self.form.label_suffix
|
||||
)
|
||||
# Only add the suffix if the label does not end in punctuation.
|
||||
# Translators: If found as last label character, these punctuation
|
||||
# characters will prevent the default label_suffix to be appended to the label
|
||||
if label_suffix and contents and contents[-1] not in _(":?.!"):
|
||||
contents = format_html("{}{}", contents, label_suffix)
|
||||
widget = self.field.widget
|
||||
id_ = widget.attrs.get("id") or self.auto_id
|
||||
if id_:
|
||||
id_for_label = widget.id_for_label(id_)
|
||||
if id_for_label:
|
||||
attrs = {**(attrs or {}), "for": id_for_label}
|
||||
if self.field.required and hasattr(self.form, "required_css_class"):
|
||||
attrs = attrs or {}
|
||||
if "class" in attrs:
|
||||
attrs["class"] += " " + self.form.required_css_class
|
||||
else:
|
||||
attrs["class"] = self.form.required_css_class
|
||||
context = {
|
||||
"field": self,
|
||||
"label": contents,
|
||||
"attrs": attrs,
|
||||
"use_tag": bool(id_),
|
||||
"tag": tag or "label",
|
||||
}
|
||||
return self.form.render(self.form.template_name_label, context)
|
||||
|
||||
def legend_tag(self, contents=None, attrs=None, label_suffix=None):
|
||||
"""
|
||||
Wrap the given contents in a <legend>, if the field has an ID
|
||||
attribute. Contents should be mark_safe'd to avoid HTML escaping. If
|
||||
contents aren't given, use the field's HTML-escaped label.
|
||||
|
||||
If attrs are given, use them as HTML attributes on the <legend> tag.
|
||||
|
||||
label_suffix overrides the form's label_suffix.
|
||||
"""
|
||||
return self.label_tag(contents, attrs, label_suffix, tag="legend")
|
||||
|
||||
def css_classes(self, extra_classes=None):
|
||||
"""
|
||||
Return a string of space-separated CSS classes for this field.
|
||||
"""
|
||||
if hasattr(extra_classes, "split"):
|
||||
extra_classes = extra_classes.split()
|
||||
extra_classes = set(extra_classes or [])
|
||||
if self.errors and hasattr(self.form, "error_css_class"):
|
||||
extra_classes.add(self.form.error_css_class)
|
||||
if self.field.required and hasattr(self.form, "required_css_class"):
|
||||
extra_classes.add(self.form.required_css_class)
|
||||
return " ".join(extra_classes)
|
||||
|
||||
@property
|
||||
def is_hidden(self):
|
||||
"""Return True if this BoundField's widget is hidden."""
|
||||
return self.field.widget.is_hidden
|
||||
|
||||
@property
|
||||
def auto_id(self):
|
||||
"""
|
||||
Calculate and return the ID attribute for this BoundField, if the
|
||||
associated Form has specified auto_id. Return an empty string otherwise.
|
||||
"""
|
||||
auto_id = self.form.auto_id # Boolean or string
|
||||
if auto_id and "%s" in str(auto_id):
|
||||
return auto_id % self.html_name
|
||||
elif auto_id:
|
||||
return self.html_name
|
||||
return ""
|
||||
|
||||
@property
|
||||
def id_for_label(self):
|
||||
"""
|
||||
Wrapper around the field widget's `id_for_label` method.
|
||||
Useful, for example, for focusing on this field regardless of whether
|
||||
it has a single widget or a MultiWidget.
|
||||
"""
|
||||
widget = self.field.widget
|
||||
id_ = widget.attrs.get("id") or self.auto_id
|
||||
return widget.id_for_label(id_)
|
||||
|
||||
@cached_property
|
||||
def initial(self):
|
||||
return self.form.get_initial_for_field(self.field, self.name)
|
||||
|
||||
def build_widget_attrs(self, attrs, widget=None):
|
||||
widget = widget or self.field.widget
|
||||
attrs = dict(attrs) # Copy attrs to avoid modifying the argument.
|
||||
if (
|
||||
widget.use_required_attribute(self.initial)
|
||||
and self.field.required
|
||||
and self.form.use_required_attribute
|
||||
):
|
||||
# MultiValueField has require_all_fields: if False, fall back
|
||||
# on subfields.
|
||||
if (
|
||||
hasattr(self.field, "require_all_fields")
|
||||
and not self.field.require_all_fields
|
||||
and isinstance(self.field.widget, MultiWidget)
|
||||
):
|
||||
for subfield, subwidget in zip(self.field.fields, widget.widgets):
|
||||
subwidget.attrs["required"] = (
|
||||
subwidget.use_required_attribute(self.initial)
|
||||
and subfield.required
|
||||
)
|
||||
else:
|
||||
attrs["required"] = True
|
||||
if self.field.disabled:
|
||||
attrs["disabled"] = True
|
||||
if not widget.is_hidden and self.errors:
|
||||
attrs["aria-invalid"] = "true"
|
||||
# Preserve aria-describedby provided by the attrs argument so user
|
||||
# can set the desired order.
|
||||
if not attrs.get("aria-describedby") and not self.use_fieldset:
|
||||
if aria_describedby := self.aria_describedby:
|
||||
attrs["aria-describedby"] = aria_describedby
|
||||
return attrs
|
||||
|
||||
@property
|
||||
def aria_describedby(self):
|
||||
# Preserve aria-describedby set on the widget.
|
||||
if self.field.widget.attrs.get("aria-describedby"):
|
||||
return None
|
||||
aria_describedby = []
|
||||
if self.auto_id and not self.is_hidden:
|
||||
if self.help_text:
|
||||
aria_describedby.append(f"{self.auto_id}_helptext")
|
||||
if self.errors:
|
||||
aria_describedby.append(f"{self.auto_id}_error")
|
||||
return " ".join(aria_describedby)
|
||||
|
||||
@property
|
||||
def widget_type(self):
|
||||
return re.sub(
|
||||
r"widget$|input$", "", self.field.widget.__class__.__name__.lower()
|
||||
)
|
||||
|
||||
@property
|
||||
def use_fieldset(self):
|
||||
"""
|
||||
Return the value of this BoundField widget's use_fieldset attribute.
|
||||
"""
|
||||
return self.field.widget.use_fieldset
|
||||
|
||||
|
||||
@html_safe
|
||||
class BoundWidget:
|
||||
"""
|
||||
A container class used for iterating over widgets. This is useful for
|
||||
widgets that have choices. For example, the following can be used in a
|
||||
template:
|
||||
|
||||
{% for radio in myform.beatles %}
|
||||
<label for="{{ radio.id_for_label }}">
|
||||
{{ radio.choice_label }}
|
||||
<span class="radio">{{ radio.tag }}</span>
|
||||
</label>
|
||||
{% endfor %}
|
||||
"""
|
||||
|
||||
def __init__(self, parent_widget, data, renderer):
|
||||
self.parent_widget = parent_widget
|
||||
self.data = data
|
||||
self.renderer = renderer
|
||||
|
||||
def __str__(self):
|
||||
return self.tag(wrap_label=True)
|
||||
|
||||
def tag(self, wrap_label=False):
|
||||
context = {"widget": {**self.data, "wrap_label": wrap_label}}
|
||||
return self.parent_widget._render(self.template_name, context, self.renderer)
|
||||
|
||||
@property
|
||||
def template_name(self):
|
||||
if "template_name" in self.data:
|
||||
return self.data["template_name"]
|
||||
return self.parent_widget.template_name
|
||||
|
||||
@property
|
||||
def id_for_label(self):
|
||||
return self.data["attrs"].get("id")
|
||||
|
||||
@property
|
||||
def choice_label(self):
|
||||
return self.data["label"]
|
||||
1420
myenv/lib/python3.12/site-packages/django/forms/fields.py
Normal file
1420
myenv/lib/python3.12/site-packages/django/forms/fields.py
Normal file
File diff suppressed because it is too large
Load diff
439
myenv/lib/python3.12/site-packages/django/forms/forms.py
Normal file
439
myenv/lib/python3.12/site-packages/django/forms/forms.py
Normal file
|
|
@ -0,0 +1,439 @@
|
|||
"""
|
||||
Form classes
|
||||
"""
|
||||
|
||||
import copy
|
||||
import datetime
|
||||
|
||||
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
|
||||
from django.forms.fields import Field
|
||||
from django.forms.utils import ErrorDict, ErrorList, RenderableFormMixin
|
||||
from django.forms.widgets import Media, MediaDefiningClass
|
||||
from django.utils.datastructures import MultiValueDict
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from .renderers import get_default_renderer
|
||||
|
||||
__all__ = ("BaseForm", "Form")
|
||||
|
||||
|
||||
class DeclarativeFieldsMetaclass(MediaDefiningClass):
|
||||
"""Collect Fields declared on the base classes."""
|
||||
|
||||
def __new__(mcs, name, bases, attrs):
|
||||
# Collect fields from current class and remove them from attrs.
|
||||
attrs["declared_fields"] = {
|
||||
key: attrs.pop(key)
|
||||
for key, value in list(attrs.items())
|
||||
if isinstance(value, Field)
|
||||
}
|
||||
|
||||
new_class = super().__new__(mcs, name, bases, attrs)
|
||||
|
||||
# Walk through the MRO.
|
||||
declared_fields = {}
|
||||
for base in reversed(new_class.__mro__):
|
||||
# Collect fields from base class.
|
||||
if hasattr(base, "declared_fields"):
|
||||
declared_fields.update(base.declared_fields)
|
||||
|
||||
# Field shadowing.
|
||||
for attr, value in base.__dict__.items():
|
||||
if value is None and attr in declared_fields:
|
||||
declared_fields.pop(attr)
|
||||
|
||||
new_class.base_fields = declared_fields
|
||||
new_class.declared_fields = declared_fields
|
||||
|
||||
return new_class
|
||||
|
||||
|
||||
class BaseForm(RenderableFormMixin):
|
||||
"""
|
||||
The main implementation of all the Form logic. Note that this class is
|
||||
different than Form. See the comments by the Form class for more info. Any
|
||||
improvements to the form API should be made to this class, not to the Form
|
||||
class.
|
||||
"""
|
||||
|
||||
default_renderer = None
|
||||
field_order = None
|
||||
prefix = None
|
||||
use_required_attribute = True
|
||||
|
||||
template_name_div = "django/forms/div.html"
|
||||
template_name_p = "django/forms/p.html"
|
||||
template_name_table = "django/forms/table.html"
|
||||
template_name_ul = "django/forms/ul.html"
|
||||
template_name_label = "django/forms/label.html"
|
||||
|
||||
bound_field_class = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
data=None,
|
||||
files=None,
|
||||
auto_id="id_%s",
|
||||
prefix=None,
|
||||
initial=None,
|
||||
error_class=ErrorList,
|
||||
label_suffix=None,
|
||||
empty_permitted=False,
|
||||
field_order=None,
|
||||
use_required_attribute=None,
|
||||
renderer=None,
|
||||
bound_field_class=None,
|
||||
):
|
||||
self.is_bound = data is not None or files is not None
|
||||
self.data = MultiValueDict() if data is None else data
|
||||
self.files = MultiValueDict() if files is None else files
|
||||
self.auto_id = auto_id
|
||||
if prefix is not None:
|
||||
self.prefix = prefix
|
||||
self.initial = initial or {}
|
||||
self.error_class = error_class
|
||||
# Translators: This is the default suffix added to form field labels
|
||||
self.label_suffix = label_suffix if label_suffix is not None else _(":")
|
||||
self.empty_permitted = empty_permitted
|
||||
self._errors = None # Stores the errors after clean() has been called.
|
||||
|
||||
# The base_fields class attribute is the *class-wide* definition of
|
||||
# fields. Because a particular *instance* of the class might want to
|
||||
# alter self.fields, we create self.fields here by copying base_fields.
|
||||
# Instances should always modify self.fields; they should not modify
|
||||
# self.base_fields.
|
||||
self.fields = copy.deepcopy(self.base_fields)
|
||||
self._bound_fields_cache = {}
|
||||
self.order_fields(self.field_order if field_order is None else field_order)
|
||||
|
||||
if use_required_attribute is not None:
|
||||
self.use_required_attribute = use_required_attribute
|
||||
|
||||
if self.empty_permitted and self.use_required_attribute:
|
||||
raise ValueError(
|
||||
"The empty_permitted and use_required_attribute arguments may "
|
||||
"not both be True."
|
||||
)
|
||||
|
||||
# Initialize form renderer. Use a global default if not specified
|
||||
# either as an argument or as self.default_renderer.
|
||||
if renderer is None:
|
||||
if self.default_renderer is None:
|
||||
renderer = get_default_renderer()
|
||||
else:
|
||||
renderer = self.default_renderer
|
||||
if isinstance(self.default_renderer, type):
|
||||
renderer = renderer()
|
||||
self.renderer = renderer
|
||||
|
||||
self.bound_field_class = (
|
||||
bound_field_class
|
||||
or self.bound_field_class
|
||||
or getattr(self.renderer, "bound_field_class", None)
|
||||
)
|
||||
|
||||
def order_fields(self, field_order):
|
||||
"""
|
||||
Rearrange the fields according to field_order.
|
||||
|
||||
field_order is a list of field names specifying the order. Append fields
|
||||
not included in the list in the default order for backward compatibility
|
||||
with subclasses not overriding field_order. If field_order is None,
|
||||
keep all fields in the order defined in the class. Ignore unknown
|
||||
fields in field_order to allow disabling fields in form subclasses
|
||||
without redefining ordering.
|
||||
"""
|
||||
if field_order is None:
|
||||
return
|
||||
fields = {}
|
||||
for key in field_order:
|
||||
try:
|
||||
fields[key] = self.fields.pop(key)
|
||||
except KeyError: # ignore unknown fields
|
||||
pass
|
||||
fields.update(self.fields) # add remaining fields in original order
|
||||
self.fields = fields
|
||||
|
||||
def __repr__(self):
|
||||
if self._errors is None:
|
||||
is_valid = "Unknown"
|
||||
else:
|
||||
is_valid = self.is_bound and not self._errors
|
||||
return "<%(cls)s bound=%(bound)s, valid=%(valid)s, fields=(%(fields)s)>" % {
|
||||
"cls": self.__class__.__name__,
|
||||
"bound": self.is_bound,
|
||||
"valid": is_valid,
|
||||
"fields": ";".join(self.fields),
|
||||
}
|
||||
|
||||
def _bound_items(self):
|
||||
"""Yield (name, bf) pairs, where bf is a BoundField object."""
|
||||
for name in self.fields:
|
||||
yield name, self[name]
|
||||
|
||||
def __iter__(self):
|
||||
"""Yield the form's fields as BoundField objects."""
|
||||
for name in self.fields:
|
||||
yield self[name]
|
||||
|
||||
def __getitem__(self, name):
|
||||
"""Return a BoundField with the given name."""
|
||||
try:
|
||||
field = self.fields[name]
|
||||
except KeyError:
|
||||
raise KeyError(
|
||||
"Key '%s' not found in '%s'. Choices are: %s."
|
||||
% (
|
||||
name,
|
||||
self.__class__.__name__,
|
||||
", ".join(sorted(self.fields)),
|
||||
)
|
||||
)
|
||||
if name not in self._bound_fields_cache:
|
||||
self._bound_fields_cache[name] = field.get_bound_field(self, name)
|
||||
return self._bound_fields_cache[name]
|
||||
|
||||
@property
|
||||
def errors(self):
|
||||
"""Return an ErrorDict for the data provided for the form."""
|
||||
if self._errors is None:
|
||||
self.full_clean()
|
||||
return self._errors
|
||||
|
||||
def is_valid(self):
|
||||
"""Return True if the form has no errors, or False otherwise."""
|
||||
return self.is_bound and not self.errors
|
||||
|
||||
def add_prefix(self, field_name):
|
||||
"""
|
||||
Return the field name with a prefix appended, if this Form has a
|
||||
prefix set.
|
||||
|
||||
Subclasses may wish to override.
|
||||
"""
|
||||
return "%s-%s" % (self.prefix, field_name) if self.prefix else field_name
|
||||
|
||||
def add_initial_prefix(self, field_name):
|
||||
"""Add an 'initial' prefix for checking dynamic initial values."""
|
||||
return "initial-%s" % self.add_prefix(field_name)
|
||||
|
||||
def _widget_data_value(self, widget, html_name):
|
||||
# value_from_datadict() gets the data from the data dictionaries.
|
||||
# Each widget type knows how to retrieve its own data, because some
|
||||
# widgets split data over several HTML fields.
|
||||
return widget.value_from_datadict(self.data, self.files, html_name)
|
||||
|
||||
@property
|
||||
def template_name(self):
|
||||
return self.renderer.form_template_name
|
||||
|
||||
def get_context(self):
|
||||
fields = []
|
||||
hidden_fields = []
|
||||
top_errors = self.non_field_errors().copy()
|
||||
for name, bf in self._bound_items():
|
||||
if bf.is_hidden:
|
||||
if bf.errors:
|
||||
top_errors += [
|
||||
_("(Hidden field %(name)s) %(error)s")
|
||||
% {"name": name, "error": str(e)}
|
||||
for e in bf.errors
|
||||
]
|
||||
hidden_fields.append(bf)
|
||||
else:
|
||||
fields.append((bf, bf.errors))
|
||||
return {
|
||||
"form": self,
|
||||
"fields": fields,
|
||||
"hidden_fields": hidden_fields,
|
||||
"errors": top_errors,
|
||||
}
|
||||
|
||||
def non_field_errors(self):
|
||||
"""
|
||||
Return an ErrorList of errors that aren't associated with a particular
|
||||
field -- i.e., from Form.clean(). Return an empty ErrorList if there
|
||||
are none.
|
||||
"""
|
||||
return self.errors.get(
|
||||
NON_FIELD_ERRORS,
|
||||
self.error_class(error_class="nonfield", renderer=self.renderer),
|
||||
)
|
||||
|
||||
def add_error(self, field, error):
|
||||
"""
|
||||
Update the content of `self._errors`.
|
||||
|
||||
The `field` argument is the name of the field to which the errors
|
||||
should be added. If it's None, treat the errors as NON_FIELD_ERRORS.
|
||||
|
||||
The `error` argument can be a single error, a list of errors, or a
|
||||
dictionary that maps field names to lists of errors. An "error" can be
|
||||
either a simple string or an instance of ValidationError with its
|
||||
message attribute set and a "list or dictionary" can be an actual
|
||||
`list` or `dict` or an instance of ValidationError with its
|
||||
`error_list` or `error_dict` attribute set.
|
||||
|
||||
If `error` is a dictionary, the `field` argument *must* be None and
|
||||
errors will be added to the fields that correspond to the keys of the
|
||||
dictionary.
|
||||
"""
|
||||
if not isinstance(error, ValidationError):
|
||||
# Normalize to ValidationError and let its constructor
|
||||
# do the hard work of making sense of the input.
|
||||
error = ValidationError(error)
|
||||
|
||||
if hasattr(error, "error_dict"):
|
||||
if field is not None:
|
||||
raise TypeError(
|
||||
"The argument `field` must be `None` when the `error` "
|
||||
"argument contains errors for multiple fields."
|
||||
)
|
||||
else:
|
||||
error = error.error_dict
|
||||
else:
|
||||
error = {field or NON_FIELD_ERRORS: error.error_list}
|
||||
|
||||
for field, error_list in error.items():
|
||||
if field not in self.errors:
|
||||
if field != NON_FIELD_ERRORS and field not in self.fields:
|
||||
raise ValueError(
|
||||
"'%s' has no field named '%s'."
|
||||
% (self.__class__.__name__, field)
|
||||
)
|
||||
if field == NON_FIELD_ERRORS:
|
||||
self._errors[field] = self.error_class(
|
||||
error_class="nonfield", renderer=self.renderer
|
||||
)
|
||||
else:
|
||||
self._errors[field] = self.error_class(
|
||||
renderer=self.renderer,
|
||||
field_id=self[field].auto_id,
|
||||
)
|
||||
self._errors[field].extend(error_list)
|
||||
if field in self.cleaned_data:
|
||||
del self.cleaned_data[field]
|
||||
|
||||
def has_error(self, field, code=None):
|
||||
return field in self.errors and (
|
||||
code is None
|
||||
or any(error.code == code for error in self.errors.as_data()[field])
|
||||
)
|
||||
|
||||
def full_clean(self):
|
||||
"""
|
||||
Clean all of self.data and populate self._errors and self.cleaned_data.
|
||||
"""
|
||||
self._errors = ErrorDict(renderer=self.renderer)
|
||||
if not self.is_bound: # Stop further processing.
|
||||
return
|
||||
self.cleaned_data = {}
|
||||
# If the form is permitted to be empty, and none of the form data has
|
||||
# changed from the initial data, short circuit any validation.
|
||||
if self.empty_permitted and not self.has_changed():
|
||||
return
|
||||
|
||||
self._clean_fields()
|
||||
self._clean_form()
|
||||
self._post_clean()
|
||||
|
||||
def _clean_fields(self):
|
||||
for name, bf in self._bound_items():
|
||||
field = bf.field
|
||||
try:
|
||||
self.cleaned_data[name] = field._clean_bound_field(bf)
|
||||
if hasattr(self, "clean_%s" % name):
|
||||
value = getattr(self, "clean_%s" % name)()
|
||||
self.cleaned_data[name] = value
|
||||
except ValidationError as e:
|
||||
self.add_error(name, e)
|
||||
|
||||
def _clean_form(self):
|
||||
try:
|
||||
cleaned_data = self.clean()
|
||||
except ValidationError as e:
|
||||
self.add_error(None, e)
|
||||
else:
|
||||
if cleaned_data is not None:
|
||||
self.cleaned_data = cleaned_data
|
||||
|
||||
def _post_clean(self):
|
||||
"""
|
||||
An internal hook for performing additional cleaning after form cleaning
|
||||
is complete. Used for model validation in model forms.
|
||||
"""
|
||||
pass
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Hook for doing any extra form-wide cleaning after Field.clean() has been
|
||||
called on every field. Any ValidationError raised by this method will
|
||||
not be associated with a particular field; it will have a special-case
|
||||
association with the field named '__all__'.
|
||||
"""
|
||||
return self.cleaned_data
|
||||
|
||||
def has_changed(self):
|
||||
"""Return True if data differs from initial."""
|
||||
return bool(self.changed_data)
|
||||
|
||||
@cached_property
|
||||
def changed_data(self):
|
||||
return [name for name, bf in self._bound_items() if bf._has_changed()]
|
||||
|
||||
@property
|
||||
def media(self):
|
||||
"""Return all media required to render the widgets on this form."""
|
||||
media = Media()
|
||||
for field in self.fields.values():
|
||||
media += field.widget.media
|
||||
return media
|
||||
|
||||
def is_multipart(self):
|
||||
"""
|
||||
Return True if the form needs to be multipart-encoded, i.e. it has
|
||||
FileInput, or False otherwise.
|
||||
"""
|
||||
return any(field.widget.needs_multipart_form for field in self.fields.values())
|
||||
|
||||
def hidden_fields(self):
|
||||
"""
|
||||
Return a list of all the BoundField objects that are hidden fields.
|
||||
Useful for manual form layout in templates.
|
||||
"""
|
||||
return [field for field in self if field.is_hidden]
|
||||
|
||||
def visible_fields(self):
|
||||
"""
|
||||
Return a list of BoundField objects that aren't hidden fields.
|
||||
The opposite of the hidden_fields() method.
|
||||
"""
|
||||
return [field for field in self if not field.is_hidden]
|
||||
|
||||
def get_initial_for_field(self, field, field_name):
|
||||
"""
|
||||
Return initial data for field on form. Use initial data from the form
|
||||
or the field, in that order. Evaluate callable values.
|
||||
"""
|
||||
value = self.initial.get(field_name, field.initial)
|
||||
if callable(value):
|
||||
value = value()
|
||||
# If this is an auto-generated default date, nix the microseconds
|
||||
# for standardized handling. See #22502.
|
||||
if (
|
||||
isinstance(value, (datetime.datetime, datetime.time))
|
||||
and not field.widget.supports_microseconds
|
||||
):
|
||||
value = value.replace(microsecond=0)
|
||||
return value
|
||||
|
||||
|
||||
class Form(BaseForm, metaclass=DeclarativeFieldsMetaclass):
|
||||
"A collection of Fields, plus their associated data."
|
||||
|
||||
# This is a separate class from BaseForm in order to abstract the way
|
||||
# self.fields is specified. This class (Form) is the one that does the
|
||||
# fancy metaclass stuff purely for the semantic sugar -- it allows one
|
||||
# to define a form using declarative syntax.
|
||||
# BaseForm itself has no way of designating self.fields.
|
||||
584
myenv/lib/python3.12/site-packages/django/forms/formsets.py
Normal file
584
myenv/lib/python3.12/site-packages/django/forms/formsets.py
Normal file
|
|
@ -0,0 +1,584 @@
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.forms.fields import BooleanField, IntegerField
|
||||
from django.forms.forms import Form
|
||||
from django.forms.renderers import get_default_renderer
|
||||
from django.forms.utils import ErrorList, RenderableFormMixin
|
||||
from django.forms.widgets import CheckboxInput, HiddenInput, NumberInput
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext_lazy
|
||||
|
||||
__all__ = ("BaseFormSet", "formset_factory", "all_valid")
|
||||
|
||||
# special field names
|
||||
TOTAL_FORM_COUNT = "TOTAL_FORMS"
|
||||
INITIAL_FORM_COUNT = "INITIAL_FORMS"
|
||||
MIN_NUM_FORM_COUNT = "MIN_NUM_FORMS"
|
||||
MAX_NUM_FORM_COUNT = "MAX_NUM_FORMS"
|
||||
ORDERING_FIELD_NAME = "ORDER"
|
||||
DELETION_FIELD_NAME = "DELETE"
|
||||
|
||||
# default minimum number of forms in a formset
|
||||
DEFAULT_MIN_NUM = 0
|
||||
|
||||
# default maximum number of forms in a formset, to prevent memory exhaustion
|
||||
DEFAULT_MAX_NUM = 1000
|
||||
|
||||
|
||||
class ManagementForm(Form):
|
||||
"""
|
||||
Keep track of how many form instances are displayed on the page. If adding
|
||||
new forms via JavaScript, you should increment the count field of this form
|
||||
as well.
|
||||
"""
|
||||
|
||||
TOTAL_FORMS = IntegerField(widget=HiddenInput)
|
||||
INITIAL_FORMS = IntegerField(widget=HiddenInput)
|
||||
# MIN_NUM_FORM_COUNT and MAX_NUM_FORM_COUNT are output with the rest of the
|
||||
# management form, but only for the convenience of client-side code. The
|
||||
# POST value of them returned from the client is not checked.
|
||||
MIN_NUM_FORMS = IntegerField(required=False, widget=HiddenInput)
|
||||
MAX_NUM_FORMS = IntegerField(required=False, widget=HiddenInput)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
# When the management form is invalid, we don't know how many forms
|
||||
# were submitted.
|
||||
cleaned_data.setdefault(TOTAL_FORM_COUNT, 0)
|
||||
cleaned_data.setdefault(INITIAL_FORM_COUNT, 0)
|
||||
return cleaned_data
|
||||
|
||||
|
||||
class BaseFormSet(RenderableFormMixin):
|
||||
"""
|
||||
A collection of instances of the same Form class.
|
||||
"""
|
||||
|
||||
deletion_widget = CheckboxInput
|
||||
ordering_widget = NumberInput
|
||||
default_error_messages = {
|
||||
"missing_management_form": _(
|
||||
"ManagementForm data is missing or has been tampered with. Missing fields: "
|
||||
"%(field_names)s. You may need to file a bug report if the issue persists."
|
||||
),
|
||||
"too_many_forms": ngettext_lazy(
|
||||
"Please submit at most %(num)d form.",
|
||||
"Please submit at most %(num)d forms.",
|
||||
"num",
|
||||
),
|
||||
"too_few_forms": ngettext_lazy(
|
||||
"Please submit at least %(num)d form.",
|
||||
"Please submit at least %(num)d forms.",
|
||||
"num",
|
||||
),
|
||||
}
|
||||
|
||||
template_name_div = "django/forms/formsets/div.html"
|
||||
template_name_p = "django/forms/formsets/p.html"
|
||||
template_name_table = "django/forms/formsets/table.html"
|
||||
template_name_ul = "django/forms/formsets/ul.html"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
data=None,
|
||||
files=None,
|
||||
auto_id="id_%s",
|
||||
prefix=None,
|
||||
initial=None,
|
||||
error_class=ErrorList,
|
||||
form_kwargs=None,
|
||||
error_messages=None,
|
||||
):
|
||||
self.is_bound = data is not None or files is not None
|
||||
self.prefix = prefix or self.get_default_prefix()
|
||||
self.auto_id = auto_id
|
||||
self.data = data or {}
|
||||
self.files = files or {}
|
||||
self.initial = initial
|
||||
self.form_kwargs = form_kwargs or {}
|
||||
self.error_class = error_class
|
||||
self._errors = None
|
||||
self._non_form_errors = None
|
||||
self.form_renderer = self.renderer
|
||||
self.renderer = self.renderer or get_default_renderer()
|
||||
|
||||
messages = {}
|
||||
for cls in reversed(type(self).__mro__):
|
||||
messages.update(getattr(cls, "default_error_messages", {}))
|
||||
if error_messages is not None:
|
||||
messages.update(error_messages)
|
||||
self.error_messages = messages
|
||||
|
||||
def __iter__(self):
|
||||
"""Yield the forms in the order they should be rendered."""
|
||||
return iter(self.forms)
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Return the form at the given index, based on the rendering order."""
|
||||
return self.forms[index]
|
||||
|
||||
def __len__(self):
|
||||
return len(self.forms)
|
||||
|
||||
def __bool__(self):
|
||||
"""
|
||||
Return True since all formsets have a management form which is not
|
||||
included in the length.
|
||||
"""
|
||||
return True
|
||||
|
||||
def __repr__(self):
|
||||
if self._errors is None:
|
||||
is_valid = "Unknown"
|
||||
else:
|
||||
is_valid = (
|
||||
self.is_bound
|
||||
and not self._non_form_errors
|
||||
and not any(form_errors for form_errors in self._errors)
|
||||
)
|
||||
return "<%s: bound=%s valid=%s total_forms=%s>" % (
|
||||
self.__class__.__qualname__,
|
||||
self.is_bound,
|
||||
is_valid,
|
||||
self.total_form_count(),
|
||||
)
|
||||
|
||||
@cached_property
|
||||
def management_form(self):
|
||||
"""Return the ManagementForm instance for this FormSet."""
|
||||
if self.is_bound:
|
||||
form = ManagementForm(
|
||||
self.data,
|
||||
auto_id=self.auto_id,
|
||||
prefix=self.prefix,
|
||||
renderer=self.renderer,
|
||||
)
|
||||
form.full_clean()
|
||||
else:
|
||||
form = ManagementForm(
|
||||
auto_id=self.auto_id,
|
||||
prefix=self.prefix,
|
||||
initial={
|
||||
TOTAL_FORM_COUNT: self.total_form_count(),
|
||||
INITIAL_FORM_COUNT: self.initial_form_count(),
|
||||
MIN_NUM_FORM_COUNT: self.min_num,
|
||||
MAX_NUM_FORM_COUNT: self.max_num,
|
||||
},
|
||||
renderer=self.renderer,
|
||||
)
|
||||
return form
|
||||
|
||||
def total_form_count(self):
|
||||
"""Return the total number of forms in this FormSet."""
|
||||
if self.is_bound:
|
||||
# return absolute_max if it is lower than the actual total form
|
||||
# count in the data; this is DoS protection to prevent clients
|
||||
# from forcing the server to instantiate arbitrary numbers of
|
||||
# forms
|
||||
return min(
|
||||
self.management_form.cleaned_data[TOTAL_FORM_COUNT], self.absolute_max
|
||||
)
|
||||
else:
|
||||
initial_forms = self.initial_form_count()
|
||||
total_forms = max(initial_forms, self.min_num) + self.extra
|
||||
# Allow all existing related objects/inlines to be displayed,
|
||||
# but don't allow extra beyond max_num.
|
||||
if initial_forms > self.max_num >= 0:
|
||||
total_forms = initial_forms
|
||||
elif total_forms > self.max_num >= 0:
|
||||
total_forms = self.max_num
|
||||
return total_forms
|
||||
|
||||
def initial_form_count(self):
|
||||
"""Return the number of forms that are required in this FormSet."""
|
||||
if self.is_bound:
|
||||
return self.management_form.cleaned_data[INITIAL_FORM_COUNT]
|
||||
else:
|
||||
# Use the length of the initial data if it's there, 0 otherwise.
|
||||
initial_forms = len(self.initial) if self.initial else 0
|
||||
return initial_forms
|
||||
|
||||
@cached_property
|
||||
def forms(self):
|
||||
"""Instantiate forms at first property access."""
|
||||
# DoS protection is included in total_form_count()
|
||||
return [
|
||||
self._construct_form(i, **self.get_form_kwargs(i))
|
||||
for i in range(self.total_form_count())
|
||||
]
|
||||
|
||||
def get_form_kwargs(self, index):
|
||||
"""
|
||||
Return additional keyword arguments for each individual formset form.
|
||||
|
||||
index will be None if the form being constructed is a new empty
|
||||
form.
|
||||
"""
|
||||
return self.form_kwargs.copy()
|
||||
|
||||
def _construct_form(self, i, **kwargs):
|
||||
"""Instantiate and return the i-th form instance in a formset."""
|
||||
defaults = {
|
||||
"auto_id": self.auto_id,
|
||||
"prefix": self.add_prefix(i),
|
||||
"error_class": self.error_class,
|
||||
# Don't render the HTML 'required' attribute as it may cause
|
||||
# incorrect validation for extra, optional, and deleted
|
||||
# forms in the formset.
|
||||
"use_required_attribute": False,
|
||||
"renderer": self.form_renderer,
|
||||
}
|
||||
if self.is_bound:
|
||||
defaults["data"] = self.data
|
||||
defaults["files"] = self.files
|
||||
if self.initial and "initial" not in kwargs:
|
||||
try:
|
||||
defaults["initial"] = self.initial[i]
|
||||
except IndexError:
|
||||
pass
|
||||
# Allow extra forms to be empty, unless they're part of
|
||||
# the minimum forms.
|
||||
if i >= self.initial_form_count() and i >= self.min_num:
|
||||
defaults["empty_permitted"] = True
|
||||
defaults.update(kwargs)
|
||||
form = self.form(**defaults)
|
||||
self.add_fields(form, i)
|
||||
return form
|
||||
|
||||
@property
|
||||
def initial_forms(self):
|
||||
"""Return a list of all the initial forms in this formset."""
|
||||
return self.forms[: self.initial_form_count()]
|
||||
|
||||
@property
|
||||
def extra_forms(self):
|
||||
"""Return a list of all the extra forms in this formset."""
|
||||
return self.forms[self.initial_form_count() :]
|
||||
|
||||
@property
|
||||
def empty_form(self):
|
||||
form_kwargs = {
|
||||
**self.get_form_kwargs(None),
|
||||
"auto_id": self.auto_id,
|
||||
"prefix": self.add_prefix("__prefix__"),
|
||||
"empty_permitted": True,
|
||||
"use_required_attribute": False,
|
||||
"renderer": self.form_renderer,
|
||||
}
|
||||
form = self.form(**form_kwargs)
|
||||
self.add_fields(form, None)
|
||||
return form
|
||||
|
||||
@property
|
||||
def cleaned_data(self):
|
||||
"""
|
||||
Return a list of form.cleaned_data dicts for every form in self.forms.
|
||||
"""
|
||||
if not self.is_valid():
|
||||
raise AttributeError(
|
||||
"'%s' object has no attribute 'cleaned_data'" % self.__class__.__name__
|
||||
)
|
||||
return [form.cleaned_data for form in self.forms]
|
||||
|
||||
@property
|
||||
def deleted_forms(self):
|
||||
"""Return a list of forms that have been marked for deletion."""
|
||||
if not self.is_valid() or not self.can_delete:
|
||||
return []
|
||||
# construct _deleted_form_indexes which is just a list of form indexes
|
||||
# that have had their deletion widget set to True
|
||||
if not hasattr(self, "_deleted_form_indexes"):
|
||||
self._deleted_form_indexes = []
|
||||
for i, form in enumerate(self.forms):
|
||||
# if this is an extra form and hasn't changed, don't consider it
|
||||
if i >= self.initial_form_count() and not form.has_changed():
|
||||
continue
|
||||
if self._should_delete_form(form):
|
||||
self._deleted_form_indexes.append(i)
|
||||
return [self.forms[i] for i in self._deleted_form_indexes]
|
||||
|
||||
@property
|
||||
def ordered_forms(self):
|
||||
"""
|
||||
Return a list of form in the order specified by the incoming data.
|
||||
Raise an AttributeError if ordering is not allowed.
|
||||
"""
|
||||
if not self.is_valid() or not self.can_order:
|
||||
raise AttributeError(
|
||||
"'%s' object has no attribute 'ordered_forms'" % self.__class__.__name__
|
||||
)
|
||||
# Construct _ordering, which is a list of (form_index, order_field_value)
|
||||
# tuples. After constructing this list, we'll sort it by order_field_value
|
||||
# so we have a way to get to the form indexes in the order specified
|
||||
# by the form data.
|
||||
if not hasattr(self, "_ordering"):
|
||||
self._ordering = []
|
||||
for i, form in enumerate(self.forms):
|
||||
# if this is an extra form and hasn't changed, don't consider it
|
||||
if i >= self.initial_form_count() and not form.has_changed():
|
||||
continue
|
||||
# don't add data marked for deletion to self.ordered_data
|
||||
if self.can_delete and self._should_delete_form(form):
|
||||
continue
|
||||
self._ordering.append((i, form.cleaned_data[ORDERING_FIELD_NAME]))
|
||||
# After we're done populating self._ordering, sort it.
|
||||
# A sort function to order things numerically ascending, but
|
||||
# None should be sorted below anything else. Allowing None as
|
||||
# a comparison value makes it so we can leave ordering fields
|
||||
# blank.
|
||||
|
||||
def compare_ordering_key(k):
|
||||
if k[1] is None:
|
||||
return (1, 0) # +infinity, larger than any number
|
||||
return (0, k[1])
|
||||
|
||||
self._ordering.sort(key=compare_ordering_key)
|
||||
# Return a list of form.cleaned_data dicts in the order specified by
|
||||
# the form data.
|
||||
return [self.forms[i[0]] for i in self._ordering]
|
||||
|
||||
@classmethod
|
||||
def get_default_prefix(cls):
|
||||
return "form"
|
||||
|
||||
@classmethod
|
||||
def get_deletion_widget(cls):
|
||||
return cls.deletion_widget
|
||||
|
||||
@classmethod
|
||||
def get_ordering_widget(cls):
|
||||
return cls.ordering_widget
|
||||
|
||||
def non_form_errors(self):
|
||||
"""
|
||||
Return an ErrorList of errors that aren't associated with a particular
|
||||
form -- i.e., from formset.clean(). Return an empty ErrorList if there
|
||||
are none.
|
||||
"""
|
||||
if self._non_form_errors is None:
|
||||
self.full_clean()
|
||||
return self._non_form_errors
|
||||
|
||||
@property
|
||||
def errors(self):
|
||||
"""Return a list of form.errors for every form in self.forms."""
|
||||
if self._errors is None:
|
||||
self.full_clean()
|
||||
return self._errors
|
||||
|
||||
def total_error_count(self):
|
||||
"""Return the number of errors across all forms in the formset."""
|
||||
return len(self.non_form_errors()) + sum(
|
||||
len(form_errors) for form_errors in self.errors
|
||||
)
|
||||
|
||||
def _should_delete_form(self, form):
|
||||
"""Return whether or not the form was marked for deletion."""
|
||||
return form.cleaned_data.get(DELETION_FIELD_NAME, False)
|
||||
|
||||
def is_valid(self):
|
||||
"""Return True if every form in self.forms is valid."""
|
||||
if not self.is_bound:
|
||||
return False
|
||||
# Accessing errors triggers a full clean the first time only.
|
||||
self.errors
|
||||
# List comprehension ensures is_valid() is called for all forms.
|
||||
# Forms due to be deleted shouldn't cause the formset to be invalid.
|
||||
forms_valid = all(
|
||||
[
|
||||
form.is_valid()
|
||||
for form in self.forms
|
||||
if not (self.can_delete and self._should_delete_form(form))
|
||||
]
|
||||
)
|
||||
return forms_valid and not self.non_form_errors()
|
||||
|
||||
def full_clean(self):
|
||||
"""
|
||||
Clean all of self.data and populate self._errors and
|
||||
self._non_form_errors.
|
||||
"""
|
||||
self._errors = []
|
||||
self._non_form_errors = self.error_class(
|
||||
error_class="nonform", renderer=self.renderer
|
||||
)
|
||||
empty_forms_count = 0
|
||||
|
||||
if not self.is_bound: # Stop further processing.
|
||||
return
|
||||
|
||||
if not self.management_form.is_valid():
|
||||
error = ValidationError(
|
||||
self.error_messages["missing_management_form"],
|
||||
params={
|
||||
"field_names": ", ".join(
|
||||
self.management_form.add_prefix(field_name)
|
||||
for field_name in self.management_form.errors
|
||||
),
|
||||
},
|
||||
code="missing_management_form",
|
||||
)
|
||||
self._non_form_errors.append(error)
|
||||
|
||||
for i, form in enumerate(self.forms):
|
||||
# Empty forms are unchanged forms beyond those with initial data.
|
||||
if not form.has_changed() and i >= self.initial_form_count():
|
||||
empty_forms_count += 1
|
||||
# Accessing errors calls full_clean() if necessary.
|
||||
# _should_delete_form() requires cleaned_data.
|
||||
form_errors = form.errors
|
||||
if self.can_delete and self._should_delete_form(form):
|
||||
continue
|
||||
self._errors.append(form_errors)
|
||||
try:
|
||||
if (
|
||||
self.validate_max
|
||||
and self.total_form_count() - len(self.deleted_forms) > self.max_num
|
||||
) or self.management_form.cleaned_data[
|
||||
TOTAL_FORM_COUNT
|
||||
] > self.absolute_max:
|
||||
raise ValidationError(
|
||||
self.error_messages["too_many_forms"] % {"num": self.max_num},
|
||||
code="too_many_forms",
|
||||
)
|
||||
if (
|
||||
self.validate_min
|
||||
and self.total_form_count()
|
||||
- len(self.deleted_forms)
|
||||
- empty_forms_count
|
||||
< self.min_num
|
||||
):
|
||||
raise ValidationError(
|
||||
self.error_messages["too_few_forms"] % {"num": self.min_num},
|
||||
code="too_few_forms",
|
||||
)
|
||||
# Give self.clean() a chance to do cross-form validation.
|
||||
self.clean()
|
||||
except ValidationError as e:
|
||||
self._non_form_errors = self.error_class(
|
||||
e.error_list,
|
||||
error_class="nonform",
|
||||
renderer=self.renderer,
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Hook for doing any extra formset-wide cleaning after Form.clean() has
|
||||
been called on every form. Any ValidationError raised by this method
|
||||
will not be associated with a particular form; it will be accessible
|
||||
via formset.non_form_errors()
|
||||
"""
|
||||
pass
|
||||
|
||||
def has_changed(self):
|
||||
"""Return True if data in any form differs from initial."""
|
||||
return any(form.has_changed() for form in self)
|
||||
|
||||
def add_fields(self, form, index):
|
||||
"""A hook for adding extra fields on to each form instance."""
|
||||
initial_form_count = self.initial_form_count()
|
||||
if self.can_order:
|
||||
# Only pre-fill the ordering field for initial forms.
|
||||
if index is not None and index < initial_form_count:
|
||||
form.fields[ORDERING_FIELD_NAME] = IntegerField(
|
||||
label=_("Order"),
|
||||
initial=index + 1,
|
||||
required=False,
|
||||
widget=self.get_ordering_widget(),
|
||||
)
|
||||
else:
|
||||
form.fields[ORDERING_FIELD_NAME] = IntegerField(
|
||||
label=_("Order"),
|
||||
required=False,
|
||||
widget=self.get_ordering_widget(),
|
||||
)
|
||||
if self.can_delete and (
|
||||
self.can_delete_extra or (index is not None and index < initial_form_count)
|
||||
):
|
||||
form.fields[DELETION_FIELD_NAME] = BooleanField(
|
||||
label=_("Delete"),
|
||||
required=False,
|
||||
widget=self.get_deletion_widget(),
|
||||
)
|
||||
|
||||
def add_prefix(self, index):
|
||||
return "%s-%s" % (self.prefix, index)
|
||||
|
||||
def is_multipart(self):
|
||||
"""
|
||||
Return True if the formset needs to be multipart, i.e. it
|
||||
has FileInput, or False otherwise.
|
||||
"""
|
||||
if self.forms:
|
||||
return self.forms[0].is_multipart()
|
||||
else:
|
||||
return self.empty_form.is_multipart()
|
||||
|
||||
@property
|
||||
def media(self):
|
||||
# All the forms on a FormSet are the same, so you only need to
|
||||
# interrogate the first form for media.
|
||||
if self.forms:
|
||||
return self.forms[0].media
|
||||
else:
|
||||
return self.empty_form.media
|
||||
|
||||
@property
|
||||
def template_name(self):
|
||||
return self.renderer.formset_template_name
|
||||
|
||||
def get_context(self):
|
||||
return {"formset": self}
|
||||
|
||||
|
||||
def formset_factory(
|
||||
form,
|
||||
formset=BaseFormSet,
|
||||
extra=1,
|
||||
can_order=False,
|
||||
can_delete=False,
|
||||
max_num=None,
|
||||
validate_max=False,
|
||||
min_num=None,
|
||||
validate_min=False,
|
||||
absolute_max=None,
|
||||
can_delete_extra=True,
|
||||
renderer=None,
|
||||
):
|
||||
"""Return a FormSet for the given form class."""
|
||||
if min_num is None:
|
||||
min_num = DEFAULT_MIN_NUM
|
||||
if max_num is None:
|
||||
max_num = DEFAULT_MAX_NUM
|
||||
# absolute_max is a hard limit on forms instantiated, to prevent
|
||||
# memory-exhaustion attacks. Default to max_num + DEFAULT_MAX_NUM
|
||||
# (which is 2 * DEFAULT_MAX_NUM if max_num is None in the first place).
|
||||
if absolute_max is None:
|
||||
absolute_max = max_num + DEFAULT_MAX_NUM
|
||||
if max_num > absolute_max:
|
||||
raise ValueError("'absolute_max' must be greater or equal to 'max_num'.")
|
||||
attrs = {
|
||||
"form": form,
|
||||
"extra": extra,
|
||||
"can_order": can_order,
|
||||
"can_delete": can_delete,
|
||||
"can_delete_extra": can_delete_extra,
|
||||
"min_num": min_num,
|
||||
"max_num": max_num,
|
||||
"absolute_max": absolute_max,
|
||||
"validate_min": validate_min,
|
||||
"validate_max": validate_max,
|
||||
"renderer": renderer,
|
||||
}
|
||||
form_name = form.__name__
|
||||
if form_name.endswith("Form"):
|
||||
formset_name = form_name + "Set"
|
||||
else:
|
||||
formset_name = form_name + "FormSet"
|
||||
return type(formset_name, (formset,), attrs)
|
||||
|
||||
|
||||
def all_valid(formsets):
|
||||
"""Validate every formset and return True if all are valid."""
|
||||
# List comprehension ensures is_valid() is called for all formsets.
|
||||
return all([formset.is_valid() for formset in formsets])
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% for name, value in attrs.items() %}{% if value is not sameas False %} {{ name }}{% if value is not sameas True %}="{{ value }}"{% endif %}{% endif %}{% endfor %}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{{ errors }}
|
||||
{% if errors and not fields %}
|
||||
<div>{% for field in hidden_fields %}{{ field }}{% endfor %}</div>
|
||||
{% endif %}
|
||||
{% for field, errors in fields %}
|
||||
<div{% set classes = field.css_classes() %}{% if classes %} class="{{ classes }}"{% endif %}>
|
||||
{{ field.as_field_group() }}
|
||||
{% if loop.last %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if not fields and not errors %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/errors/dict/ul.html" %}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{% for field, errors in errors %}* {{ field }}
|
||||
{% for error in errors %} * {{ error }}
|
||||
{% endfor %}{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% if errors %}<ul class="{{ error_class }}">{% for field, error in errors %}<li>{{ field }}{{ error }}</li>{% endfor %}</ul>{% endif %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/errors/list/ul.html" %}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
{% for error in errors %}* {{ error }}
|
||||
{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% if errors %}<ul class="{{ error_class }}"{% if errors.field_id %} id="{{ errors.field_id }}_error"{% endif %}>{% for error in errors %}<li>{{ error }}</li>{% endfor %}</ul>{% endif %}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{% if field.use_fieldset %}
|
||||
<fieldset{% if field.aria_describedby %} aria-describedby="{{ field.aria_describedby }}"{% endif %}>
|
||||
{% if field.label %}{{ field.legend_tag() }}{% endif %}
|
||||
{% else %}
|
||||
{% if field.label %}{{ field.label_tag() }}{% endif %}
|
||||
{% endif %}
|
||||
{% if field.help_text %}<div class="helptext"{% if field.auto_id %} id="{{ field.auto_id }}_helptext"{% endif %}>{{ field.help_text|safe }}</div>{% endif %}
|
||||
{{ field.errors }}
|
||||
{{ field }}
|
||||
{% if field.use_fieldset %}</fieldset>{% endif %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{{ formset.management_form }}{% for form in formset %}{{ form.as_div() }}{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{{ formset.management_form }}{% for form in formset %}{{ form.as_p() }}{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{{ formset.management_form }}{% for form in formset %}{{ form.as_table() }}{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{{ formset.management_form }}{% for form in formset %}{{ form.as_ul() }}{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% if use_tag %}<{{ tag }}{% if attrs %}{% include 'django/forms/attrs.html' %}{% endif %}>{{ label }}</{{ tag }}>{% else %}{{ label }}{% endif %}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{{ errors }}
|
||||
{% if errors and not fields %}
|
||||
<p>{% for field in hidden_fields %}{{ field }}{% endfor %}</p>
|
||||
{% endif %}
|
||||
{% for field, errors in fields %}
|
||||
{{ errors }}
|
||||
<p{% set classes = field.css_classes() %}{% if classes %} class="{{ classes }}"{% endif %}>
|
||||
{% if field.label %}{{ field.label_tag() }}{% endif %}
|
||||
{{ field }}
|
||||
{% if field.help_text %}
|
||||
<span class="helptext"{% if field.auto_id %} id="{{ field.auto_id }}_helptext"{% endif %}>{{ field.help_text|safe }}</span>
|
||||
{% endif %}
|
||||
{% if loop.last %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endfor %}
|
||||
{% if not fields and not errors %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
{% if errors %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{{ errors }}
|
||||
{% if not fields %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% for field, errors in fields %}
|
||||
<tr{% set classes = field.css_classes() %}{% if classes %} class="{{ classes }}"{% endif %}>
|
||||
<th>{% if field.label %}{{ field.label_tag() }}{% endif %}</th>
|
||||
<td>
|
||||
{{ errors }}
|
||||
{{ field }}
|
||||
{% if field.help_text %}
|
||||
<br>
|
||||
<span class="helptext"{% if field.auto_id %} id="{{ field.auto_id }}_helptext"{% endif %}>{{ field.help_text|safe }}</span>
|
||||
{% endif %}
|
||||
{% if loop.last %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if not fields and not errors %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
{% if errors %}
|
||||
<li>
|
||||
{{ errors }}
|
||||
{% if not fields %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% for field, errors in fields %}
|
||||
<li{% set classes = field.css_classes() %}{% if classes %} class="{{ classes }}"{% endif %}>
|
||||
{{ errors }}
|
||||
{% if field.label %}{{ field.label_tag() }}{% endif %}
|
||||
{{ field }}
|
||||
{% if field.help_text %}
|
||||
<span class="helptext"{% if field.auto_id %} id="{{ field.auto_id }}_helptext"{% endif %}>{{ field.help_text|safe }}</span>
|
||||
{% endif %}
|
||||
{% if loop.last %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% if not fields and not errors %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% for name, value in widget.attrs.items() %}{% if value is not sameas False %} {{ name }}{% if value is not sameas True %}="{{ value }}"{% endif %}{% endif %}{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input_option.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/multiple_input.html" %}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{% if widget.is_initial %}{{ widget.initial_text }}: <a href="{{ widget.value.url }}">{{ widget.value }}</a>{% if not widget.required %}
|
||||
<input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}"{% if widget.attrs.disabled %} disabled{% endif %}{% if widget.attrs.checked %} checked{% endif %}>
|
||||
<label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>{% endif %}<br>
|
||||
{{ widget.input_text }}:{% endif %}
|
||||
<input type="{{ widget.type }}" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<input type="{{ widget.type }}" name="{{ widget.name }}"{% if widget.value != None %} value="{{ widget.value }}"{% endif %}{% include "django/forms/widgets/attrs.html" %}>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% if widget.wrap_label %}<label{% if widget.attrs.id %} for="{{ widget.attrs.id }}"{% endif %}>{% endif %}{% include "django/forms/widgets/input.html" %}{% if widget.wrap_label %} {{ widget.label }}</label>{% endif %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/multiwidget.html" %}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{% set id = widget.attrs.id %}<div{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %}
|
||||
<div><label>{{ group }}</label>{% endif %}{% for widget in options %}<div>
|
||||
{% include widget.template_name %}</div>{% endfor %}{% if group %}
|
||||
</div>{% endif %}{% endfor %}
|
||||
</div>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% for widget in widget.subwidgets -%}{% include widget.template_name %}{%- endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/multiple_input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input_option.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<select name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>{% for group_name, group_choices, group_index in widget.optgroups %}{% if group_name %}
|
||||
<optgroup label="{{ group_name }}">{% endif %}{% for widget in group_choices %}
|
||||
{% include widget.template_name %}{% endfor %}{% if group_name %}
|
||||
</optgroup>{% endif %}{% endfor %}
|
||||
</select>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include 'django/forms/widgets/multiwidget.html' %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<option value="{{ widget.value }}"{% include "django/forms/widgets/attrs.html" %}>{{ widget.label }}</option>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include 'django/forms/widgets/multiwidget.html' %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include 'django/forms/widgets/multiwidget.html' %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<textarea name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
|
||||
{% if widget.value %}{{ widget.value }}{% endif %}</textarea>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
1687
myenv/lib/python3.12/site-packages/django/forms/models.py
Normal file
1687
myenv/lib/python3.12/site-packages/django/forms/models.py
Normal file
File diff suppressed because it is too large
Load diff
114
myenv/lib/python3.12/site-packages/django/forms/renderers.py
Normal file
114
myenv/lib/python3.12/site-packages/django/forms/renderers.py
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
import functools
|
||||
import warnings
|
||||
from pathlib import Path
|
||||
|
||||
from django.conf import settings
|
||||
from django.template.backends.django import DjangoTemplates
|
||||
from django.template.loader import get_template
|
||||
from django.utils.deprecation import RemovedInDjango60Warning
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.module_loading import import_string
|
||||
|
||||
|
||||
@functools.lru_cache
|
||||
def get_default_renderer():
|
||||
renderer_class = import_string(settings.FORM_RENDERER)
|
||||
return renderer_class()
|
||||
|
||||
|
||||
class BaseRenderer:
|
||||
form_template_name = "django/forms/div.html"
|
||||
formset_template_name = "django/forms/formsets/div.html"
|
||||
field_template_name = "django/forms/field.html"
|
||||
|
||||
bound_field_class = None
|
||||
|
||||
def get_template(self, template_name):
|
||||
raise NotImplementedError("subclasses must implement get_template()")
|
||||
|
||||
def render(self, template_name, context, request=None):
|
||||
template = self.get_template(template_name)
|
||||
return template.render(context, request=request).strip()
|
||||
|
||||
|
||||
class EngineMixin:
|
||||
def get_template(self, template_name):
|
||||
return self.engine.get_template(template_name)
|
||||
|
||||
@cached_property
|
||||
def engine(self):
|
||||
return self.backend(
|
||||
{
|
||||
"APP_DIRS": True,
|
||||
"DIRS": [Path(__file__).parent / self.backend.app_dirname],
|
||||
"NAME": "djangoforms",
|
||||
"OPTIONS": {},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class DjangoTemplates(EngineMixin, BaseRenderer):
|
||||
"""
|
||||
Load Django templates from the built-in widget templates in
|
||||
django/forms/templates and from apps' 'templates' directory.
|
||||
"""
|
||||
|
||||
backend = DjangoTemplates
|
||||
|
||||
|
||||
class Jinja2(EngineMixin, BaseRenderer):
|
||||
"""
|
||||
Load Jinja2 templates from the built-in widget templates in
|
||||
django/forms/jinja2 and from apps' 'jinja2' directory.
|
||||
"""
|
||||
|
||||
@cached_property
|
||||
def backend(self):
|
||||
from django.template.backends.jinja2 import Jinja2
|
||||
|
||||
return Jinja2
|
||||
|
||||
|
||||
# RemovedInDjango60Warning.
|
||||
class DjangoDivFormRenderer(DjangoTemplates):
|
||||
"""
|
||||
Load Django templates from django/forms/templates and from apps'
|
||||
'templates' directory and use the 'div.html' template to render forms and
|
||||
formsets.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
warnings.warn(
|
||||
"The DjangoDivFormRenderer transitional form renderer is deprecated. Use "
|
||||
"DjangoTemplates instead.",
|
||||
RemovedInDjango60Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
# RemovedInDjango60Warning.
|
||||
class Jinja2DivFormRenderer(Jinja2):
|
||||
"""
|
||||
Load Jinja2 templates from the built-in widget templates in
|
||||
django/forms/jinja2 and from apps' 'jinja2' directory.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
warnings.warn(
|
||||
"The Jinja2DivFormRenderer transitional form renderer is deprecated. Use "
|
||||
"Jinja2 instead.",
|
||||
RemovedInDjango60Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class TemplatesSetting(BaseRenderer):
|
||||
"""
|
||||
Load templates using template.loader.get_template() which is configured
|
||||
based on settings.TEMPLATES.
|
||||
"""
|
||||
|
||||
def get_template(self, template_name):
|
||||
return get_template(template_name)
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% for name, value in attrs.items %}{% if value is not False %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}{% endfor %}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{{ errors }}
|
||||
{% if errors and not fields %}
|
||||
<div>{% for field in hidden_fields %}{{ field }}{% endfor %}</div>
|
||||
{% endif %}
|
||||
{% for field, errors in fields %}
|
||||
<div{% with classes=field.css_classes %}{% if classes %} class="{{ classes }}"{% endif %}{% endwith %}>
|
||||
{{ field.as_field_group }}
|
||||
{% if forloop.last %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% if not fields and not errors %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/errors/dict/ul.html" %}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{% for field, errors in errors %}* {{ field }}
|
||||
{% for error in errors %} * {{ error }}
|
||||
{% endfor %}{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% if errors %}<ul class="{{ error_class }}">{% for field, error in errors %}<li>{{ field }}{{ error }}</li>{% endfor %}</ul>{% endif %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/errors/list/ul.html" %}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
{% for error in errors %}* {{ error }}
|
||||
{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% if errors %}<ul class="{{ error_class }}"{% if errors.field_id %} id="{{ errors.field_id }}_error"{% endif %}>{% for error in errors %}<li>{{ error }}</li>{% endfor %}</ul>{% endif %}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{% if field.use_fieldset %}
|
||||
<fieldset{% if field.aria_describedby %} aria-describedby="{{ field.aria_describedby }}"{% endif %}>
|
||||
{% if field.label %}{{ field.legend_tag }}{% endif %}
|
||||
{% else %}
|
||||
{% if field.label %}{{ field.label_tag }}{% endif %}
|
||||
{% endif %}
|
||||
{% if field.help_text %}<div class="helptext"{% if field.auto_id %} id="{{ field.auto_id }}_helptext"{% endif %}>{{ field.help_text|safe }}</div>{% endif %}
|
||||
{{ field.errors }}
|
||||
{{ field }}{% if field.use_fieldset %}</fieldset>{% endif %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{{ formset.management_form }}{% for form in formset %}{{ form.as_div }}{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{{ formset.management_form }}{% for form in formset %}{{ form.as_p }}{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{{ formset.management_form }}{% for form in formset %}{{ form.as_table }}{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{{ formset.management_form }}{% for form in formset %}{{ form.as_ul }}{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% if use_tag %}<{{ tag }}{% include 'django/forms/attrs.html' %}>{{ label }}</{{ tag }}>{% else %}{{ label }}{% endif %}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{{ errors }}
|
||||
{% if errors and not fields %}
|
||||
<p>{% for field in hidden_fields %}{{ field }}{% endfor %}</p>
|
||||
{% endif %}
|
||||
{% for field, errors in fields %}
|
||||
{{ errors }}
|
||||
<p{% with classes=field.css_classes %}{% if classes %} class="{{ classes }}"{% endif %}{% endwith %}>
|
||||
{% if field.label %}{{ field.label_tag }}{% endif %}
|
||||
{{ field }}
|
||||
{% if field.help_text %}
|
||||
<span class="helptext"{% if field.auto_id %} id="{{ field.auto_id }}_helptext"{% endif %}>{{ field.help_text|safe }}</span>
|
||||
{% endif %}
|
||||
{% if forloop.last %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endfor %}
|
||||
{% if not fields and not errors %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
{% if errors %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{{ errors }}
|
||||
{% if not fields %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% for field, errors in fields %}
|
||||
<tr{% with classes=field.css_classes %}{% if classes %} class="{{ classes }}"{% endif %}{% endwith %}>
|
||||
<th>{% if field.label %}{{ field.label_tag }}{% endif %}</th>
|
||||
<td>
|
||||
{{ errors }}
|
||||
{{ field }}
|
||||
{% if field.help_text %}
|
||||
<br>
|
||||
<span class="helptext"{% if field.auto_id %} id="{{ field.auto_id }}_helptext"{% endif %}>{{ field.help_text|safe }}</span>
|
||||
{% endif %}
|
||||
{% if forloop.last %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if not fields and not errors %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
{% if errors %}
|
||||
<li>
|
||||
{{ errors }}
|
||||
{% if not fields %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% for field, errors in fields %}
|
||||
<li{% with classes=field.css_classes %}{% if classes %} class="{{ classes }}"{% endif %}{% endwith %}>
|
||||
{{ errors }}
|
||||
{% if field.label %}{{ field.label_tag }}{% endif %}
|
||||
{{ field }}
|
||||
{% if field.help_text %}
|
||||
<span class="helptext"{% if field.auto_id %} id="{{ field.auto_id }}_helptext"{% endif %}>{{ field.help_text|safe }}</span>
|
||||
{% endif %}
|
||||
{% if forloop.last %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% if not fields and not errors %}
|
||||
{% for field in hidden_fields %}{{ field }}{% endfor %}
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% for name, value in widget.attrs.items %}{% if value is not False %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}{% endfor %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input_option.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/multiple_input.html" %}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{% if widget.is_initial %}{{ widget.initial_text }}: <a href="{{ widget.value.url }}">{{ widget.value }}</a>{% if not widget.required %}
|
||||
<input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}"{% if widget.attrs.disabled %} disabled{% endif %}{% if widget.attrs.checked %} checked{% endif %}>
|
||||
<label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>{% endif %}<br>
|
||||
{{ widget.input_text }}:{% endif %}
|
||||
<input type="{{ widget.type }}" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<input type="{{ widget.type }}" name="{{ widget.name }}"{% if widget.value != None %} value="{{ widget.value|stringformat:'s' }}"{% endif %}{% include "django/forms/widgets/attrs.html" %}>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% if widget.wrap_label %}<label{% if widget.attrs.id %} for="{{ widget.attrs.id }}"{% endif %}>{% endif %}{% include "django/forms/widgets/input.html" %}{% if widget.wrap_label %} {{ widget.label }}</label>{% endif %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/multiwidget.html" %}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{% with id=widget.attrs.id %}<div{% if id %} id="{{ id }}"{% endif %}{% if widget.attrs.class %} class="{{ widget.attrs.class }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %}
|
||||
<div><label>{{ group }}</label>{% endif %}{% for option in options %}<div>
|
||||
{% include option.template_name with widget=option %}</div>{% endfor %}{% if group %}
|
||||
</div>{% endif %}{% endfor %}
|
||||
</div>{% endwith %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% spaceless %}{% for widget in widget.subwidgets %}{% include widget.template_name %}{% endfor %}{% endspaceless %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/input.html" %}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% include "django/forms/widgets/multiple_input.html" %}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue