Доброго времени суток! Вся валидация происходит на сервере, для фронт у меня есть
от бэков только url по которым происходит проверка. Подскажите пожалуйста, каким образом
я должна вытягивать regexp с сервера на клиентскую часть? Не совсем понимаю последовательность
действий, впервые сталкиваюсь с серверной валидацией, которую нужно перетянуть на фронт.
Ответы
Ответ 1
Обычно на фронте отсеивают запрещенные символы и другие явные ограничения (например,
длину), а после заполнения каждого очередного поля – отправляют AJAX'ом значение поля
на сервер, он уже сообщает ок или не ок и почему.
Ответ 2
есть готовые проверщики валидации, судя по тэгам - это валидация на джей кваери:
http://jqueryvalidation.org/validate/ или http://www.formvalidator.net/
если же регекспы перетащить из серверной части в клиенсткую, то копировать и вставлять
включая голову, так как небольше различия всетаки есть !
Но не могу понять, почему срабатывает проверка, только со второго раза? Возможно
кто-то работал с данным плагином.
Как можно исправить модуль, чтобы плагин срабатывал и срабатывал как положено (если
поля не заполнены, форма не отправляется отображаются error поля, если все в порядке,
то отправляются данные)?
Ответы
Ответ 1
В данном случае происходит неверное использование плагина. Перед тем как использовать
что-то, это что-то надо инициализировать.
По аналогии, рассчитывать, что сработает this.submitForm при отправке формы, не вызвав
app.init.
Далее, сама инициализация, выполнена не совсем корректна.
В документации к плагину можно увидеть, что свойство invalidHandler нужно для выполнения
своего кода в случае если валидация не прошла. В коде в вопросе, в этом методе идет
выставление переменной valid, которая в коде используется для определения того, прошла
валидация или нет.
Вместо это нужно было использовать метод form, который как раз возвращает результат
проверки, без дополнительных переменных.
В итоге метод validateForm: function(form){ можно удалить и заменить его использование
на одну строку
form.validate().form()
В этом случае плагин не будет инициализирован дважды и более раз, ввиду наличия проверки
внутри самого плагина.
Пример:
// Callback forms
(function() {
var app = {
init: function() {
this.setUpListeners();
},
setUpListeners: function() {
$(document).on('submit', 'form', this.submitForm);
$(document).on('keyup', 'input', this.removeError);
},
submitForm: function(e) {
e.preventDefault();
var form = $(this),
btnSubmit = form.find('[type="submit"]');
if (form.validate().form() === false) return false;
btnSubmit.addClass('disabled');
var str = form.serialize();
$.ajax({
url: 'contacts.php',
type: 'post',
data: str
}).done(function(msg) {
if (msg === "OK") {
var res = "
Well
done! You successfully read this important alert message.
Как я понял - нужно перед началом работы с валидацией проинициализировать validate
для формы. Т.е. вызвать $("form").validate() после загрузки DOM и скриптов. В вашем
примере я просто написал это перед app.init() (97 строка js) и форма начала работать
с 1ого раза.
Как в Python 3 реализовать проверку на целое число? (все положительные, отрицательные
целые числа и ноль)
Ответы
Ответ 1
Чтобы проверить является ли строка введённая пользователем целым числом, можно воспользоваться
int в try/except, похожим образом как показано в ответе на вопрос «Python 3 Проверка
на дробное число введённое пользователем», порекомендованный @Alex.B, заменив float
на int как @gil9red предложил и @slippyk явно показал:
def isint(s):
try:
int(s)
return True
except ValueError:
return False
Пример:
>>> isint('10')
True
>>> isint('a') # не десятичная цифра
False
>>> isint('²') # верхний индекс
False
>>> isint('১') # Bengali (Unicode)
True
Это может сломаться, если ввод не строка, например:
>>> isint(0.5) # XXX не работает для float
True
>>> 0.5 .is_integer()
False
>>> from numbers import Integral
>>> isinstance(0.5, Integral)
False
>>> isinstance(123, Integral)
True
>>> isinstance(1., Integral) # XXX float
False
>>> 1..is_integer() # но целое значение
True
>>> from fractions import Fraction
>>> isint(Fraction(1, 2)) # XXX не работает для дробей
True
>>> isinstance(Fraction(1, 2), Integral)
False
>>> isinstance(Fraction(1), Integral) # XXX дробь
False
>>> Fraction(1) == 1 # даже если целое значение
True
См. How to check if a float value is a whole number.
Если вы хотите проверить, что переданная строка содержит только десятичные цифры
и ничего более (к примеру, нет '+','-', ' ', '\n' символов в ней), то можно str.isdecimal
использовать:
>>> '123'.isdecimal()
True
>>> '+123'.isdecimal()
False
>>> isint('+123')
True
>>> isint(' 123\n')
True
>>> ' 123\n'.isdecimal()
False
isdecimal() можно использовать, чтобы имена файлов, содержащие цифры, в "естественном"
порядке отсортировать (как Windows-проводнике). См. Python analog of natsort function
(sort a list using a “natural order” algorithm).
Если хотите несколько таких чисел из ввода извлечь, можно регулярное выражение использовать:
>>> import re
>>> from datetime import datetime
>>> date_string = '2016-11-01 23:04:05'
>>> datetime(*map(int, re.findall(r'\d+', date_string)))
datetime.datetime(2016, 11, 1, 23, 4, 5)
Последнее, это возможно более простой, менее строгий (и эффективный) вариант для:
>>> datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S')
datetime.datetime(2016, 11, 1, 23, 4, 5)
Если вы хотите разрешить задавать целые числа в произвольном основании как в исходном
коде Питона, то передайте base=0:
>>> int('0b1110', 0) # binary ("01")
14
>>> int('0xcafe', 0) # hexadecimal
51966
Подробнее в документации int.
Ответ 2
Про числа в питоне почитайте:
a = int('19') # Переводим строку в число
b = int('19.5') # Строка не является целым числом
Traceback (most recent call last):
File "", line 1, in
ValueError: invalid literal for int() with base 10: '19.5'
В чем проблема исправить уже готовую функцию? @gil9red прямым текстом.
def isInt(value):
try:
int(value)
return True
except ValueError:
return False
isInt(input())
Ответ 3
принимает числовые значения
def isInt(n):
return int(n) == float(n)
>>> isInt(122)
True
>>> isInt(12.2)
False
>>> isInt(12.0)
True
>>>
Ответ 4
Попробуй через type(variable).
Например: if type(var) is int: print('Variable: %d is int!' % var)
Ответ 5
Проверка на самом деле простая. Как вы помните, любое деление или возведение в степень
в Python некоего выражения приведёт к тому, что результат операции примет тип переменной
float. Функция type() окажется бесполезной. Я для проверки пользуюсь простой формулой
деления целого числа на число с плавающей запятой. Если число целое, то результат будет
равен 1.0, а иначе отличаться от единицы. Вот пример кода для проверки возведённого
в степень числа:
number = 170
a=number**(1/2)
if int(a)/float(a)==1.0:
print('Квадратный корень из',int(number),'равен', int(number**(1/2)), ' - является
целым числом')
else:
print('Квадратный корень из',int(number),'- не целое число.')
Ответ 6
Используйте стандартный метод
>>> (-2.0).is_integer()
True
>>> (3.2).is_integer()
False
Я новичок в javascript, и у меня есть вопрос. У меня есть код с проверкой на валидность
заполнение регистрационной формы. Я думал как ее можно упростить и пришел к выводу,
что нужно создать отдельный метод и туда передавать нужные мне параметры, но столкнулся
с проблемой, что не знаю с какого места их лучше передавать. Как это сделать лучше
и правильно?
var namePattern = new RegExp("^([A-z]{4,20})$");
var emailPattern = new RegExp("^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,5})$");
var passwordPattern = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,20}$");
document.getElementById("registration_form").addEventListener("submit", function(event) {
var fName = document.getElementById("fName").value;
var lName = document.getElementById("lName").value;
var email = document.getElementById("email").value;
var password = document.getElementById("pass").value;
var confirmPassword = document.getElementById("confPass").value;
document.getElementById("error_first_name").innerHTML = '';
document.getElementById("error_last_name").innerHTML = '';
document.getElementById("error_email").innerHTML = '';
document.getElementById("error_password").innerHTML = '';
document.getElementById("error_confirmPassword").innerHTML = '';
if (!namePattern.test(fName)) {
document.getElementById("error_first_name").innerHTML = 'Wrong first name! range:
[4-20] and not contain numbers';
event.preventDefault();
} if (!namePattern.test(lName)) {
document.getElementById("error_last_name").innerHTML = 'Wrong last name! range:
[4-20] and not contain numbers';
event.preventDefault();
} if(!emailPattern.test(email)){
document.getElementById("error_email").innerHTML = 'Wrong email! Your email should
contains this symbols: [-_A-z0-9]';
event.preventDefault();
} if(!passwordPattern.test(password)){
document.getElementById("error_password").innerHTML = 'Wrong password! range:
[8-20], minimum one upper case letter: [A] and minimum one figure';
event.preventDefault();
} if(confirmPassword != password){
document.getElementById("error_confirmPassword").innerHTML = 'Your passwords
do not match';
event.preventDefault();
}
})
Моя форма:
Я пытаюсь уменьшить свой код, для этого я создал функцию, в которой передаю все параметры,
которые мне нужны, но что я не делаю правильно. Теперь это выглядит так.
var namePattern = new RegExp("^([A-z]{4,20})$");
var emailPattern = new RegExp("^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,5})$");
var passwordPattern = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,20}$");
document.getElementById("registration_form").addEventListener("submit", function(event){
function getParam(value, pattern, error_value, error_message){
error_value.innerHTML = '';
if(!pattern.test(value)){
error_value.innerHTML = error_message;
event.preventDefault();
}
}
})
Но то, что я делаю, неверно, как я могу улучшить его и правильно передать мои параметры?
Нужно ли передавать их с помощью html или как лучше будет это реализовать?
Ответы
Ответ 1
Все с комментариями.
Примечание: элементы ошибок должны начинатся с error_ и дальше должно быть написано
имя поля которое в errorInfo(first_name, last_name и т.д), то есть быть вот таким:
error_first_name, error_last_name и т.д
var namePattern = new RegExp("^([A-z]{4,20})$");
var emailPattern = new RegExp("^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,5})$");
var passwordPattern = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,20}$");
document.getElementById("registration_form").addEventListener("submit", function(event) {
event.preventDefault(); // достаточно написать один раз
var fName = document.getElementById("fName").value;
var lName = document.getElementById("lName").value;
var email = document.getElementById("email").value;
var password = document.getElementById("pass").value;
var confirmPassword = document.getElementById("confPass").value;
// набор полей ошибок
var errorInfo = {
first_name: { // имя поля(потом находит элемент по нему document.getElementById('error_'
+ name))
// валидное ли поле? если true то не будет ошибки
validity: namePattern.test(fName),
// сообщение об ошибке
text: 'Wrong first name! range: [4-20] and not contain numbers'
},
last_name: {
validity: namePattern.test(lName),
text: 'Wrong last name! range: [4-20] and not contain numbers'
},
email: {
validity: emailPattern.test(email),
text: 'Wrong email! Your email should contains this symbols: [-_A-z0-9]'
},
password: {
validity: passwordPattern.test(password),
text: 'Wrong password! range: [8-20], minimum one upper case letter: [A] and
minimum one figure'
},
confirmPassword: {
validity: confirmPassword === password,
text: 'Your passwords do not match'
}
}
// перебирает errorInfo, name - имя поля(ключ объекта errorInfo)
for (let name in errorInfo) {
var errorMsg = ''; // текст ошиьки, изначально ставит ошибку как ее нет
// если поле не валидное
if (!errorInfo[name].validity)
errorMsg = errorInfo[name].text; // ставит текст ошибки
// ставит текст ошибки (innerHTML медленее textContent)
document.getElementById('error_' + name).textContent = errorMsg;
}
})
Ответ 2
Все маски можно ввести в data- атрибуты (о бессмысленности валидации e-mail регекспом
можно почитать, например здесь)
Тексты ошибок можно вписать на страницу заранее и просто показывать/прятать блок
Все инпуты можно перебрать в цикле как дочерние к элементу
document.getElementById("registration_form").addEventListener("submit", function(event) {
var blocks = this.querySelectorAll('ul');
for (var i = 0; i < blocks.length; i++) {
var input = blocks[i].querySelector('input');
var msg = blocks[i].querySelector('.error');
var pattern = input.getAttribute('data-pattern');
var valid = false;
if (pattern !== null) {
var re = new RegExp(pattern);
valid = re.test(input.value);
} else
valid = input.value == document.getElementById('pass').value;
if (!valid) {
msg.style.display = 'block';
event.preventDefault();
} else
msg.style.display = 'none';
}
})
.error {
color: #ff0000;
display: none;
}
Всем доброго времени суток)
Разрабатываю систему с использованием DDD.
В системе есть 2 модуля:
Модуль конфигурации. Он занимается регистрацией новых устройств: само устройство,
его модель и прочие параметры.
Модуль проверки устройства на дефекты.
Каждый тип устройства описывает конкретный класс-сущность (entity). При этом при
создании объекта класса-сущности необходимо производить валидацию его параметров. Регистрация
нового устройства в системе заканчивается его сохранением в базе данных с использованием
соответствующего репозитория (repository).
В модуле проверки выбранное из списка устройство загружается в программу из базы
данных. При помощи соответствующего репозитория на основе идентификатора возвращается
устройство для проверки на неисправности. На выходе репозитория в диагностику загружается
соответствующий объект класса-сущности устройства. Однако для создания такого объекта
необходимо проводить его валидацию.
Возникает вопрос: насколько необходимо проводить валидацию извлеченной из базы данных
информации, если изначально в базу данных записывается верная информации о сущности?
Сама валидация осуществляется классом-валидатором, встраивающимся в соответствующий
объект-сущность устройства.
Может быть я что-либо совсем не так понимаю?
Ответы
Ответ 1
В базе нужно хранить уже достоверную и правильную информацию, чтобы сохранялась целостность
данных. То есть что ты именно будешь верифицировать при извлечении из бд, я не понимаю.
Проверять данные на корректность, нужно обязательно (!!) перед сохранением в БД.
Ответ 2
Я полностью согласен с @ImZ в том что при восстановлении из БД сущности валидировать
не надо. Однако, проверять надо не перед сохранением в БД, а при попытке изменить сущность.
Т.е. более правильно, когда нельзя привести сущность в невалидное состояние передав
неправильное значение. Для этого сущность должна проводить проверку на корректность
значений задаваемых через публичный интерфейс.
Все это приводит к двум выводам:
Сущность сохраняемая в БД априори валидна и повторная валидация не
требуется.
Если используется не тупой объект с сеттерами и
геттерами, то вполне ожидаемо, что часть полей представляющих
состояние объекта не будет представлено в публичном интерфейсе. И
чтобы не идти на нарушение инкапсуляции добавляя геттеры и сеттеры,
необходимы механизмы инициализации объекта минуя публичный
интерфейс.
Т.о. задача сохранения и восстановления в/из БД это чтение и последующая запись некоторого
приватного состояния в объект.
Есть бизнес класс, который выполняет какую-то единицу работы:
class EmployeeCalculator
{
public Pay CalculatePay(Employee employee)
{
//Do somthing
}
}
По каким-то причинам выполнение метода CalculatePay может завершиться с ошибкой.
Собственно вопрос: как лучше будет передать ошибку ? Можно сделать какой-нибудь класс
типа:
public class PayResult
{
public Pay Pay { get; set; }
public bool IsError { get; set; }
public string ErrorMessage { get; set; }
}
И возвращать его из метода CalculatePay, а на вызывающей стороне проверять IsError.
Либо из метода CalculatePay бросить исключение, и так же на вызывающей стороне ловить
его. Если бросать исключение то на каком уровне его ловить (предположим что наше приложение
использует MVC) ? На уровне контроллеров и там уже перерабатывать и выдавать сообщения
на UI или это может быть отдельный слой обработки ошибок между контроллером и бизнес
логикой ?
PS. Буду благодарен любой информации по вопросу (ваши мысли, статьи, книги).
Ответы
Ответ 1
Все зависит от причины, по которой не удалось посчитать Pay.
Если это действительно исключительная ситуация - например, невалидные данные для
расчета - то нужно бросать исключение.
Если это ожидаемая ситуация - например, Employee ничего не заработал - то стоит возвращать
или Pay с 0 (возможно, как преодпределенный экземпляр Pay.None), или возвращать null
- если ваш клиентский код готов этот null обработать.
Ответ 2
Лучше PayResult, если результат не посчитан значит PayResult.Pay = null, если клиенту
нужны подробности то пусть смотрит PayResult.ErrorMessage. Исключения нужны когда системный
сбой, неправильные аргументы функции когда продолжить работу невозможно, а у вас возврат
результата которого можно и не получить - вполне штатная ситуация.
Ответ 3
Если ошибка возникает очень редко (является исключительной ситуацией), то выкидывать
исключение.
Если ошибка - почти норма, возникает часто, то можно возвращать код ошибки.
Распространённый подход - иметь два метода: один выкидывает исключение, другой, с
префиксом Try возвращает булево значение, сигналирующее об успешности операции. Например:
int.Parse - int.TryParse
DateTime.Parse - DateTime.TryParse
и другие.
Проблема в следующем если использовать , то
по умолчанию выбирается "что-то", и нельзя использовать required для select, так как
уже выбрано "что-то". В связи с этим вопрос как реализовать placeholder для select.
Отдельным блоком с position: absolute, не использую, может есть что-то получше.
Ответы
Ответ 1
Проверьте чтото типа
А дальше через Jquery делайте проверку типа
if($('#first').val()=='0'){alert('Choose it');}
Есть 2 SelectedModels:
SelectedCanvas
{
public CanvasModel {get;set;}
}
SelectedImage
{
public ImageModel {get;set;}
}
, каждая из которых содержит свою модель:
CanvasModel
{
public double CanvasWidth {get;set;}
public double CanvasHeight {get;set;}
}
ImageModel
{
public double X {get;set;}
public double Y {get;set;}
}
Свойства выбранной CanvasModel(Width, Height) должны накладывать ограничения на свойства
выбранной ImageModel(X,Y), на которую байндятся несколько View-моделей.
Вопрос: как правильнее организовать валидацию, с учетом того, что прямой связи между
выбранными моделями нет?
Ответы
Ответ 1
Ориентируясь на
Свойства выбранной CanvasModel(Width, Height) должны накладывать ограничения на
свойства выбранной ImageModel(X,Y), на которую байндятся несколько View-моделей.
я бы сделал как-нибудь так
public class MainVM : BaseVM
{
private CanvasVM _selectedCanvas;
public CanvasVM SelectedCanvas
{
get { return _selectedCanvas; }
set
{
// Тут, по-хорошему, тоже надо проверять на доспустимость выбора, если SelectedImage
!= null
_selectedCanvas = value;
RaisePropertyChanged("SelectedCanvas");
}
}
private ImageVM _selectedImage;
public ImageVM SelectedImage
{
get { return _selectedImage; }
set
{
if (/*Проверка на допустимость выбора с учетом SelectedCanvas*/)
{
// Ошибка, недопустимое значение
throw new ArgumentException("Такой Image не подойдет!");
}
_selectedImage = value;
RaisePropertyChanged("SelectedImage");
}
}
}
Где
ImageVM - ViewModel для ImageModel
CanvasVM - ViewModel для CanvasModel
MainVM - ViewModel, в которой происходит работа по установке SelectedImage и SelectedCanvas.
А View я бы привязывал к MainVM.
Ответ 2
Расскажу как был решен вопрос, может кому-то пригодится.
Был выделен интерфейс
IBounds
{
Width { get;set; }
Height { get;set; }
}
от него унаследован CanvasModel
в ImageModel было добавлено св-во:
ImageModel
{
IBounds Bounds { get; set; }
}
При добавлении новой ImageModel св-ву Bounds присваивается SelectedCanvas.CanvasModel
Валидация реализуется в ImageModel.
Имеется следующая ситуация, есть на странице две кнопки, которые лежат рядом друг
с другом Сформировать программу из краткосрочно плана и Сформировать отчет сравнение
с краткосрочным планом по нажатию на которые открывается модальное окно:
HTML-код модального окна и кнопок открытия модального окна:
Выбор краткосрочного плана
Выберите из предложенного списка краткосрочный план, на основании которого
будут произведены действия.
Если нажать на одну из кнопок, то модальное окно выглядит примерно так:
JavaScript код, который обрабатывает нажатия на кнопки на странице, в том числе и
в модальном окне:
function fillChoisePlanSelector() {
console.log('fillChoisePlanSelector');
$.get('@Url.Action("GetShortTermPlanList", "Programs")', {
year: 2016 })
.done(function(result) {
var parsedResult = JSON.parse(result);
$.each(parsedResult, function(index, elem) {
$('#choise-plan')
.append($('
Ответы
Ответ 1
Методом проб и ошибок выяснил, что если у кнопки убрать data-dismiss="modal" и в
JavaScript убрать обработку нажатия на кнопку $('#btn-choise-plan-ok').click то валидация
начинает работать. При любой попытке навесить обработку нажатия на кнопку - валидация
перестает работать. Поэтому было решено перенести форму внутрь модального окна (она
была вокруг модалки):
И навесить обработку отправки данных с формы:
$('#form-choise-plan').submit(function(e) {
e.preventDefault();
$('#modal-choise-plan').modal('hide');
if ($('#btn-click-type').val() === 'report-compare-with-plan') {
//TODO: Сформировать отчет
console.log('Сформировать отчет');
} else {
//TODO: Сформировать программу
console.log('Сформировать программу');
}
});
Оставшийся код остался без изменений. Таким образом валидация обязательного поля
работает:
Интересную особенность заметил.
:root {} на сайтах встречаю ооооочень редко, но при этом, натыкаюсь на статьи (типо
этой), где говориться только о плюсах :root и других штуках.
Но при этом, при проверки валидации CSS на W3C получил аж 89 ошибок, связанных с :root.
Как быть? Как вы к этому относитесь?
Ответы
Ответ 1
Нет ничего неправильного в том, чтобы использовать CSS-переменные, да и :root тоже,
это однозначно валидный код. Ошибки выкидывает просто потому, что парсер валидатора
все еще не доработали — вероятно, по причине того, что спецификация custom properties
все еще носит статус Candidate Recomendation.
Источники:
псевдокласс :root, CSS-переменные.
Есть форма регистрации с двумя полями: пароль и подтверждение пароля. Если нажать
кнопку с незаполненными полями, появится tooltip и красная обводка. Кроме того, даже
после расфокусирования формы при input:hover появляется подсказка с текстом ошибки.
Как сделать чтобы в точности такой же эффект появлялся когда пароли не совпадают?
(function() {
var validationApp = angular.module("validationApp", [])
validationApp.controller("ValidationCtrl", function() {
})
})()
Воспользуйтесь ng-class для установки ng-invalid при срабатывании условия не равенства
паролей. В проверку так же желательно включить условие, что пароль не пуст, иначе они
будут светиться по умолчанию.
Доброго времени суток, форумчане!
Подскажите пожалуйста, почему не работает валидация формы. Делаю всё, как тут:
jQuery Validate Demo
и тут
Validate a Form using jQuery and Bootstrap Validator
Может что-то не так с файлом скрипта? Или подключаю его как-то не так?
Код скрипта, взятый из примера и переделанный под мои нужды:
$(document).ready(function () {
$('#timeValidationForm').bootstrapValidator({
container: '#messages',
feedbackIcons: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
time: {
validators: {
notEmpty: {
message: 'The full name is required and cannot be empty'
}
},
stringLength: {
min: 1,
max: 5,
message: 'Input must be larger than 1 and less than 5'
}
}
}
});
});
Код html. Нужно заметить, что валидация поля происходит в модальном окне и должна
работать без нажатия кнопки "submit":
@using( Html.BeginForm("ClockChanger", "Clocks", FormMethod.Post, new{@id="timeValidationForm",
@class="form-horizontal"} ) )
{
}
Скрипт подключаю в теге с помощью
Ответы
Ответ 1
В коде инициализации валидатора ошибка - скобка поставлена неверно и поле stringLength
не входит в объект validators.
$(document).ready(function () {
$('#timeValidationForm').bootstrapValidator({
container: '#messages',
feedbackIcons: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
time: {
validators: {
notEmpty: {
message: 'The full name is required and cannot be empty'
},
stringLength: {
min: 1,
max: 5,
message: 'Input must be larger than 1 and less than 5'
}
},
}
}
});
});
Исправленный вариант в fiddle.
Как сделать проверку на число? Например:
a = float(input('Текст'))
Как проверить а, если пользователь введет строку? При этом мне ему нужно написать,
что это не число.
Ответы
Ответ 1
Проверка
Этот метод возвращает True, если получил любую строку, которую можно распознать как
число с плавающей точкой.
def isfloat(value):
try:
float(value)
return True
except ValueError:
return False
Чтобы дать ответ пользователю, вы можете использовать тернарный оператор:
print('это число' if isfloat(input('введите число')) else 'это не число')
Или обычное условие:
a = input('введите число')
if isfloat(a):
print('это число')
else
print('это не число')
Вот что является и не является "числом" (float) в Python:
#Команда isFloat? Комментарий
#------------------------------------ -------- --------------------------------
print(isfloat("")) #False Пустая строка
print(isfloat("127")) #True Распознаваемая строка
print(isfloat(True)) #True Истина - это число
print(isfloat("True")) #False "Истина" - это не число!
print(isfloat(False)) #True Зато Ложь - число
print(isfloat("123.456")) #True Десятичное число
print(isfloat(" -127 ")) #True Пробелы вокруг числа обрезаются
print(isfloat("\t\n12\r\n")) #True Включая переносы строк
print(isfloat("NaN")) #True Not a number - число!
print(isfloat("NaNanananaBATMAN")) #False Но не в составе большей строки
print(isfloat("-iNF")) #True Минус бесконечность
print(isfloat("123.E4")) #True Экспоненциальная нотация
print(isfloat(".1")) #True Только мантисса
print(isfloat("1,234")) #False Дискриминация, запятая не считается
разделителем!
print(isfloat(u'\x30')) #True Unicode - это число
print(isfloat("NULL")) #False "Null" - обычная строка
print(isfloat(0x3fade)) #True Шестнадцатеричное число
print(isfloat("6e7777777777777")) #True Насколько большое, что считается
бесконечным
print(isfloat("1.797693e+308")) #True Максимальное значение float
print(isfloat("infinity")) #True То же что inf - бесконечность
print(isfloat("infinityandBEYOND")) #False Но не в составе большей строки
print(isfloat("12.34.56")) #False Только одна точка
print(isfloat(u'四')) #False Японский символ '4' это не float.
print(isfloat("#56")) #False знак фунта стерлингов
print(isfloat("56%")) #False Проценты не обрабатываются
print(isfloat("0E0")) #True Странная, но экспонента
print(isfloat(0**0)) #True Ноль в степени ноль
print(isfloat("-5e-5")) #True Отрицательная степень
print(isfloat("+1e1")) #True Можно явно указать, что число положительное
print(isfloat("+1e1^5")) #False Нераспознаваемый экспоненциальный
формат
print(isfloat("+1e1.3")) #False Экспонента должна быть целым числом
print(isfloat("-+1")) #False Слишком много знаков
print(isfloat("(1)")) #False Скобки препятствуют распознаванию
Эта таблица - перевод ответа, данного Eric Leschinski на en.SO. Я закомментировал
лишние части строки, чтобы ее можно было скопировать и выполнить как код.
Ответ 2
try:
a = float(input('Текст'))
except ValueError:
print('Введено не число')
Есть два изсестных мне подхода проверки вводимых данных и выдачи соотвествующего
сообщения пользователю - это генерация исключения в сеттере и использование ExceptionValidationRule
и использование интерфейса IDataError.
Вопрос в следующем: можно ли применять разные стили ErrorTemplate в зависимости от
типа исключения?
Приведу пример - есть класс описывающий объект, с полями A, B и C. В зависимости
от занчений A и B поле C может быть либо обязательным, либо желательным. В первом случае
незаполненость поля C - это критическая ошибка и нельзя давать пользователю сохранить
объект, во втором же случае нужно просто уведомить пользователя.
На деле же я хочу применять разные стили в зависимости от того желательное поле или
обязательное для заполнения. Скажем для обязательных подсвечивать контролы красным,
а для желательных - зеленым. Возможно ли это, или придется придумать другой подход,
без использованяи встроенной валидации?
Ответы
Ответ 1
В общем решение нашлось в ходе изучения структуры класса Validation. Почему я его
так долго искал - не знаю, не туда смотрел видимо.
У класса Validation есть коллекция Errors, которая содержит описание ошибок валидации.
Дак вот каждый элемент этой коллекции имеет тип ValidationError, у которого и есть
нужное нам свойство Exception. Теперь мы можем основываясь на его типе, определять шаблон.
Приведу пример. Может кому пригодится.
Есть простой класс:
public class SomeClass
{
public int A { get; set; }
public int B { get; set; }
private int _c;
public int C
{
get { return _c; }
set
{
// Вот тут мы и будем в зависимости от состояния других полей генерировать
разные исключения
if (A == 0 && B == 0 && value == 0)
throw new ArgumentMandatoryException("Поле является обязательным к заполнению");
if ((A != 0 || B != 0) && value == 0)
throw new ArgumentDesiredException("Поле является желательным к заполнению");
_c = value;
}
}
}
Как видите в сеттере свойства C мы в зависимости от выполнения условия бросили два
разных исключения. Теперь нам надо обработать это в шаблоне Validation.ErrorTemplate.
Здесь нам помогут ContentControl и DataTemplate. Получим что-то такое:
Теперь в зависимости от типа исключения рамка будет либо класной, либо желтой.
Один из методов бизнес-логики начинается с кода валидации:
public void Update(ProductDto dto)
{
if (dto == null)
{
throw new ArgumentNullException(nameof(dto));
}
var validContext = new ValidationContext(dto);
Validator.ValidateObject(dto, validContext);
//...
}
Если в метод передается null, то я выбрасываю стандартное исключение ArgumentNullException
и никакой дополнительной информации как видите не отсылаю.
Мне кажется, что блок проверки на null излишен, потому что в случае dto = null следующее
за ним выражение var validContext = new ValidationContext(dto) так и так выбросит
то же самое исключение:
Будет ли ругаться "практика правильного дизайна", если я сокращу метод так?
public void Update(ProductDto dto)
{
var validContext = new ValidationContext(dto);
Validator.ValidateObject(dto, validContext);
//...
}
Ответы
Ответ 1
Да, такое изменение я бы не назвал правильным.
Дело в том, что вы тем самым вносите в ваш метод связность. Ваш код будет правильным
лишь в том случае, если
конструктор ValidationContext проверяет входящий объект на null, и бросает исключение, и
у вас до вызова этого конструктора нету другого кода, который использует dto или
делает какую-то другую полезную работу.
Каждое из этих предположений нужно будет держать в голове, работая с данным кодом.
Причём в коде придётся ещё и оставлять комментарий, который будет объяснять, что null
не является валидным входным значением, и почему именно в этом месте нету проверки на null.
В противоположность этому проверка в начале является практически самодокументируемым
кодом, она сразу говорит читателю, что нулевое входное значение неверно.
Чем меньше нужно держать в голове, тем лучше, и тем меньше вероятность ошибки.
Ещё одно мелкое соображение в пользу ранней проверки: если вы видите stack trace
упавшего на ArgumentNullException приложения, то ошибка скорее всего находится в методе
на один фрейм выше метода, бросившего исключение. В случае «пропуска» плохого аргумента
в глубину это соображение не работает.
Ответ 2
Внесу краткое дополнение к ответу.
Не сложность заметить, что конструкции вида:
public void Update(ProductDto dto)
{
if (dto == null)
{
throw new ArgumentNullException(nameof(dto));
}
//...
}
выглядят довольно громоздко и не эстетично, так и возникает желание избавиться от
них. А потому одним из способов добиться этого, может стать использование контрактов
(Code Contracts). Например, в случае их использования код выглядел бы так:
public void Update(ProductDto dto)
{
// Определили Предусловие. Нарушение предусловия говорит о том,
// что клиент не прав.
Contract.Requires(dto != null);
//...
}
Это не только сократит его и сделает чище, но а так же более явно выразит ваши требования.
Для валидации форм использую плагин jquery.validate. К функционалу плагина я добавил регулярку проверки имени. $.validator.addMethod("name", function( value, element ) {
return this.optional( element ) || /[а-яё]/i.test( value );
});
Но возникла проблема, при вводе, например, 123Александр, плагин не выдаёт ошибку, т.е регулярка не срабатывает. $("form").validate({
rules: {
email: {
required: true,
email: true
},
name: {
required: true,
minlength: 3,
name: true
}
}
});
Как решить проблему ввода корректного имени, чтобы не было таких ошибок?
Ответ
/[а-яё]/i возваращает true при нахождении одной русской буквы в строке. Если необходима валидация целой строки, т.е. все символы в строке должны являться русскими буквами, используйте /^[а-яё]+$/i
Где:
^ - начало строки
[а-яё]+ - 1 и более русских букв
$ - конец строки
/i - модификатор, активирующий нечувствительность выражения к регистру символов.
Демо:
var r = /^[а-яё]+$/i;
console.log(r.test("Александр"));
console.log(r.test("123Александр"));
Но не могу понять, почему срабатывает проверка, только со второго раза? Возможно кто-то работал с данным плагином. Как можно исправить модуль, чтобы плагин срабатывал и срабатывал как положено (если поля не заполнены, форма не отправляется отображаются error поля, если все в порядке, то отправляются данные)?
Ответ
В данном случае происходит неверное использование плагина. Перед тем как использовать что-то, это что-то надо инициализировать. По аналогии, рассчитывать, что сработает this.submitForm при отправке формы, не вызвав app.init
Далее, сама инициализация, выполнена не совсем корректна. В документации к плагину можно увидеть, что свойство invalidHandler нужно для выполнения своего кода в случае если валидация не прошла. В коде в вопросе, в этом методе идет выставление переменной valid, которая в коде используется для определения того, прошла валидация или нет. Вместо это нужно было использовать метод form, который как раз возвращает результат проверки, без дополнительных переменных. В итоге метод validateForm: function(form){ можно удалить и заменить его использование на одну строку form.validate().form()
В этом случае плагин не будет инициализирован дважды и более раз, ввиду наличия проверки внутри самого плагина. Пример:
// Callback forms
(function() {
var app = {
init: function() {
this.setUpListeners();
},
setUpListeners: function() {
$(document).on('submit', 'form', this.submitForm);
$(document).on('keyup', 'input', this.removeError);
},
submitForm: function(e) {
e.preventDefault();
var form = $(this),
btnSubmit = form.find('[type="submit"]');
if (form.validate().form() === false) return false;
btnSubmit.addClass('disabled');
var str = form.serialize();
$.ajax({
url: 'contacts.php',
type: 'post',
data: str
}).done(function(msg) {
if (msg === "OK") {
var res = "
Well done! You successfully read this important alert message.
Всем доброго времени суток)
Разрабатываю систему с использованием DDD. В системе есть 2 модуля:
Модуль конфигурации. Он занимается регистрацией новых устройств: само устройство, его модель и прочие параметры.
Модуль проверки устройства на дефекты.
Каждый тип устройства описывает конкретный класс-сущность (entity). При этом при создании объекта класса-сущности необходимо производить валидацию его параметров. Регистрация нового устройства в системе заканчивается его сохранением в базе данных с использованием соответствующего репозитория (repository).
В модуле проверки выбранное из списка устройство загружается в программу из базы данных. При помощи соответствующего репозитория на основе идентификатора возвращается устройство для проверки на неисправности. На выходе репозитория в диагностику загружается соответствующий объект класса-сущности устройства. Однако для создания такого объекта необходимо проводить его валидацию.
Возникает вопрос: насколько необходимо проводить валидацию извлеченной из базы данных информации, если изначально в базу данных записывается верная информации о сущности? Сама валидация осуществляется классом-валидатором, встраивающимся в соответствующий объект-сущность устройства. Может быть я что-либо совсем не так понимаю?
Ответ
В базе нужно хранить уже достоверную и правильную информацию, чтобы сохранялась целостность данных. То есть что ты именно будешь верифицировать при извлечении из бд, я не понимаю. Проверять данные на корректность, нужно обязательно (!!) перед сохранением в БД.
Есть бизнес класс, который выполняет какую-то единицу работы: class EmployeeCalculator
{
public Pay CalculatePay(Employee employee)
{
//Do somthing
}
}
По каким-то причинам выполнение метода CalculatePay может завершиться с ошибкой.
Собственно вопрос: как лучше будет передать ошибку ? Можно сделать какой-нибудь класс типа: public class PayResult
{
public Pay Pay { get; set; }
public bool IsError { get; set; }
public string ErrorMessage { get; set; }
}
И возвращать его из метода CalculatePay, а на вызывающей стороне проверять IsError.
Либо из метода CalculatePay бросить исключение, и так же на вызывающей стороне ловить его. Если бросать исключение то на каком уровне его ловить (предположим что наше приложение использует MVC) ? На уровне контроллеров и там уже перерабатывать и выдавать сообщения на UI или это может быть отдельный слой обработки ошибок между контроллером и бизнес логикой ? PS. Буду благодарен любой информации по вопросу (ваши мысли, статьи, книги).
Ответ
Все зависит от причины, по которой не удалось посчитать Pay. Если это действительно исключительная ситуация - например, невалидные данные для расчета - то нужно бросать исключение. Если это ожидаемая ситуация - например, Employee ничего не заработал - то стоит возвращать или Pay с 0 (возможно, как преодпределенный экземпляр Pay.None), или возвращать null - если ваш клиентский код готов этот null обработать.
Все привет. Кто сталкивался с компонентом PhalconValidation? Я, прочитав документацию, не могу понять, как производить валидацию, набросал вот такой вот подход:
public function initialize()
{
$this->add('name', new PresenceOf(array(
'message' => 'Вы не заполнили Имя и Фамилию'
))); $this->add('name', new RegexValidator(array(
'pattern' => '/^[а-яА-ЯёЁa-zA-Z-]+$/ui',
'message' => 'Имя и Фамилия могут содержать только буквы и тире'
))); $this->add('name', new StringLength(array(
'max' => 50,
'min' => 5,
'messageMaximum' => 'Имя и Фамилия не может содержать больше 50 символов',
'messageMinimum' => 'Имя и Фамилия не может содержать меньше 5 символов'
))); $this->add('email', new PresenceOf(array(
'message' => 'Вы не заполнили Email адрес'
))); $this->add('email', new Email(array(
'message' => 'Не корректный Email адрес'
))); $this->add('password', new PresenceOf(array(
'message' => 'Вы не заполнили Пароль'
))); $this->add('password', new StringLength(array(
'min' => 8,
'minimumMessage' => 'Пароль не может быть короче 8 символов'
))); $this->add('confirm', new PresenceOf(array(
'message' => 'Вы не заполнили Подтверждение пароля'
))); $this->add('password', new Confirmation(array(
'message' => 'Пароли не совпадают',
'with' => 'confirm'
)));
}
Это неправильный подход, потому что если формы пустые, ошибки всплывают все, а не те, что проверяют форму на пустоту. Как исправить такое положение?
И да, если установить 'cancelOnFail' => true, то валидация не пройдёт дальше той валидации, которая имеет этот параметр первая в очереди.
UPD 06.11.14:
Приведу пример валидации.
Есть 4 поля, к примеру (имя/емэйл/пароль/и подтверждение пароля).
Первым делом валидация проверяет заполнены поля или нет, потом поэтапно каждое поле, то есть изначально он проверяет все поля на пустоту, а потом все поэтапно, и поля не связаны между собой, за исключением пароля, и его подтверждения. Как то так.
Ответ
В чем проблема производить валидацию в два этапа и считать сообщения по выходу с первого? Зачем нужен PresenceOf, если для этого поля уже работает StringLength/Confirmation/Email?
Phalcon, конечно, фреймворк с прибабахом, и валидация должна идти по группам, приложение разбиваться по неймспейсам, а объявление всего и вся через анонимные функции - это откровенная laravel-блевня, но здесь-то и задачи как таковой не стоит.
Обновление
@Bastian, если вы уже в самой задаче бьете ее на два этапа? Валидация одна, этапов два. Хотя объектов валидации будет два, наверное, мне лень было так глубоко лезть