Другое событие NullPointerException
возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.
String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
System.out.println(phrase.equals(keyPhrase));
}
Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals
для гарантированного непустого объекта.
Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null
.
Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.
String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
System.out.println(phrase.equals(keyPhrase));
}
Я использовал простой прием:
class SuperFoo(models.Model):
name = models.CharField('name of SuperFoo instance', max_length=50)
...
class Meta:
abstract = True
class Foo(SuperFoo):
... # do something that changes verbose_name of name field of SuperFoo
Foo._meta.get_field('name').verbose_name = 'Whatever'
Принимая во внимание предостережение о том, что изменение Foo._meta.fields также повлияет на суперкласс - и, следовательно, действительно полезно, только если суперкласс является абстрактным, я обернул ответ, который @Gerry отбросил как декоратор многоразового использования класса:
def modify_fields(**kwargs):
def wrap(cls):
for field, prop_dict in kwargs.items():
for prop, val in prop_dict.items():
setattr(cls._meta.get_field(field), prop, val)
return cls
return wrap
Используйте это так:
@modify_fields(timestamp={
'verbose_name': 'Available From',
'help_text': 'Earliest date you can book this'})
class Purchase(BaseOrderItem):
pass
В приведенном выше примере изменяются verbose_name и help_text для унаследованного поля 'timestamp'. Вы можете передать столько аргументов ключевых слов, сколько есть полей, которые вы хотите изменить.
Посмотрите, как Django-CMS делает это, они переопределяют поле db_table
в моделях, унаследованных от CMSPlugin
. Основы (которые я также использую для своих собственных вещей) сводятся к следующему:
class SuperFooMetaClass(ModelBase):
def __new__(cls, name, bases, attrs):
new_class = super(SuperFooMetaClass, cls).__new__(cls, name, bases, attrs)
new_class._meta.verbose_name = "...." # perhaps only if not customized
return new_class
class SuperFoo(models.Model):
__metaclass__ = SuperFooMetaClass
....
Вы можете добавить некоторые проверки, например, обновлять только для подклассов (не прямого типа) или обновлять только в том случае, если значение не настроено.
Лучше всего установить / изменить метку в самой форме. Обращение к полю name
модели Foo
(например, поиск его в Foo._meta.fields
) фактически даст вам ссылку на поле name
в SuperFoo
, поэтому изменение его verbose_name
изменит его в обеих моделях.
Кроме того, добавление поля name
в поле Класс Foo
тоже не будет работать, потому что ...
Переопределение полей в родительской модели приводит к трудностям в таких областях, как инициализация новых экземпляров (указание какое поле инициализируется в
Модель .__ init __
) и сериализацию. Это функции, которые обычный Python наследование классов не должно иметь дело с таким же образом, поэтому разница между моделью Django наследование и класс Python наследование не просто произвольное.