自定义model
- 格式:wps
- 大小:801.50 KB
- 文档页数:23
djangoModel层常⽤验证器及⾃定义验证器详解在Django中,对数据进⾏校验有两种⽅式:⼀种是通过Form校验,⼀种是通过Model校验。
在此,我对Model中的校验⽅法做下记录。
⽰例之前补充以下⼏点:1、Django数据校验⽅式分为以下三步:Model.clean_fields() 验证字段基本规则⽐如长度格式等;Model.clean() 可⾃定义验证条件和报错信息;Model.validate_unique() 为验证添加的唯⼀性约束。
2、此三步验证通过调⽤full_claen(exclude=None, validate_unique=True)来依次执⾏。
exclude:可以⽤来指定不需要执⾏校验的field。
ModelForm也利⽤这个参数来将field排除。
validate_unique:⽤来指定是否需要执⾏Model.validate_unique()。
3、⽽full_clean()⼜是通过调⽤is_valid()⽅法来执⾏。
4、save()执⾏的时候是不会⾃动调⽤full_clean()来进⾏校验的。
校验应该在save()执⾏之前完成,你可以先在form进⾏校验,也可以在model中进⾏校验。
但是,你必须确保通过这两个校验之后的数据是绝对没有问题的“⼲净”数据,然后再调⽤save()⽅法将数据存储⼊库。
5、校验中的错误处理我们使⽤ValidationError来在Model.clean中抛出错误,这个错误信息将会存储在以NON_FIELD_ERRORS为key的字典中。
这个key是⽤来存储对于整个model中的错误信息的。
如何获取校验的错误信息:from django.core.exceptions import ValidationError, NON_FIELD_ERRORStry:article.full_clean()except ValidationError as e:non_field_errors = e.message_dict[NON_FIELD_ERRORS]如何指定对于某个特定的field的校验错误信息:class Article(models.Model):...def clean(self):if self.status == 'draft' and self.pub_date is not None:# raise ValidationError({'pub_date': _('Draft entries may not have a publication date.')})raise ValidationError({'pub_date': 'Draft entries may not have a publication date.'})...如何指定多个field的校验错误信息:class Article(models.Model):...def clean(self):if self.status == 'draft' and self.pub_date is not None:raise ValidationError({'pub_date': 'Draft entries may not have a publication date.','creator': 'Creator can't be null'})...如何指定全局性校验错误信息:class Article(models.Model):...def clean(self):if self.status == 'draft' and self.pub_date is not None:raise ValidationError('Draft entries may not have a publication date.')...进⼊正题:⼀、如何使⽤验证器:在验证某个字段的时候,在模型或者⾃定义form表单中传递⼀个 validators 参数⽤来指定验证器,进⼀步对数据进⾏过滤。
最近在研究 MVC 模型绑定,发现 DefaultModelBinder 有一个弊端,就是无法实现对浏览器请求参数的自定义,最初的想法是想为实体模型的属性设置特性(Attribute),然后通过取得设置的特性值对属性进行赋值,研究了好久MVC 源码之后发现可以通过重写 DefaultModelBinder 的 BindProperty 方法可以达到预期的目的。
MVC 中有一个自定义模型绑定特性 CustomModelBinderAttribute,打算通过重写 CustomModelBinderAttribute 来对实体属性进行出来,实现如下:
但是由于 CustomModelBinderAttribute 不支持对属性设置特性,所以只好继承 Attribute 类重新写一个特性,代码如下:
这样就可以在实体模型的属性上设置别名了。
自定义模型使用教程:在织梦系统中有内容模型这个概念,不同内容模型可以用来构建不同内容形式的站点,在系统中自带了以下几种模型:普通文章、图集、软件、商品、分类信息、专题。
通过系统自带的模型,我们可以用来构建不同类型的站点,例如:使用图集可以做一个图片站,用软件模型构建一个软件下载站点。
当然以上随系统附带的模型被称为系统模型,用户可以自己定义一些模型,比如图书、音乐专辑等,自定义了这些模型才可以构建更多内容形式的站点,本篇将讲述如何使用系统的自定义模型管理功能来实现内容模型的构建。
我们首先登录系统后台,点击[核心]-[内容模型管理],进入内容模型管理界面,如下图所示:这里我们介绍几个相关参数的概念:•ID号用于区分模型的唯一ID,一般常规模型的ID都是大于0的,比如普通文章、软件等,如果使用了单表模型,ID一般需要小于-1,例如这里的分类信息模型;•频道名称用于识别频道类型的标识;•识别id系统用于识别的id,这个关系到模板方面;•附加表系统内容附加表项;•模型类型分为系统类型和自动类型,系统类型为固化在系统中的内容模型,自动类型为用户可创建的内容模型类型;接下来我们开始介绍如何使用自定义模型管理来创建一个自己的模型,并且用于建设不同内容类型的网站中去。
这里我们介绍一些周边的内容,几个要用到的概念:•字段在数据库中,表的列称为字段,织梦系统也是如此,但更恰当的说法,存储某个内容信息单元,称为字段,例如标题、来源、作者等都是一个字段;•内容系统主表程序将一些公用字段存储在系统主表dede_archives,例如:标题、关键词、缩略图等,主表具体字段可以查询织梦帮助中心()的有关二次开发手册数据表部分的内容;•附加表不同内容模型对应不同的附加表,通常以dede_addon[识别ID]命名,附加表中存放的都是详细内容的相关字段(非公用),例如:文章内容(dede_addonarticle)、软件类型(dede_addonsoft)、图片集合(dede_addonimage)等;•单表独立模型存储时候不用到“主表+附加表”的结构形式,直接使用单个数据表进行存储内容数据,这样脱离主从表,减少主表数据服在开销,可以从很大程度上解决数据负载问题;明白了以上几个概念我们可以来学习如何来自己创建一个内容模型了。
definemodel 例子-概述说明以及解释1.引言1.1 概述引言是文章中的开篇部分,它旨在介绍文章的主题和背景,引起读者的兴趣并提出文章的目的和重要性。
在本篇文章中,我们将讨论定义模型的概念,并探讨其在实际应用中的作用和意义。
通过对模型的概念、应用范围和特点进行深入分析,我们希望能为读者提供对定义模型的全面理解,进而促进其在实践中的应用和发展。
通过本文的阐述,我们也希望能够激发更多的研究和讨论,为定义模型的研究和应用带来更多的启发和创新。
1.2文章结构1.2 文章结构本文主要包括以下内容:- 引言部分:首先介绍了定义模型的概念,并说明了文章的目的和结构。
- 正文部分:详细介绍了定义模型的概念、应用范围和特点,帮助读者全面了解这一概念。
- 结论部分:总结了文章的主要内容,并展望了定义模型的未来发展方向。
- 结束语:对全文进行了总结,强调了定义模型在实际应用中的重要性。
通过上述结构,读者可以系统地了解定义模型的定义、应用和特点,为进一步研究和应用提供了基础和指导。
1.3 目的:本文的目的主要在于介绍和探讨define model的概念,帮助读者深入了解模型定义的重要性和应用范围。
通过对模型的特点进行分析,可以帮助读者更好地理解define model在实际应用中的价值和作用。
同时,本文还旨在引导读者对模型进行深入思考和研究,探索更多有关define model的可能性,为相关领域的研究和实践提供一定的参考和借鉴。
希望通过本文的阐述,能够为读者提供一些启发和思考,促进对define model 概念的进一步理解和应用。
2.正文2.1 定义模型的概念在科学研究和实践中,模型是对真实世界的简化和抽象。
它是一种用来描述、解释和预测现实世界的工具,可以帮助人们更好地理解复杂的现象和系统。
模型可以是数学模型、统计模型、图形模型等多种形式,其核心作用在于提供一种简单、可控的方式来研究和分析现实世界中的问题。
drf modelviewset自定义方法在Django REST Framework (DRF)的ModelViewSet中自定义方法有两种方式:1. 通过装饰器定义自定义action方法;2. 重写ModelViewSet类。
下面是两种方式的具体实现方法:1. 通过装饰器定义自定义action方法:```pythonfrom rest_framework.decorators import actionfrom rest_framework.response import Responseclass YourModelViewSet(viewsets.ModelViewSet):# ... 自定义ModelViewSet的其他设置 ...@action(detail=True, methods=['POST'])def your_custom_action(self, request, pk=None):# 自定义逻辑# 可以使用self.get_object()获取当前对象# 可以使用self.get_queryset()获取当前queryset# 返回自定义结果return Response('Your custom action has been executed.')```在上面的例子中,使用了`@action`装饰器定义了一个名为`your_custom_action`的自定义action方法。
`detail=True`表示该方法是针对单个对象的,`methods=['POST']`表示该方法只能通过POST方法访问。
2. 重写ModelViewSet类:```pythonfrom rest_framework import viewsetsfrom rest_framework.response import Responseclass YourModelViewSet(viewsets.ModelViewSet):# ... 自定义ModelViewSet的其他设置 ...def your_custom_action(self, request, pk=None):# 自定义逻辑# 可以使用self.get_object()获取当前对象# 可以使用self.get_queryset()获取当前queryset# 返回自定义结果return Response('Your custom action has been executed.')def dispatch(self, request, *args, **kwargs):# 如果请求的方法为your_custom_action,则调用your_custom_action方法if request.method == 'POST':return self.your_custom_action(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)```在上面的例子中,重写了`dispatch`方法,如果请求的方法为`your_custom_action`,则调用`your_custom_action`方法。
drf modelviewset 自定义方法DRF ModelViewSet 自定义方法概述•ModelViewSet是Django Rest Framework(DRF)中最常用的视图集之一,它提供了一组默认的CRUD(创建、读取、更新、删除)方法。
•然而,我们有时需要根据特定的需求自定义一些方法。
在本文中,我将详细介绍如何使用DRF ModelViewSet来自定义方法。
定义ModelViewSet首先,我们需要定义一个ModelViewSet。
在Django的视图集中,通常需要继承ModelViewSet类。
例如:from rest_ import ModelViewSetclass MyModelViewSet(ModelViewSet):queryset = ()serializer_class = MyModelSerializer添加自定义方法在ModelViewSet中,我们可以通过添加自定义的方法来实现一些特定的功能。
以下是一些常用的方法:1. list方法•list方法用于获取所有模型对象的列表。
•可以在ModelViewSet中直接定义list方法:def list(self, request, *args, **kwargs):# 自定义代码return super().list(request, *args, **kwargs)2. create方法•create方法用于创建一个新的模型对象。
•可以在ModelViewSet中直接定义create方法:def create(self, request, *args, **kwargs):# 自定义代码return super().create(request, *args, **kwargs) 3. retrieve方法•retrieve方法用于获取单个模型对象的详细信息。
•可以在ModelViewSet中直接定义retrieve方法:def retrieve(self, request, *args, **kwargs):# 自定义代码return super().retrieve(request, *args, **kwargs)4. update方法•update方法用于更新一个模型对象的信息。
vue3 v-model用法Vue3是Vue.js的下一个主要版本,它引入了很多新的特性和语法糖,使开发者可以更轻松地构建出功能强大的应用程序。
其中一个非常重要且常用的特性就是v-model指令。
v-model指令在Vue.js中用于实现双向数据绑定,它能够将数据模型和表单元素之间建立关联,使得数据的改变可以实时地反映在视图上,并且用户在视图上的更改也可以同步到数据模型中。
在Vue3中,v-model指令的用法相较于Vue2有一些变化。
1. 基本用法:在Vue3中,v-model指令的基本用法和Vue2保持一致。
它可以直接用于表单元素,如输入框、选择器等。
例如,在一个输入框中使用v-model指令可以很方便地实现双向数据绑定:```<template><input v-model="message" /></template><script>export default {data() {return {message: ""};}};</script>```在上述代码中,当用户在输入框中输入文本时,`message`的值将自动更新。
如果我们修改`message`的值,输入框中的文本也会相应地更新。
2. 自定义组件中的v-model:在Vue3中,v-model指令也可以用于自定义组件中,使得开发者可以轻松地创建自己的可重用组件。
不同于Vue2,Vue3对于自定义组件中的v-model指令的用法做了一些改变。
在Vue3中,要在一个自定义组件中使用v-model指令,需要先在组件选项中声明`modelValue`属性,并在`emits`选项中声明一个名为`update:modelValue`的事件。
下面是一个示例:```<template><custom-input v-model="message" /></template><script>import CustomInput from "./CustomInput.vue";export default {components: {CustomInput},data() {return {message: ""};}};</script>```在上述代码中,我们在父组件中使用了一个自定义组件`CustomInput`,并将`message`通过v-model指令与子组件中的`modelValue`建立了关联。
laravel model的用法Laravel是一款流行的PHP框架,其提供了一种称为Model-View-Controller (MVC)的架构模式来构建Web应用程序。
在Laravel中,Model被用于处理与数据库进行交互的操作,例如数据的创建、读取、更新和删除(CRUD操作)。
使用Laravel Model可以轻松地定义和管理数据库表,而无需直接编写SQL语句。
以下是Laravel Model的几个常用用法:1. 定义Model:在Laravel中,可以使用Artisan命令行工具快速创建一个Model。
在终端中运行以下命令:```php artisan make:model Blog```这将生成一个名为"Blog.php"的Model文件,其中包含了一些基本的设置和方法。
2. 进行数据库操作:在Model中,可以定义与数据库表相关的字段、关系和方法。
通过定义这些属性和方法,Laravel将自动处理与数据库的交互。
例如,在Blog模型中,可以定义一个与"blogs"表相关的字段和方法,如下所示:```phpnamespace App\Models;use Illuminate\Database\Eloquent\Model;class Blog extends Model{protected $table = 'blogs';protected $fillable = ['title', 'content'];public function comments(){return $this->hasMany(Comment::class);}}```在上述示例中,$table属性指定了Model对应的数据库表名为"blogs",$fillable 属性指定了可以批量赋值的字段。
vue v-model 组合写法在Vue中,v-model指令通常用于在表单输入元素上创建双向数据绑定。
然而,有时候我们需要对v-model进行一些自定义的操作,这就需要使用v-model的组合写法。
组合写法实际上是v-model的语法糖,它允许我们在自定义组件上使用v-model。
在自定义组件中,我们可以通过props接收value属性,并在需要时触发input事件来更新value属性。
以下是一个简单的例子:javascript.// 子组件 ChildComponent.vue.<template>。
<input :value="innerValue"@input="updateValue($event.target.value)">。
</template>。
<script>。
export default {。
props: ['value'],。
data() {。
return {。
innerValue: this.value. };},。
methods: {。
updateValue(value) {。
this.innerValue = value;this.$emit('input', value);}。
},。
watch: {。
value(newVal) {。
this.innerValue = newVal;}。
}。
};</script>。
在这个例子中,我们创建了一个名为ChildComponent的子组件,它接收一个名为value的prop,并在内部维护一个名为innerValue的数据。
在input事件触发时,我们更新innerValue并通过$emit方法触发input事件,将新的值传递给父组件。
同时,我们也使用了一个watcher来监听value的变化,并在变化时更新innerValue。
简述vue3 v-model的原理Vue3 的v-model是一个特殊的指令,它可以让 Model 层与 View 层互相绑定,一个变动,另一个也会变动。
V-model有两个作用:一是读取用户在表单界面输入,二是把数据保存进 Model。
Vue3将v-model由指令分离成render函数和value事件,render函数将Model里的值渲染到DOM中,value 事件将用户在表单界面的输入,传回Model中更新数据。
V-model 可以用在 input, select, 和 textarea 上,同时它也允许你在任何地方声明一个组件,只要它接受 v-model prop 和 emitting input 事件即可。
实际上,v-model 编译成两个不同函数:一个用于读取 Model 层的值,另一个用于将 View 层的输入写回 Model 层,以更新数据。
V-model 在 Vue3.0 是通过解耦 input 事件和 change 事件实现的。
它的实现方式很像 v-bind ,区别在于,当更新 Model 层的数据时,v-model 会去自动去执行更新DOM 的操作,而 v-bind 只会更新 Model 层的数据,然后执行更新 DOM的操作是需要用户手动去执行的。
V-model 也可以被用在表单元素上,从而使表单自动获得双向绑定效果。
它可以用来处理用户输入,并在保存数据时调用读取值的回调函数。
而且,V-model配合双向绑定,可以节约用户多次读写 HTML DOM 中的表单内容,从而大大增加了效率。
Vue3同时在 v-model 里实现了自定义模型,它可以在 Model 层和 View 层之间自动将 model 数据转换成 View 层所需的数据,从而使 Model 层和 View 层更加容易理解,灵活控制。
总的来说,Vue3的v-model是一种强大的双向绑定工具,可以让 Model 层与 View 层互相绑定,及时更新model的值和view的值,提高编码效率,并且允许用户自定义model 与 view 间的转换,使它们能更清楚的知道彼此的变化。
自定义modelQt的model-view架构中的几个关键的概念。
一个model中的每个数据元素都有一个model索引。
这个索引指明这个数据位于model的位置,比如行、列等。
这就是前面我们曾经说到过的QModelIndex。
每个数据元素还要有一组属性值,称为角色(roles)。
这个属性值并不是数据的内容,而是它的属性,比如说,这个数据是用来展示数据的,还是用于显示列头的?因此,这组属性值实际上是Qt的一个enum定义的,比较常见的有Qt::DisplayRole和Qt::EditRole,另外还有Qt::ToolTipRole, Qt::StatusTipRole, 和Qt::WhatsThisRole等。
并且,还有一些属性是用来描述基本的展现属性的,比如Qt::FontRole,Qt::TextAlignmentRole, Qt::TextColorRole, Qt::BackgroundColorRole等list model定位其中的一个数据只需要有一个行号通过QModelIndex::row()函数进行访问;对于table model而言,这种定位需要有两个值:行号和列号,这两个值可以通过QModelIndex::row()和QModelIndex::column()这两个函数访问到。
另外,对于tree model而言,用于定位的可以是这个元素的父节点。
不仅仅是tree model,并且list model和table model的元素也都有自己的父节点,只不过对于list model和table model,它们元素的父节点都是相同的,并且指向一个非法的QModelIndex所有的model,这个父节点都可以通过QModelIndex::parent()函数访问到。
这就是说,每个model的项都有自己的角色数据(属性),0个、1个或多个子节点。
既然每个元素都有自己的子元素,那么它们就可以通过递归的算法进行遍历,就像数据结构中树的遍历一样,关于父节点的描述;下面我们通过一个简单的例子来看看如何实现自定义model。
首先描述一下需求。
这里我们要实现的是一个类似于货币汇率表的table这是一个很简单的实现,直接用QTableWidget不就可以了吗?的确,如果直接使用QTableWidget确实很方便。
但是,试想一个包含了 100种货币的汇率表。
显然,这是一个二维表,并且,对于每一种货币,都需要给出相对于其他100种货币的汇率(在这里,我们把自己对自己的汇率也包含在内,只不过这个汇率永远是1.0000)。
那么,这张表要有100 x 100 = 10000个数据项。
现在要求我们减少存储空间。
于是我们想,如果我们的数据不是显示的数据,而是这种货币相对于美元的汇率,那么,其他货币的汇率都可以根据这个汇率计算出来了。
比如说,我存储的是人民币相对美元的汇率,日元相对美元的汇率,那么人民币相对日元的汇率只要作一下比就可以得到了。
我没有必要存储10000个数据项,只要存储100个就够了。
于是,我们要自己实现一个model(就是更优化的model)。
CurrencyModel就是这样一个model。
它底层的数据使用一个QMap<QString, double>类型的数据,作为key的QString是货币名字,作为value的double是这种货币对美元的汇率。
然后我们来看代码:class CurrencyModel : public QAbstractTableModel{public:CurrencyModel(QObject *parent = 0);void setCurrencyMap(const QMap<QString, double> &map);int rowCount(const QModelIndex &parent) const;int columnCount(const QModelIndex &parent)const;QVariant data(const QModelIndex &index, int role) const;QVariant headerData(int section, Qt::Orientation orientation, int role) const;private:QString currencyAt(int offset) const;QMap<QString, double> currencyMap;};CurrencyModel::CurrencyModel(QObject *parent): QAbstractTableModel(parent){}int CurrencyModel::rowCount(const QModelIndex & parent) const{return currencyMap.count();}int CurrencyModel::columnCount(const QModelIndex & parent) const{return currencyMap.count();}QVariant CurrencyModel::data(const QModelIndex &index, int role) const{if(!index.isValid())return QVariant();if(role == Qt::TextAlignmentRole) {return int(Qt::AlignRight | Qt::AlignVCenter);} else if(role == Qt::DisplayRole) {QString rowCurrency = currencyAt(index.row());QString columnCurrency = currencyAt(index.column());if(currencyMap.value(rowCurrency) == 0.0)return"####";double amount = currencyMap.value(columnCurrency) / currencyM ap.value(rowCurrency);return QString("%1").arg(amount, 0, 'f', 4);}return QVariant();}QVariant CurrencyModel::headerData(int section, Qt::Orientation orientation, int role) const{if(role != Qt::DisplayRole)return QVariant();return currencyAt(section);}void CurrencyModel::setCurrencyMap(const QMap<QString, double> &map) {currencyMap = map;reset();}QString CurrencyModel::currencyAt(int offset) const{return(currencyMap.begin() + offset).key();}we选择了继承QAbstractTableModel。
虽然是自定义model,但各种model之间也会有很多共性。
Qt提供了一系列的抽象类供我们继承,以便让我们只需要覆盖掉几个函数就可以轻松地定义出我们自己的model。
Qt提供QAbstractListModel和 QAbstractTableModel两类,前者是一维数据model,后者是二维数据model。
如果你的数据很复杂,那么可以直接继承QAbstractItemModel。
这三个类之间的关系可以表述如下:构造函数中没有添加任何代码,只要调用父类的构造函数就可以然后我们重写了rowCount()和columnCount()这两个函数,用于返回model的行数和列数。
由于我们使用一维的map记录数据,因此这里的行和列都是map的大小。
然后我们看最复杂的data()函数。
QVariant CurrencyModel::data(const QModelIndex &index, int role) const{if (!index.isValid()) //valid 有效的 ,正当的return QVariant();if (role == Qt::TextAlignmentRole) {return int(Qt::AlignRight | Qt::AlignVCenter);} else if (role == Qt::DisplayRole) {QString rowCurrency = currencyAt(index.row());QString columnCurrency =currencyAt(index.column());if (currencyMap.value(rowCurrency) == 0.0)return"####";double amount = currencyMap.value(columnCurrency) / currencyMap.value(rowCurrency);return QString("%1").arg(amount, 0, 'f', 4);}return QVariant();}data()函数返回单元格的数据。
它有两个参数:第一个是QModelIndex,也就是单元格的位置;第二个是role,也就是这个数据的角色。
这个函数的返回值是QVariant。
至此,我们还是第一次见到这个类型。
这个类型相当于是Java里面的Object,它把绝大多数Qt提供的数据类型都封装起来,起到一个数据类型“擦除”的作用。
比如我们的table单元格可以是string,也可以是int,也可以是一个颜色值,那么这么多类型怎么返回呢?于是,Qt提供了这个QVariant类型,你可以把这很多类型都存放进去,到需要使用的时候使用一系列的to函数取出来即可。
比如你把int包装成一个QVariant,使用的时候要用QVariant::toInt()重新取出来。
这里需要注意的是,QVariant类型的放入和取出必须是相对应的,你放入一个int就必须按int取出,不能用toString(), Qt 不会帮你自动转换。