Какие атрибуты метода используются в Django?

В документации для ModelAdmin.list_display описано несколько способов настройки метода/функции для использования и отображения в представлении списка администратора:

  • admin_order_field (описывает, какое поле в модели используется для упорядочения по методу)
  • allow_tags (позволяет отображать HTML, а не экранировать)
  • short_description (устанавливает метку для столбца)
  • boolean (определяет, должно ли поле обрабатываться логическое поле для отображения)

Он описывает их как атрибуты метода.

Добавление

Просто нашел еще несколько атрибутов метода/функции, используемых для фильтров шаблонов:

  • is_safe, используемый при маркировке фильтра шаблонов как безопасный
  • needs_autoescape, используемый для работы с автозащитой данных.

Какие еще атрибуты метода существуют в Django (или даже Python)? Или это действительно единственные случаи?

Разъяснение

Просто, чтобы быть ясным, об этом я и говорю конкретно.

В следующем коде:

class Foo(models.Model):
    name = models.CharField(max_length=100)
    color = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    def is_adult(self):
        return age > 18
    is_adult.boolean = True
    is_adult.short_description = "Over 18?"

    def colored_name(self):
        return '<span style="color: %s">%s</span>' % (self.color, self.name)
    colored_name.allow_tags = True
    colored_name.short_desciption = "Name"
    colored_name.admin_order_field = "name"

Атрибуты метода, о которых я говорю, это is_adult.boolean, is_adult.short_description, colored_name.allow_tags, colored_name.short_description и colored_name.admin_order_field.

Если вам нужна дополнительная информация, прочитайте связанную документацию.

Добавление # 2

Похоже, что это частично описано в PEP 232: Атрибуты функции. PEP указывает на сообщение списка рассылки, в котором перечислены другие потенциальные варианты использования атрибутов функций:

  • Мне нужно связать объявление типа стиля Java с помощью метода что он может быть распознан на основе его типа во время Java-метода отправка. Как вы это делаете с экземплярами?

  • Мне нужно связать "правило грамматики" с помощью метода Python, чтобы метод вызывается, когда парсер распознает синтаксическую конструкцию во входных данных.

  • Мне нужно связать объявление IDL с помощью метода, чтобы COM определение интерфейса может быть сгенерировано из исходного файла.

  • Мне нужно связать строку шаблона XPath с помощью метода Python так что метод может быть вызван, когда ходок по дереву обнаруживает конкретный шаблон в XML DOM.

  • Мне нужно связать несколько форм документации с помощью метода. Они оптимизированы для разных IDE, сред или языков.

Здесь реализация, позволяющая отвечать на атрибуты метода:

from django.contrib.admin import ModelAdmin
from datetime.datetime import now

class ProfileAdmin(ModelAdmin):

    list_display = ('votes_today',)

    class VotesToday:
        def __call__(self, model_admin, obj):
            today = now().replace(hour=0, minute=0, second=0, microsecond=0)
            return obj.vote_set.filter(created__gte=today)

        @property
        def short_description(self):
            return 'Votes today (%s)' % now().strftime('%B %d')

    @property
    def votes_today(self):
        if not hasattr(self, '__votes_today'):
            self.__votes_today = self.VotesToday()
        return self.__votes_today

Ответы

Ответ 1

смешно, что вы должны спросить об этом, я был немного удивлен другим использованием этого в документации django ранее сегодня:

def upper_case_name(obj):
    return ("%s %s" % (obj.first_name, obj.last_name)).upper()
upper_case_name.short_description = 'Name'
# !!! another occurrence of a "method attribute," an attribute
# assigned to a function object.

class PersonAdmin(admin.ModelAdmin):
    list_display = (upper_case_name,)

Итак, это означает, по сути, то, что определения функций - это тип объекта. Более знакомый способ сказать это может быть:

>>> def myfunc():
...   return "myvalue"

# 'myfunc' is now an object of type 'function' in the local scope. observe:

>>> type(myfunc)
<type: 'function'>

# you can, of course call __call__ on 'myfunc':
>>> myfunc()
"myvalue"
>>> myfunc.__call__()
"myvalue"

# and because 'myfunc' is also a normal object, you can define attributes on it.
myfunc.someattribute = 'somevalue'
myfunc.is_a_function = True
myfunc.takes_args = False

Итак, ваш вопрос немного связан с идеей, что python - это "объекты на всем пути вниз", то есть все в python - это объект.

Теперь почему это полезно? Предположим, вы хотите собирать и использовать некоторые метаданные для набора функций (или методов), которые вы пишете:

from operator import attrgetter

def add(x, y):
    return x + y

def subtract(x, y):
    return x - y

def get_attribute_value(obj, attr):
    return attrgetter(attr)(obj)

add.takes_args = True
add.number_of_args = 2
add.type_of_args = [int, int]
add.uses_black_magic = False

subtract.takes_args = True
subtract.number_of_args = 2
subtract.type_of_args = [int, int]
subtract.uses_black_magic = False

get_attribute_value.takes_args = True
get_attribute_value.number_of_args = 2
get_attribute_value.type_of_args = [object, str]
get_attribute_value.uses_black_magic = True

Вы могли бы использовать эти "атрибуты метода" полезным способом:

def perform_function_checks(function_list):
    for afunc in function_list:
        if getattr(afunc, 'takes_args'):
            print "function '%s' takes args! how unusual!" % (afunc.__name__,)
        if getattr(afunc, 'number_of_args'):
            print "function '%s' takes %s args." % (afunc.__name__, afunc.number_of_args)
        if getattr(afunc, 'type_of_args'):
            print "function '%s' takes %s args: %s" (afunc.__name__, len(afunc.type_of_args), [", and ".join(str(item)) for item in afunc.type_of_args])
        if getattr(afunc, 'uses_black_magic'):
            print "oh no! function '%s' uses black magic!" % (afunc.__name__,)

perform_function_checks([add, subtract, get_attribute_value])

# prints:
# function 'add' takes args! how unusual!
# function 'add' takes 2 args.
# function 'add' takes 2 args: <type 'int'>, and <type 'int'>
# function 'subtract' takes args! how unusual!
# function 'subtract' takes 2 args.
# function 'subtract' takes 2 args: <type 'int'>, and <type 'int'>
# function 'get_attribute_value' takes args! how unusual!
# function 'get_attribute_value' takes 2 args.
# function 'get_attribute_value' takes 2 args: <type 'object'>, and <type 'str'>
# oh no! function 'get_attribute_value' uses black magic!

Теперь, конечно, приведенное выше только для иллюстративных целей, если вы на самом деле пытались сделать этот тип интроспекции на функциях и объектах, которые вы, вероятно, захотите использовать модуль "проверка", вместо того, чтобы добавлять свой собственный bizarro метаданные: http://docs.python.org/library/inspect.html

Для получения дополнительной информации по этой теме, я бы рекомендовал этот пост:

http://www.cafepy.com/article/python_types_and_objects/python_types_and_objects.html

- EDIT:

Извините, я не рассматривал вашу "реализацию, которая позволяет атрибутам метода быть вызываемым" в добавлении № 2.

В этом обсуждении есть немного красной селедки. Что происходит там, это то, что кто-то использует декоратор @property, чтобы украсить метод, чтобы он выглядел как свойство (атрибут a.k.a.). Рассмотрим этот пример:

# let define a simple class
class Foo():
    # and a "normal" attribute
    an_attribute = 'a value'
    # now a method that we'll decorate with the @property decorator
    @property
    def what_kind(self):
        return str(self.__class__.__name__)

# now, instances of our Foo class will have the attribute '.what_kind'.

>>> bar = Foo()

# bar is now an instance of foo.

>>> bar.an_attribute
"a value"

# and finally our decorated method:

>>> bar.what_kind
"Foo"

Обратите внимание, что нам не нужно было вызывать "what_kind" выше, чтобы вернуть значение. Я думаю, что весь декоратор @property автоматически вызывает .__call__()

так что автор этого сообщения делает это, чтобы посмотреть на django, что вы просто добавляете к классу "простой старый" атрибут, когда, фактически,.short_description и .votes_today - фактически методы.

Здесь больше информации о декораторе/функции @property (которая встроена, BTW, поэтому вам не нужно ее импортировать): http://adam.gomaa.us/blog/2008/aug/11/the-python-property-builtin/

- EDIT: исправлено несколько проблем разметки и опечатка.

Ответ 2

Этот вопрос довольно далеко идущий, если я правильно его понимаю. В зависимости от объекта, который вы просматриваете, существует множество методов и атрибутов.

Я рекомендую:

  • Посмотрите на источник . Django docs - отличная отправная точка, но вы найдете ее намного более мощной, чем то, что открыто описано.
  • Получите настройку для завершения вкладки и откройте оболочку Django. Затем вы можете указать, какие методы и атрибуты доступны.

    python manage.py shell