Операторы переключения с String
случаи были реализованы в [1 124] Java SE 7, по крайней мере 16 лет после того, как их сначала требовали. А ясная причина задержки не была обеспечена, но это, вероятно, имело отношение к производительности.
опция была теперь реализована в javac
с процессом "de-sugaring"; чистый, высокоуровневый синтаксис с помощью String
константы в case
объявления расширен во время компиляции в более сложный код после шаблона. Получающийся код использует инструкции по JVM, которые всегда существовали.
А switch
с String
случаи переводится в два переключателя во время компиляции. Первые карты каждая строка к уникальному integer— его положение в исходном переключателе. Это сделано первым включением хэш-кода маркировки. Соответствующий случай if
оператор, который тестирует строковое равенство; если существуют коллизии на хеше, тест является расположением каскадом if-else-if
. Вторые зеркала переключателя, что в коде первоисточника, но заменах случай маркирует их соответствующими положениями. Этот двухступенчатый процесс облегчает сохранять управление потоком исходного переключателя.
Для большей технической глубины на switch
, можно обратиться к Спецификации JVM, где компиляция операторов переключения описана. Короче говоря существует две различных инструкции по JVM, которые могут использоваться для переключателя, в зависимости от разреженности констант, используемых случаями. Оба зависят от использования целочисленных констант для каждого случая для выполнения эффективно.
, Если константы являются плотными, они используются в качестве индекса (после того, как, вычитая самое низкое значение) в таблицу инструкции pointers— tableswitch
инструкция.
, Если константы редки, двоичный поиск корректного случая является performed— lookupswitch
инструкция.
В de-sugaring switch
на [1 113] объекты, обе инструкции, вероятно, будут использоваться. Эти lookupswitch
подходит для первого, включают хэш-коды для нахождения исходного положения случая. Получающийся ординал является естественным пригодным для tableswitch
.
Обе инструкции требуют, чтобы целочисленные константы, присвоенные каждому случаю, были отсортированы во время компиляции. Во времени выполнения, в то время как O(1)
производительность [1 117] обычно кажется лучше, чем O(log(n))
производительность [1 119], это требует, чтобы некоторый анализ определил, является ли таблица достаточно плотной для выравнивания по ширине space– компромисс времени. Bill Venners записал большая статья , которая касается этого более подробно, наряду со взглядом под капотом на другие инструкции по управлению потоком Java.
До JDK 7, enum
мог приблизиться String
- базирующийся переключатель. Это использует помехи valueOf
метод, сгенерированный компилятором на каждом enum
тип. Например:
Pill p = Pill.valueOf(str);
switch(p) {
case RED: pop(); break;
case BLUE: push(); break;
}
It's amazing, but I found a best solution for me!
django-registration have form with checking uniqueness of email field: RegistrationFormUniqueEmail
example of usage here
Внимание: Приведенный ниже код был написан для более старой версии Django (до Custom Были представлены пользовательские модели ). Он содержит состояние гонки и следует использовать только с уровнем изоляции транзакции
SERIALIZABLE
и транзакции с ограниченным объемом запроса.
Ваш код не будет работать, поскольку атрибуты экземпляров полей доступны только для чтения. Боюсь, это может быть немного сложнее, чем вы думаете.
Если вы когда-либо будете создавать экземпляры User только с формой, вы можете определить настраиваемую ModelForm, которая обеспечивает такое поведение:
from django import forms
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
def clean_email(self):
email = self.cleaned_data.get('email')
username = self.cleaned_data.get('username')
if email and User.objects.filter(email=email).exclude(username=username).exists():
raise forms.ValidationError(u'Email addresses must be unique.')
return email
Затем просто используйте это форма везде, где вам нужно создать нового пользователя.
Кстати, вы можете использовать Model._meta.get_field ('field_name')
для получения полей по имени, а не по позиции. Так, например:
# The following lines are equivalent
User._meta.fields[4]
User._meta.get_field('email')
В документации Django рекомендуется использовать метод clean
для всех проверок, охватывающих несколько полей формы, потому что он вызывается после всех
и
. Это означает, что вы можете (в основном) полагаться на значение поля, присутствующее в cleaned_data
изнутри clean
.
Поскольку поля формы проверяются в том порядке, в котором они объявлены, Я думаю, что время от времени можно размещать проверку нескольких полей в методе
, если соответствующее поле появляется после всех других полей, от которых оно зависит. Я делаю это так, чтобы любые ошибки проверки были связаны с самим полем, а не с формой.
из модели, унаследованной пользователем, правильно переопределите атрибут. Это должно работать, поскольку в ядре django это бесполезно, потому что это просто сделать.
Один из возможных способов сделать это - установить обработчик pre-save для объекта User и отклонить сохранение электронного письма, уже существующего в таблице.
Первый ответ здесь работает для меня, когда я создаю новых пользователей, но он терпит неудачу, когда я пытаюсь отредактировать пользователя, поскольку я исключаю имя пользователя из представления. Есть ли для этого простое редактирование, которое сделает проверку независимой от поля имени пользователя?
Я также попытался включить поле имени пользователя в качестве скрытого (так как я не хочу, чтобы люди его редактировали), но это тоже не удалось, потому что django проверял дублирующиеся имена пользователей в системе.
(извините, это опубликовано в качестве ответа, но у меня нет прав, чтобы опубликовать его в качестве комментария. Не уверен, что я понимаю логику Stackoverflow по этому поводу.)