Python学习笔记_进阶篇(三)_django知识(二)
本章内容
- Django model
Model 基础配置
django默认支持sqlite,mysql, oracle,postgresql数据库。
<1> sqlite
django默认使用sqlite的数据库,默认自带sqlite的数据库驱动
引擎名称:django.db.backends.sqlite3
<2>mysql
引擎名称:django.db.backends.mysql
1、配置文件中sqlite
DATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': os.path.join(BASE_DIR, 'db.sqlite3'),}
}
2、配置文件中mysql
DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME':'数据库名','USER': 'root','PASSWORD': 'xxx','HOST': '','PORT': '',}
}
注:由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
如下设置放置的与project同名的配置的 init.py文件中
import pymysql
pymysql.install_as_MySQLdb()
Model 创建表结构
创建的时候必须放置models文件中,其他文件中均不可创建
一、基本结构
from django.db import models
class Content(models.Model):title = models.CharField(max_length=150)body = models.TextField()timestamp = models.DateTimeField()
Contentt里用了CharField,TextField, TextField域。难道就只有这三种,不可能!
如下,我列出了其它的Field,并表明了它们的继承关系:
Field
|--AutoField
|--BooleanField
|--CharField
| |--EmailField
| |--SlugField
| `--URLField
|--DateField
| `--DateTimeField
|--DecimalField
|--FilePathField
|--FloatField
|--IntegerField
| |--BigIntegerField
| |--PositiveIntegerField
| `--PositiveSmallIntegerField
|--IPAddressField
|--GenericIPAddressField
|--NullBooleanField
|--TextField
|--TimeField
`--BinaryField
字段注释
1、models.AutoField 自增列 = int(11)如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField 字符串字段必须 max_length 参数
3、models.BooleanField 布尔类型=tinyint(1)不能为空,Blank=True
4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar继承CharField,所以必须 max_lenght 参数
5、models.DateField 日期类型 date对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
6、models.DateTimeField 日期类型 datetime同DateField的参数
7、models.Decimal 十进制小数类型 = decimal必须指定整数位max_digits和小数位decimal_places
8、models.EmailField 字符串类型(正则表达式邮箱) =varchar对字符串进行正则表达式
9、models.FloatField 浮点类型 = double
10、models.IntegerField 整形
11、models.BigIntegerField 长整形integer_field_ranges = {'SmallIntegerField': (-32768, 32767),'IntegerField': (-2147483648, 2147483647),'BigIntegerField': (-9223372036854775808, 9223372036854775807),'PositiveSmallIntegerField': (0, 32767),'PositiveIntegerField': (0, 2147483647),}
12、models.IPAddressField 字符串类型(ip4正则表达式)
13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的)参数protocol可以是:both、ipv4、ipv6验证时,会根据设置报错
14、models.NullBooleanField 允许为空的布尔类型
15、models.PositiveIntegerFiel 正Integer
16、models.PositiveSmallIntegerField 正smallInteger
17、models.SlugField 减号、下划线、字母、数字
18、models.SmallIntegerField 数字数据库中的字段有:tinyint、smallint、int、bigint
19、models.TextField 字符串=longtext
20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField 字符串,地址正则表达式
22、models.BinaryField 二进制
23、models.ImageField 图片
24、models.FilePathField 文件
Field类在构造的时候可以指定以下参数:
1、null=True数据库中字段是否可以为空
2、blank=Truedjango的 Admin 中添加数据时是否可允许空值
3、primary_key = False主键,对AutoField设置主键后,就会代替原来的自增 id 列
4、auto_now 和 auto_now_addauto_now 自动创建---无论添加或修改,都是当前操作的时间auto_now_add 自动创建---永远是创建时的时间
5、choices
GENDER_CHOICE = ((u'M', u'Male'),(u'F', u'Female'),)
gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
6、max_length
7、default 默认值
8、verbose_name Admin中字段的显示名称
9、name|db_column 数据库中的字段名称
10、unique=True 不允许重复
11、db_index = True 数据库索引
12、editable=True 在Admin里是否可编辑
13、error_messages=None 错误提示
14、auto_created=False 自动创建
15、help_text 在Admin中提示帮助信息
16、validators=[]
17、upload-to
二、连表结构
- 一对多:models.ForeignKey(其他表)
- 多对多:models.ManyToManyField(其他表)
- 一对一:models.OneToOneField(其他表)
应用场景:
1、一对一
当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)
例:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。
2、多对多
在某表中创建一行数据是,有一个可以多选的下拉框
例:创建用户信息,需要为用户指定多个爱好
3、一对一
在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了
例:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据
Model 操作
一、基本操作
1、增:
# 方式一
models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs# 方式二
obj = models.Tb1(c1='xx', c2='oo')
obj.save()
2、删
models.Tb1.objects.filter(name= 'seven').delete() # 删除指定条件的数据
3、改
# 方式一
models.Tb1.objects.filter(name='seven').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs# 方式二
obj = models.Tb1.objects.get(id=1)
obj.c1 = '111'
obj.save() # 修改单条数据
4、查
models.Tb1.objects.get(id=123) # 获取单条数据,不存在则报错(不建议)
models.Tb1.objects.all() # 获取全部
models.Tb1.objects.filter(name='seven') # 获取指定条件的数据
二、进阶操作
利用双下划线将字段和对应的操作连接起来
# 获取个数## models.Tb1.objects.filter(name='seven').count()# 大于,小于## models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值# models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值# models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值# in## models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据# models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in# contains## models.Tb1.objects.filter(name__contains="ven")# models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感# models.Tb1.objects.exclude(name__icontains="ven")# range## models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and# 其他类似## startswith,istartswith, endswith, iendswith,# order by## models.Tb1.objects.filter(name='seven').order_by('id') # asc# models.Tb1.objects.filter(name='seven').order_by('-id') # desc# limit 、offset## models.Tb1.objects.all()[10:20]# group byfrom django.db.models import Count, Min, Max, Sum# models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))# SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
Model 操作案例
一、一对多案例
1、表结构如下:
from django.db import modelsclass Usertype(models.Model):uid = models.AutoField(primary_key=True)caption = models.CharField(max_length=32)class Userinfo(models.Model):user = models.CharField(max_length=32)email = models.EmailField(max_length=32)pwd = models.CharField(max_length=32)user_type = models.ForeignKey('Usertype')
打开终端进入project目录下输入命令生成表结构:
python3 manage.py makemigrations
python3 manage.py migrate
2、创建数据
def index(request):# 三种创建数据方法obj = models.Usertype(caption ='管理员' )obj.save()models.Usertype.objects.create(caption='普通用户')obj = {'caption':'Guest'}models.Usertype.objects.create(**obj)# 建议使用这一种方法userinfo_dict = {'user':'张岩林','email':'123@qq.com','pwd':'123','user_type_id':1,}userinfo_dicts = {'user':'aylin','email':'124@qq.com','pwd':'1333','user_type':models.Usertype.objects.get(uid=3),}models.Userinfo.objects.create(**userinfo_dict)models.Userinfo.objects.create(**userinfo_dicts)return HttpResponse('OK')
3、单表查询
def index(request):# 单表查询,查询结果是queryset对象ret = models.Usertype.objects.all()print(ret) # 结果<QuerySet [<Usertype: Usertype object>, <Usertype: Usertype object>, <Usertype: Usertype object>]>for item in ret:print(item.caption) # 取值管理员,普通用户,guest# 单独只取一列 vlauesret = models.Usertype.objects.all().values('caption')print(ret)for i in ret:print(i,type(i)) # {'caption': '管理员'} <class 'dict'># 可以通过变量取到关联表的对象后面加入.caption取另一个表的内容ret = models.Userinfo.objects.all()print(ret,type(ret))for item in ret:print(item.user,item.user_type.caption) # item.user_type取到的是usertype的对象,所以可以取captionreturn HttpResponse('OK')
4、连表正向查找(双下划线)
def index(request):# 连表查询之双下划线ret = models.Userinfo.objects.all().values('user','user_type__caption')print(ret)# 过滤所有用户类型是管理员的用户(连表查询)ret = models.Userinfo.objects.filter(user_type__caption="管理员").values('user', 'user_type__caption')print(ret)return HttpResponse('OK')
5、连表反向查找(双下划线)
def index(request):# 过滤取出第一个是管理员的哪一行数据obj = models.Usertype.objects.filter(caption='管理员').first()print(obj.uid)print(obj.caption)print(obj.userinfo_set.all())obj = models.Usertype.objects.filter(userinfo__user='张岩林').values('userinfo__user')print(obj)return HttpResponse('OK')
二、多对多操作
1、表结构如下:
# 1、传统多对多创建表
class HostToGroup(models.Model):hgid = models.AutoField(primary_key=True)host_id = models.ForeignKey('Host')group_id = models.ForeignKey('Group')class Host(models.Model):hid = models.AutoField(primary_key=True)hostname = models.CharField(max_length=32)ip = models.CharField(max_length=32)class Group(models.Model):gid = models.AutoField(primary_key=True)name = models.CharField(max_length=16)# 2、django给创建第三章关系表,同时可以通过group表里的h2g来给第三张表进行操作class Host(models.Model):hid = models.AutoField(primary_key=True)hostname = models.CharField(max_length=32)ip = models.CharField(max_length=32)# h2g = models.ManyToManyField('Group')
class Group(models.Model):gid = models.AutoField(primary_key=True)name = models.CharField(max_length=16)h2g = models.ManyToManyField('Host')# 3、自己写第三张表的时候,many要加参数class Host(models.Model):hid = models.AutoField(primary_key=True)hostname = models.CharField(max_length=32)ip = models.CharField(max_length=32)# h2g = models.ManyToManyField('Group')
class Group(models.Model):gid = models.AutoField(primary_key=True)name = models.CharField(max_length=16)h2g = models.ManyToManyField('Host',through="HostToGroup") # 重点在这class HostToGroup(models.Model):hgid = models.AutoField(primary_key=True)host_id = models.ForeignKey('Host')group_id = models.ForeignKey('Group')status = models.IntegerField()class Meta:# index_together = ("host_id",'goup_id')unique_together = [('host_id', 'group_id'),]
本次操作以第二种表结构操作,第一种方式传统的操作方式和一对多操作一样,第二三种主要是通关表结构中many来操作表
2、创建数据
def index(request):models.Host.objects.create(hostname='c1', ip='1.1.1.1')models.Host.objects.create(hostname='c2', ip='1.1.1.2')models.Host.objects.create(hostname='c3', ip='1.1.1.3')models.Host.objects.create(hostname='c4', ip='1.1.1.4')models.Host.objects.create(hostname='c5', ip='1.1.1.5')models.Group.objects.create(name='财务部')models.Group.objects.create(name='人事部')models.Group.objects.create(name='公关部')models.Group.objects.create(name='技术部')models.Group.objects.create(name='运营部')models.Group.objects.create(name='销售部')models.Group.objects.create(name='客服部')return HttpResponse('OK')
3、正向添加数据
obj = models.Group.objects.get(gid=1 )obj.h2g.add(*models.Host.objects.all())print(obj.h2g.all())# <QuerySet [<Host: Host object>, <Host: Host object>, <Host: Host object>, <Host: Host object>, <Host: Host object>]>
4、反向添加数据(_set)
# 将一台机器,分配给多个组 # 方法一 只能一个一个添加host = models.Host.objects.get(hid=1)group = models.Group.objects.get(gid=4)group.h2g.add(host)# 方法二 添加多条h = models.Host.objects.get(hid=4)h.group_set.add(*models.Group.objects.filter(gid__gt=3))# 方法三h =models.Host.objects.get(hid=2)ret = h.group_set.set(models.Group.objects.filter(gid__gt=3))print(ret,type(ret))
5、删除
# 删除语句h = models.Host.objects.get(hid=2)h.group_set.remove(*models.Group.objects.filter(gid__gt=3))# 危险删除方法,慎用,会把分组表里的分组也会给删掉h.group_set.all().delete()
6、补充
# 补充,add添加可以添加数字h = models.Host.objects.get(hid=1)h.group_set.add(1)h.group_set.add(models.Group.objects.get(gid=1))h.group_set.add(*[2,3])h.group_set.add(*models.Group.objects.filter(gid__gt=1))# 两个表都添加数据h = models.Host.objects.get(hid=2)h.group_set.get_or_create(name = "人事部")h.group_set.update_or_create(name="技术部")
相关文章:
Python学习笔记_进阶篇(三)_django知识(二)
本章内容 Django model Model 基础配置 django默认支持sqlite,mysql, oracle,postgresql数据库。 <1> sqlite django默认使用sqlite的数据库,默认自带sqlite的数据库驱动 引擎名称:django.db.backends.sqlite3 <2>mysql …...
RISC-V 整型通用寄存器介绍
简介 RISC-V64位/32位提供了32个整型通用寄存器,编号是x0~x31,这些整型通用寄存器的宽度与架构位数一致。 浮点数寄存器与整形寄存器一样也提供了32个:f0~f31,位数与架构位数一致。 通用寄存器介绍 零寄存器 x0/zero x0寄存…...
学习Vue:【性能优化】异步组件和懒加载
在Vue.js应用开发中,性能优化是一个至关重要的主题,而异步组件和懒加载是提升性能的有效方法之一。本文将介绍什么是异步组件和懒加载,以及如何在Vue.js中应用这些技术来提升应用性能。 异步组件和懒加载 异步组件 异步组件是指在需要的时候…...
pdf格式文件下载不预览,云存储的跨域解决
需求背景 后端接口中返回的是pdf文件路径比如: pdf文件路径 (https://wangzhendongsky.oss-cn-beijing.aliyuncs.com/wzd-test.pdf) 前端适配是这样的 <ahref"https://wangzhendongsky.oss-cn-beijing.aliyuncs.com/wzd-test.pdf&…...
httplib + nlohmann::json上传数据时中文乱码解决
1、nlohmann::json 1.1 编码格式使用UTF-8 参考 nlohmann::json 中文乱码解决方案 (1)将数据先转为UTF-8格式 2、httplib 2.1 上传数据前 (1)调用httplib::Response对象的set_header()方法来设置编码格式 httplib::Response res…...
JavaScript中的设计模式之一--单例模式和模块
虽然有一种疯狂天才的感觉可能很诱人,但重新发明轮子通常不是设计软件的最佳方法。很有可能有人已经遇到了和你一样的问题,并以一种聪明的方式解决了它。这样的最佳实践在形式化后被称为设计模式。今天我们来看看它们的概念,并检查单例模式和…...
回归预测 | MATLAB实现GAM广义加性模型多输入单输出回归预测(多指标,多图)
回归预测 | MATLAB实现GAM广义加性模型多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现GAM广义加性模型多输入单输出回归预测(多指标,多图)效果一览基本介绍程序设计参考资料 效果一览 基本…...
css学习4(背景)
1、CSS中,颜色值通常以以下方式定义: 十六进制 - 如:"#ff0000"RGB - 如:"rgb(255,0,0)"颜色名称 - 如:"red" 2、background-image 属性描述了元素的背景图像. 默认情况下,背景图像进…...
二、SQL,如何实现表的创建和查询
1、新建表格(在当前数据库中新建一个表格): (1)基础语法: create table [表名]( [字段:列标签] [该列数据类型] comment [字段注释], [字段:列标签] [该列数据类型] comment [字段注释], ……,…...
大数据及软件教学与实验专业实训室建设方案
一 、系统概述 大数据及软件教学与实验大数据及软件教学与实验在现代教育中扮演重要角色,这方面的教学内容涵盖了大数据处理、数据分析、数据可视化和大数据应用等多个方面。以下是大数据及软件教学与实验的一般内容:1. 数据基础知识:教授学生…...
信创办公–基于WPS的EXCEL最佳实践系列 (公式和函数)
信创办公–基于WPS的EXCEL最佳实践系列 (公式和函数) 目录 应用背景相关知识操作步骤1、认识基本的初级函数2、相对引用,绝对引用,混合引用3、统计函数4、文本函数 应用背景 熟练掌握Excel的函数工具能让我们在日常的使用中更加方…...
【Apollo】自动驾驶感知——毫米波雷达
作者简介: 辭七七,目前大一,正在学习C/C,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: 七七的闲谈 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖…...
SpringBoot部署到腾讯云
SpringBoot部署到腾讯云 此处默认已经申请到腾讯云服务器,因为本人还没有申请域名,所以就直接使用的ip地址 XShell连接到腾讯云 主机中填写腾讯云的公网ip地址 公网ip地址在下图中找到 接下来填写服务器的用户名与密码 一般centOS用户名为rootÿ…...
Git 设置代理
Git 传输分两种协议,SSH和 http(s),设置代理也需要分两种。 http(s) 代理 Command Line 使用 命令行 模式,可以在Powershell中使用以下命令设置代理: $env:http_proxy"http://127.0.0.1:7890" $env:https_proxy&quo…...
基于Spring Boot的机场VIP客户管理系统的设计与实现(Java+spring boot+MySQL)
获取源码或者论文请私信博主 演示视频: 基于Spring Boot的机场VIP客户管理系统的设计与实现(Javaspring bootMySQL) 使用技术: 前端:html css javascript jQuery ajax thymeleaf 微信小程序 后端:Java s…...
图数据库_Neo4j学习cypher语言_使用CQL_构建明星关系图谱_导入明星数据_导入明星关系数据_创建明星关系---Neo4j图数据库工作笔记0009
首先找到明星数据 可以看到有一个sheet1,是,记录了所有的关系的数据 然后比如我们搜索一个撒贝宁,可以看到撒贝宁的数据 然后这个是构建的CQL语句 首先我们先去启动服务 neo4j console 然后我们再来看一下以前导入的,可以看到导入很简单, 就是上面有CQL 看一下节点的属性...
恒运资本:算力概念强势拉升,亚康股份“20cm”涨停,首都在线等大涨
算力概念21日盘中强势拉升,到发稿,亚康股份“20cm”涨停,首都在线、汇金股份涨逾11%,鸿博股份亦涨停,南凌科技涨近9%,科创信息、神州数码、铜牛信息等涨超7%。 音讯面上,8月19日,202…...
Neo4j之union基础
UNION 用于将多个 MATCH 或 RETURN 子句的结果合并为一个结果集。它可以用来合并不同模式的节点和关系,或者将多个查询的结果合并在一起。以下是一些常用的示例和解释: 基本用法: MATCH (p:Person) WHERE p.age > 30 RETURN p.name AS n…...
搭建:基于nginx的上传功能
搭建:基于nginx的上传功能 文章目录 搭建:基于nginx的上传功能一、准备二、安装nginx1.1 解压nginx和nginx插件1.2 编译并安装nginx 三、启动一个python后台服务,用于上传到临时路径文件,转移到正式路径四、添加nginx配置…...
JavaScript高级
1、JavaScript面向对象 1.1、面向对象介绍 在 Java 中我们学习过面向对象,核心思想是万物皆对象。在 JavaScript 中同样也有面向对象。思想类似。 1.2、类的定义和使用 结构说明 代码实现 <!DOCTYPE html> <html lang"en"> <head>…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
文件上传漏洞防御全攻略
要全面防范文件上传漏洞,需构建多层防御体系,结合技术验证、存储隔离与权限控制: 🔒 一、基础防护层 前端校验(仅辅助) 通过JavaScript限制文件后缀名(白名单)和大小,提…...
