Инструменты пользователя

Инструменты сайта


products:pussy:other:dev_custom_property

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слеваПредыдущая версия
Следующая версия
Предыдущая версия
products:pussy:other:dev_custom_property [2023/12/08 17:07] – [Разработка Свойства без механизма валидации значения] ironmeshproducts:pussy:other:dev_custom_property [2023/12/13 14:54] (текущий) – внешнее изменение 127.0.0.1
Строка 1: Строка 1:
 ====== Разрабатываем класс свойства ====== ====== Разрабатываем класс свойства ======
- 
-FIXME 
  
 В данном уроке я расскажу как разработать собственный класс Свойства. Фреймворк уже содержит некоторое количество [[:products:pussy:api:pyub:types:properties:main|готовых свойств]], но в в определенных случаях этого может быть недостаточно, подробнее о концепции свойств читайте [[:products:pussy:concepts:property|здесь]]. В данном уроке я расскажу как разработать собственный класс Свойства. Фреймворк уже содержит некоторое количество [[:products:pussy:api:pyub:types:properties:main|готовых свойств]], но в в определенных случаях этого может быть недостаточно, подробнее о концепции свойств читайте [[:products:pussy:concepts:property|здесь]].
  
-Итак, перед началом следует упомянуть несколько важных моментов. Значения и параметры должны иметь такие типы, которые могут быть сериализованы с помощью модуля [[https://docs.python.org/3/library/pickle.html|pickle]], чтобы Менеджер мог сохранить их в базе данных, в противном случае это может привести к непредскажуемым результатам, вероятнее всего Менеджер просто не сможет сохранить данные.+Итак, перед началом следует упомянуть несколько важных моментов: значения и параметры Свойств должны иметь такие типы данных, которые могут быть сериализованы с помощью модуля [[https://docs.python.org/3/library/pickle.html|pickle]], чтобы Менеджер мог сохранить их в базе данных, в противном случае это может привести к непредсказуемым результатам, вероятнее всего Менеджер просто не сможет сохранить данные.
  
 <WRAP center round important 60%>\\ <WRAP center round important 60%>\\
Строка 11: Строка 9:
 </WRAP> </WRAP>
  
-Как вам должно быть известно Свойство это компонент, предназначеный для хранения и отображения данных. Свойства делятся на 2 типа: с валидацией значения по заданным параметрам и без валидации, во всех случая нужно переопределить следующие методы:+Как вам должно быть известно Свойство это компонент, предназначеный для хранения и отображения данных. Свойства делятся на 2 типа: с валидацией значения по заданным параметрам и без валидации, во всех случаях нужно переопределить следующие методы:
  
   * [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;property#init|_ _init_ _()]]   * [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;property#init|_ _init_ _()]]
Строка 25: Строка 23:
 Опишу процесс разработки на примере уже существующего свойства [[:products:pussy:api:pyub:types:properties:boolproperty|]], оно очень просто устроено и служит для хранения одного булевого значения. Опишу процесс разработки на примере уже существующего свойства [[:products:pussy:api:pyub:types:properties:boolproperty|]], оно очень просто устроено и служит для хранения одного булевого значения.
  
-Для начала создадим новый py-файл и определить новый класс, унаследованный от [[:products:pussy:api:pyub:types:properties:property|]]. Пришло время переопределить методы, код метода //_ _init()_ _() // приведен ниже+Для начала создадим новый py-файл и определим новый класс, унаследованный от [[:products:pussy:api:pyub:types:properties:property|]]. Затем нужно переопределить необходимые методы, код метода //_ _init_ _() //  приведен ниже 
 <code python> <code python>
  def __init__(self, default_value:bool=False, name="Unnamed", tool_tip=""):  def __init__(self, default_value:bool=False, name="Unnamed", tool_tip=""):
Строка 35: Строка 34:
 </code> </code>
  
-тут все просто, здесь мы задаем начальное значение свойства и устанавливаем его параметры. Значение свойства должно храниться в поле //_value//, если отступить от этого правила, то придется переопределять методы [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#value|value()]] и [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#set_value|set_value()]]. Имена полей параметров должны начинаться с префикса **p_**, отступление от этого правила вынудит переопределять методы [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#get_parameters_dict|get_parameters_dict()]] и [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#set_parameters_from_dict|set_parameters_from_dict()]]. Имя свойства должно храниться в поле //p_name//, в противном случае будет необходимо переопределить метод [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#get_name|get_name()]]. Имена аргументов для метода лучше выбрать из тех, что существуют, а для тех что нет, следует подобрать, которые точно описывают их назначение. Существующие имена аргументов:+тут все просто, здесь мы задаем начальное значение свойства и устанавливаем его параметры. Значение свойства должно храниться в поле //_value//, если отступить от этого правила, то придется переопределять методы [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#value|value()]] и [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#set_value|set_value()]]. Имена полей параметров должны начинаться с префикса **p_**, отступление от этого правила вынудит переопределять методы [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#get_parameters_dict|get_parameters_dict()]] и [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#set_parameters_from_dict|set_parameters_from_dict()]]. Имя свойства должно храниться в поле //p_name//, в противном случае будет необходимо переопределить метод [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#get_name|get_name()]]. Имена аргументов для метода лучше выбрать из тех, что существуют, а для тех что нет, следует подобрать имена, которые точно описывают их назначение. Существующие имена аргументов:
  
   * //default_value //- значение свойства по умолчанию   * //default_value //- значение свойства по умолчанию
Строка 55: Строка 54:
 </code> </code>
  
-В методе //get_input_widget()//  создается экземпляр виджета и сохраняется в поле //_widget_ref//, у виджета устанавливается состояние согласно тому, что установлено в значении; в методе //retranslate()//  производится установка всплывающей подсказки, тут производится поиск перевода в установленных словарях в контексте //properties, //  в этом методе следует производит все установки отображаемых данных, которым требуется перевод, так как пользователь может на лету производить переключение языка интерфейса; в конце метод должен вернуть ссылку на виджет.+В методе //get_input_widget()//  создается экземпляр виджета и сохраняется в поле //_widget_ref//, у виджета устанавливается состояние согласно тому, что установлено в значении свойства; в методе //retranslate()//  производится установка всплывающей подсказки, тут производится поиск перевода в установленных словарях в контексте //properties, //  в этом методе следует производить все установки отображаемых данных, которым требуется перевод, так как пользователь может на лету производить переключение языка интерфейса; в конце метод должен вернуть ссылку на виджет.
  
-Итак, ссылку на виджет мы имеем, теперь, нам нужно обновить это значение, все правильно, значение свойства синхронизируется с виджетом по запросу, а не при изменении, эту работу выполняет метод// extract_widget_data()//, его задача извлечь данные из виджета и записать их внутрь свойства, также он должен уведомить о том, что значение было изменено.+Итак, ссылку на виджет мы имеем, теперь, нам нужно обновить его значение, все правильно, значение свойства синхронизируется с виджетом по запросу, а не при изменении, эту работу выполняет метод// extract_widget_data()//, его задача извлечь данные из виджета и записать их внутрь свойства, также он должен уведомить о том, что значение было изменено.
  
 <code python> <code python>
Строка 72: Строка 71:
 </code> </code>
  
-Для начала определям переменную //has_value_changed //  и присваиваем ей значение **False**, этот флаг будет сигнализировать о том, что значение свойства было изменено; затем проверяем существует ли поле со ссылкой на виджет //_widget_ref//, так сказать на всякий случай; если ссылка пристутствует, то значение виджета извлекается и сравнивается с текущим значением свойства, если они не равны, то значение свойства обновляется, флаг //has_value_changed //  устанавливается как **True**; в конце метод возвращает значение флага //has_value_changed//.+Для начала определям переменную //has_value_changed //  и присваиваем ей значение **False**, этот флаг будет сигнализировать о том, что значение свойства было изменено; затем проверяем существует ли поле со ссылкой на виджет //_widget_ref//, так сказать: "на всякий случай"; если ссылка присутствует, то значение виджета извлекается и сравнивается с текущим значением свойства, если они не равны, то значение свойства обновляется, флаг //has_value_changed //  устанавливается как **True**; в конце метод возвращает значение флага //has_value_changed//.
  
 Итак, вы только что узнали как создавать собственные свойства, согласитесь, это было очень просто, далее мы разберем как создавать свойства с механизмов валидации значения. Итак, вы только что узнали как создавать собственные свойства, согласитесь, это было очень просто, далее мы разберем как создавать свойства с механизмов валидации значения.
Строка 78: Строка 77:
 <WRAP center round important 60%> <WRAP center round important 60%>
  
-Дополнительный раз напомню, что значение свойства должно храниться в поле //_value//, если отступить от этого правила, то придется переопределять методы [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#value|value()]] и [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#set_value|set_value()]]; имена полей параметров должны начинаться с префикса **p_**, отступление от этого правила вынудит переопределять методы [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#get_parameters_dict|get_parameters_dict()]] и [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#set_parameters_from_dict|set_parameters_from_dict()]]; имя свойства должно храниться в поле //p_name//, в противном случае будет необходимо переопределить метод [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#get_name|get_name()]]. </WRAP> +Дополнительный раз напомню, что значение свойства должно храниться в поле //_value//, если отступить от этого правила, то придется переопределять методы [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#value|value()]] и [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#set_value|set_value()]]; имена полей параметров должны начинаться с префикса **p_**, отступление от этого правила вынудит переопределять методы [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#get_parameters_dict|get_parameters_dict()]] и [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#set_parameters_from_dict|set_parameters_from_dict()]]; имя свойства должно храниться в поле //p_name//, в противном случае будет необходимо переопределить метод [[http://wiki.mig-ironmesh.ru/products;pussy;api;pyub;types;properties;abstractproperty#get_name|get_name()]]. </WRAP> 
 ===== Разработка Свойства с механизмом валидации значения ===== ===== Разработка Свойства с механизмом валидации значения =====
  
 Здесь рассмотрим процесс разработки на примере уже существующего свойства [[:products:pussy:api:pyub:types:properties:intproperty|]], которое служит для хранения одного целого числа. Здесь рассмотрим процесс разработки на примере уже существующего свойства [[:products:pussy:api:pyub:types:properties:intproperty|]], которое служит для хранения одного целого числа.
  
-Для начала создадим новый py-файл и определить новый класс, унаследованный от [[:products:pussy:api:pyub:types:properties:propertyvalidated|]], приведу код для данного класса затем опишу каждый метод в отдельности+Для начала создадим новый py-файл и определим новый класс, унаследованный от [[:products:pussy:api:pyub:types:properties:propertyvalidated|]], приведу код для данного класса целиком, затем опишу каждый метод в отдельности
  
 <code python> <code python>
Строка 129: Строка 129:
             elif value> self.p_maximum:             elif value> self.p_maximum:
                 self.__dict__["_value"] = self.p_maximum                 self.__dict__["_value"] = self.p_maximum
 +
  
 </code> </code>
  
-Метод //_ _init_ _()//  как и в прошлом случае делает тоже самое, только обратите внимание на один нюанс: в самом начале вызывается метод //_set_validation()//  и ему передается значение **False**, этот метод создает флаг //_do_validation // с указанным значением, он указывает на то, производить валидацию значения или нет, передав False мы запрещаем свойству производить валидацию, валидацию мы включаем перед созданием поля //_value//, передав методу //_set_validation// () значение **True**, чтобы при установке знгачения свойства проивзести его валидацию.+Метод //_ _init_ _()//  как и в прошлом случае делает тоже самое, только обратите внимание на один нюанс: в самом начале вызывается метод //_set_validation()//  и ему передается значение **False**, этот метод создает флаг //_do_validation //  с указанным значением, он указывает на то, производить валидацию значения или нет, передав **False **  мы запрещаем свойству производить валидацию, валидацию мы включаем перед созданием поля //_value//, передав методу //_set_validation//  () значение **True**, чтобы после установки значения свойства произвести его валидацию.
  
-Механизм валидации устроен очень просто, у класс [[:products:pussy:api:pyub:types:properties:propertyvalidated|]]переопределен магический метод _ _setattr_ _(), которые вызывается каждый раз, когда в коде происходит присвоение полей экземпляру класса, кстати, вот его код+Механизм валидации устроен очень просто, у класса [[:products:pussy:api:pyub:types:properties:propertyvalidated|]] переопределен магический метод //_ _setattr_ _()//, который вызывается каждый раз, когда в коде происходит присвоение полей экземпляру класса, кстати, вот его код
  
 <code python> <code python>
Строка 142: Строка 143:
         if self._do_validation:         if self._do_validation:
             self.validate_value(key)             self.validate_value(key)
 +
  
 </code> </code>
  
-Здесь производится присвоение полю как обычно, затем производится вызов метода //validate_value()//, если флаг //_do_validation//  установлен как **True. ** Напомню, что //_do_validation // устанавливается методом //_set_validation//.+Здесь как обычно производится присвоение полю значения , затем выполняется вызов метода //validate_value()//, если флаг //_do_validation//  установлен как **True. **  Напомню, что //_do_validation //  устанавливается методом //_set_validation()//.
  
-Методы //get_input_widget(),  retranslate() // и// extract_widget_data() // пишутся по тем же правилам, которые были описаны в первом случае.+Методы //get_input_widget(), retranslate() //  и// extract_widget_data() //  пишутся по тем же правилам, которые были описаны в первом случае.
  
-Для свойств данного типа нужно определить важный метод //validate_value()//, который и определяет алгоритм валидации значения свойства. Данный метод принимает //changed_attr // тут содержится имя изменяемого поля; в переменной сheck_list содержится список полей при изменении которых будет производиться валидация, в данном случае это само значение и максимальноеминимальное значения, можно обойтись и без данного списка, только валидация будет производится даже в тех случаях, когда это не требуется; далее производится проверка на вхождение изменяемого атрибута в чеклист, если он входит или отсутствует, то выполняется алгоритм валидации, обратите внимание, что значение следует проивзодить следующим образом //self.__dict__["_value"] = < значение>//, а не так //self._value = < значение>//, чтобы программа не вошла в бесконечный цикл.+Для свойств данного типа нужно определить важный метод //validate_value()//, который и определяет алгоритм валидации значения свойства. Данный метод принимает //changed_attr//, в нем содержится строка с именем изменяемого поля; в переменной //сheck_list//  содержится список полейпри изменении которых будет производиться валидация, в данном случае это само значение свойства, максимальное и минимальное значения, можно обойтись и без данного списка, только валидация будет производиться даже в тех случаях, когда это не требуется; далее производится проверка на вхождение изменяемого атрибута в чеклист, если он входит или отсутствует, то выполняется алгоритм валидации, обратите внимание, что присвоение значения следует производить следующим образом//self._ _dict_ _["_value"] = < значение>//, а не так//self._value = < значение>//, чтобы программа не вошла в бесконечный цикл.
  
-Ну, вот и все, урок по разработке собственного класса свойства подошел к концу, как вы могли убедиться это очень простой процесскоторый не займет много времени и сил, но перед использованием не забывайте тестировать свой код. Если что-то не понятно, то можно задать вопрос в [[http://discord.gg/JD5yKPrKCk|Discord]]+Ну, вот и все, урок по разработке собственного класса свойства подошел к концу, как вы могли убедиться это очень простой процесскоторый не займет много времени и сил, но перед использованием не забывайте тестировать свой код. Если что-то не понятно, то можно задать вопрос в [[http://discord.gg/JD5yKPrKCk|Discord]].
  
  
products/pussy/other/dev_custom_property.1702044468.txt.gz · Последнее изменение: (внешнее изменение)