测试gitnore
This commit is contained in:
@@ -13,28 +13,26 @@ from django.utils import formats, timezone
|
||||
from django.utils.html import format_html
|
||||
from django.utils.regex_helper import _lazy_re_compile
|
||||
from django.utils.text import capfirst
|
||||
from django.utils.translation import ngettext
|
||||
from django.utils.translation import override as translation_override
|
||||
from django.utils.translation import ngettext, override as translation_override
|
||||
|
||||
QUOTE_MAP = {i: "_%02X" % i for i in b'":/_#?;@&=+$,"[]<>%\n\\'}
|
||||
QUOTE_MAP = {i: '_%02X' % i for i in b'":/_#?;@&=+$,"[]<>%\n\\'}
|
||||
UNQUOTE_MAP = {v: chr(k) for k, v in QUOTE_MAP.items()}
|
||||
UNQUOTE_RE = _lazy_re_compile("_(?:%s)" % "|".join([x[1:] for x in UNQUOTE_MAP]))
|
||||
UNQUOTE_RE = _lazy_re_compile('_(?:%s)' % '|'.join([x[1:] for x in UNQUOTE_MAP]))
|
||||
|
||||
|
||||
class FieldIsAForeignKeyColumnName(Exception):
|
||||
"""A field is a foreign key attname, i.e. <FK>_id."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def lookup_spawns_duplicates(opts, lookup_path):
|
||||
def lookup_needs_distinct(opts, lookup_path):
|
||||
"""
|
||||
Return True if the given lookup path spawns duplicates.
|
||||
Return True if 'distinct()' should be used to query the given lookup path.
|
||||
"""
|
||||
lookup_fields = lookup_path.split(LOOKUP_SEP)
|
||||
# Go through the fields (following all relations) and look for an m2m.
|
||||
for field_name in lookup_fields:
|
||||
if field_name == "pk":
|
||||
if field_name == 'pk':
|
||||
field_name = opts.pk.name
|
||||
try:
|
||||
field = opts.get_field(field_name)
|
||||
@@ -42,13 +40,12 @@ def lookup_spawns_duplicates(opts, lookup_path):
|
||||
# Ignore query lookups.
|
||||
continue
|
||||
else:
|
||||
if hasattr(field, "get_path_info"):
|
||||
if hasattr(field, 'get_path_info'):
|
||||
# This field is a relation; update opts to follow the relation.
|
||||
path_info = field.get_path_info()
|
||||
opts = path_info[-1].to_opts
|
||||
if any(path.m2m for path in path_info):
|
||||
# This field is a m2m relation so duplicates must be
|
||||
# handled.
|
||||
# This field is a m2m relation so distinct must be called.
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -58,11 +55,11 @@ def prepare_lookup_value(key, value):
|
||||
Return a lookup value prepared to be used in queryset filtering.
|
||||
"""
|
||||
# if key ends with __in, split parameter into separate values
|
||||
if key.endswith("__in"):
|
||||
value = value.split(",")
|
||||
if key.endswith('__in'):
|
||||
value = value.split(',')
|
||||
# if key ends with __isnull, special case '' and the string literals 'false' and '0'
|
||||
elif key.endswith("__isnull"):
|
||||
value = value.lower() not in ("", "false", "0")
|
||||
elif key.endswith('__isnull'):
|
||||
value = value.lower() not in ('', 'false', '0')
|
||||
return value
|
||||
|
||||
|
||||
@@ -71,7 +68,7 @@ def quote(s):
|
||||
Ensure that primary key values do not confuse the admin URLs by escaping
|
||||
any '/', '_' and ':' and similarly problematic characters.
|
||||
Similar to urllib.parse.quote(), except that the quoting is slightly
|
||||
different so that it doesn't get automatically unquoted by the web browser.
|
||||
different so that it doesn't get automatically unquoted by the Web browser.
|
||||
"""
|
||||
return s.translate(QUOTE_MAP) if isinstance(s, str) else s
|
||||
|
||||
@@ -98,7 +95,9 @@ def flatten_fieldsets(fieldsets):
|
||||
"""Return a list of field names from an admin fieldsets structure."""
|
||||
field_names = []
|
||||
for name, opts in fieldsets:
|
||||
field_names.extend(flatten(opts["fields"]))
|
||||
field_names.extend(
|
||||
flatten(opts['fields'])
|
||||
)
|
||||
return field_names
|
||||
|
||||
|
||||
@@ -125,26 +124,26 @@ def get_deleted_objects(objs, request, admin_site):
|
||||
has_admin = model in admin_site._registry
|
||||
opts = obj._meta
|
||||
|
||||
no_edit_link = "%s: %s" % (capfirst(opts.verbose_name), obj)
|
||||
no_edit_link = '%s: %s' % (capfirst(opts.verbose_name), obj)
|
||||
|
||||
if has_admin:
|
||||
if not admin_site._registry[model].has_delete_permission(request, obj):
|
||||
perms_needed.add(opts.verbose_name)
|
||||
try:
|
||||
admin_url = reverse(
|
||||
"%s:%s_%s_change"
|
||||
% (admin_site.name, opts.app_label, opts.model_name),
|
||||
None,
|
||||
(quote(obj.pk),),
|
||||
)
|
||||
admin_url = reverse('%s:%s_%s_change'
|
||||
% (admin_site.name,
|
||||
opts.app_label,
|
||||
opts.model_name),
|
||||
None, (quote(obj.pk),))
|
||||
except NoReverseMatch:
|
||||
# Change url doesn't exist -- don't display link to edit
|
||||
return no_edit_link
|
||||
|
||||
# Display a link to the admin page.
|
||||
return format_html(
|
||||
'{}: <a href="{}">{}</a>', capfirst(opts.verbose_name), admin_url, obj
|
||||
)
|
||||
return format_html('{}: <a href="{}">{}</a>',
|
||||
capfirst(opts.verbose_name),
|
||||
admin_url,
|
||||
obj)
|
||||
else:
|
||||
# Don't display link to edit, because it either has no
|
||||
# admin or is edited inline.
|
||||
@@ -153,10 +152,7 @@ def get_deleted_objects(objs, request, admin_site):
|
||||
to_delete = collector.nested(format_callback)
|
||||
|
||||
protected = [format_callback(obj) for obj in collector.protected]
|
||||
model_count = {
|
||||
model._meta.verbose_name_plural: len(objs)
|
||||
for model, objs in collector.model_objs.items()
|
||||
}
|
||||
model_count = {model._meta.verbose_name_plural: len(objs) for model, objs in collector.model_objs.items()}
|
||||
|
||||
return to_delete, model_count, perms_needed, protected
|
||||
|
||||
@@ -173,10 +169,10 @@ class NestedObjects(Collector):
|
||||
|
||||
def collect(self, objs, source=None, source_attr=None, **kwargs):
|
||||
for obj in objs:
|
||||
if source_attr and not source_attr.endswith("+"):
|
||||
if source_attr and not source_attr.endswith('+'):
|
||||
related_name = source_attr % {
|
||||
"class": source._meta.model_name,
|
||||
"app_label": source._meta.app_label,
|
||||
'class': source._meta.model_name,
|
||||
'app_label': source._meta.app_label,
|
||||
}
|
||||
self.add_edge(getattr(obj, related_name), obj)
|
||||
else:
|
||||
@@ -191,9 +187,7 @@ class NestedObjects(Collector):
|
||||
|
||||
def related_objects(self, related_model, related_fields, objs):
|
||||
qs = super().related_objects(related_model, related_fields, objs)
|
||||
return qs.select_related(
|
||||
*[related_field.name for related_field in related_fields]
|
||||
)
|
||||
return qs.select_related(*[related_field.name for related_field in related_fields])
|
||||
|
||||
def _nested(self, obj, seen, format_callback):
|
||||
if obj in seen:
|
||||
@@ -242,8 +236,8 @@ def model_format_dict(obj):
|
||||
else:
|
||||
opts = obj
|
||||
return {
|
||||
"verbose_name": opts.verbose_name,
|
||||
"verbose_name_plural": opts.verbose_name_plural,
|
||||
'verbose_name': opts.verbose_name,
|
||||
'verbose_name_plural': opts.verbose_name_plural,
|
||||
}
|
||||
|
||||
|
||||
@@ -275,7 +269,7 @@ def lookup_field(name, obj, model_admin=None):
|
||||
if callable(name):
|
||||
attr = name
|
||||
value = attr(obj)
|
||||
elif hasattr(model_admin, name) and name != "__str__":
|
||||
elif hasattr(model_admin, name) and name != '__str__':
|
||||
attr = getattr(model_admin, name)
|
||||
value = attr(obj)
|
||||
else:
|
||||
@@ -300,21 +294,13 @@ def _get_non_gfk_field(opts, name):
|
||||
model (rather something like `foo_set`).
|
||||
"""
|
||||
field = opts.get_field(name)
|
||||
if (
|
||||
field.is_relation
|
||||
and
|
||||
# Generic foreign keys OR reverse relations
|
||||
((field.many_to_one and not field.related_model) or field.one_to_many)
|
||||
):
|
||||
if (field.is_relation and
|
||||
# Generic foreign keys OR reverse relations
|
||||
((field.many_to_one and not field.related_model) or field.one_to_many)):
|
||||
raise FieldDoesNotExist()
|
||||
|
||||
# Avoid coercing <FK>_id fields to FK
|
||||
if (
|
||||
field.is_relation
|
||||
and not field.many_to_many
|
||||
and hasattr(field, "attname")
|
||||
and field.attname == name
|
||||
):
|
||||
if field.is_relation and not field.many_to_many and hasattr(field, 'attname') and field.attname == name:
|
||||
raise FieldIsAForeignKeyColumnName()
|
||||
|
||||
return field
|
||||
@@ -350,10 +336,7 @@ def label_for_field(name, model, model_admin=None, return_attr=False, form=None)
|
||||
elif form and name in form.fields:
|
||||
attr = form.fields[name]
|
||||
else:
|
||||
message = "Unable to lookup '%s' on %s" % (
|
||||
name,
|
||||
model._meta.object_name,
|
||||
)
|
||||
message = "Unable to lookup '%s' on %s" % (name, model._meta.object_name)
|
||||
if model_admin:
|
||||
message += " or %s" % model_admin.__class__.__name__
|
||||
if form:
|
||||
@@ -362,11 +345,9 @@ def label_for_field(name, model, model_admin=None, return_attr=False, form=None)
|
||||
|
||||
if hasattr(attr, "short_description"):
|
||||
label = attr.short_description
|
||||
elif (
|
||||
isinstance(attr, property)
|
||||
and hasattr(attr, "fget")
|
||||
and hasattr(attr.fget, "short_description")
|
||||
):
|
||||
elif (isinstance(attr, property) and
|
||||
hasattr(attr, "fget") and
|
||||
hasattr(attr.fget, "short_description")):
|
||||
label = attr.fget.short_description
|
||||
elif callable(attr):
|
||||
if attr.__name__ == "<lambda>":
|
||||
@@ -392,7 +373,7 @@ def help_text_for_field(name, model):
|
||||
except (FieldDoesNotExist, FieldIsAForeignKeyColumnName):
|
||||
pass
|
||||
else:
|
||||
if hasattr(field, "help_text"):
|
||||
if hasattr(field, 'help_text'):
|
||||
help_text = field.help_text
|
||||
return help_text
|
||||
|
||||
@@ -400,7 +381,7 @@ def help_text_for_field(name, model):
|
||||
def display_for_field(value, field, empty_value_display):
|
||||
from django.contrib.admin.templatetags.admin_list import _boolean_icon
|
||||
|
||||
if getattr(field, "flatchoices", None):
|
||||
if getattr(field, 'flatchoices', None):
|
||||
return dict(field.flatchoices).get(value, empty_value_display)
|
||||
# BooleanField needs special-case null-handling, so it comes before the
|
||||
# general null test.
|
||||
@@ -443,7 +424,7 @@ def display_for_value(value, empty_value_display, boolean=False):
|
||||
elif isinstance(value, (int, decimal.Decimal, float)):
|
||||
return formats.number_format(value)
|
||||
elif isinstance(value, (list, tuple)):
|
||||
return ", ".join(str(v) for v in value)
|
||||
return ', '.join(str(v) for v in value)
|
||||
else:
|
||||
return str(value)
|
||||
|
||||
@@ -453,14 +434,14 @@ class NotRelationField(Exception):
|
||||
|
||||
|
||||
def get_model_from_relation(field):
|
||||
if hasattr(field, "get_path_info"):
|
||||
if hasattr(field, 'get_path_info'):
|
||||
return field.get_path_info()[-1].to_opts.model
|
||||
else:
|
||||
raise NotRelationField
|
||||
|
||||
|
||||
def reverse_field_path(model, path):
|
||||
"""Create a reversed field path.
|
||||
""" Create a reversed field path.
|
||||
|
||||
E.g. Given (Order, "user__groups"),
|
||||
return (Group, "user__order").
|
||||
@@ -491,7 +472,7 @@ def reverse_field_path(model, path):
|
||||
|
||||
|
||||
def get_fields_from_path(model, path):
|
||||
"""Return list of Fields given path relative to model.
|
||||
""" Return list of Fields given path relative to model.
|
||||
|
||||
e.g. (ModelX, "user__groups__name") -> [
|
||||
<django.db.models.fields.related.ForeignKey object at 0x...>,
|
||||
@@ -528,42 +509,34 @@ def construct_change_message(form, formsets, add):
|
||||
|
||||
change_message = []
|
||||
if add:
|
||||
change_message.append({"added": {}})
|
||||
change_message.append({'added': {}})
|
||||
elif form.changed_data:
|
||||
change_message.append({"changed": {"fields": changed_field_labels}})
|
||||
change_message.append({'changed': {'fields': changed_field_labels}})
|
||||
if formsets:
|
||||
with translation_override(None):
|
||||
for formset in formsets:
|
||||
for added_object in formset.new_objects:
|
||||
change_message.append(
|
||||
{
|
||||
"added": {
|
||||
"name": str(added_object._meta.verbose_name),
|
||||
"object": str(added_object),
|
||||
}
|
||||
change_message.append({
|
||||
'added': {
|
||||
'name': str(added_object._meta.verbose_name),
|
||||
'object': str(added_object),
|
||||
}
|
||||
)
|
||||
})
|
||||
for changed_object, changed_fields in formset.changed_objects:
|
||||
change_message.append(
|
||||
{
|
||||
"changed": {
|
||||
"name": str(changed_object._meta.verbose_name),
|
||||
"object": str(changed_object),
|
||||
"fields": _get_changed_field_labels_from_form(
|
||||
formset.forms[0], changed_fields
|
||||
),
|
||||
}
|
||||
change_message.append({
|
||||
'changed': {
|
||||
'name': str(changed_object._meta.verbose_name),
|
||||
'object': str(changed_object),
|
||||
'fields': _get_changed_field_labels_from_form(formset.forms[0], changed_fields),
|
||||
}
|
||||
)
|
||||
})
|
||||
for deleted_object in formset.deleted_objects:
|
||||
change_message.append(
|
||||
{
|
||||
"deleted": {
|
||||
"name": str(deleted_object._meta.verbose_name),
|
||||
"object": str(deleted_object),
|
||||
}
|
||||
change_message.append({
|
||||
'deleted': {
|
||||
'name': str(deleted_object._meta.verbose_name),
|
||||
'object': str(deleted_object),
|
||||
}
|
||||
)
|
||||
})
|
||||
return change_message
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user