Django框架 数据库模型(Model)2 表操作

参考:
https://www.cnblogs.com/wupeiqi/articles/6216618.html
一.书籍-作者-出版社数据库结构:

作者模型:作者有1个姓名

作者详细模型:把作者的详情放到详情表,包含性别/email地址/出生日期
  和作者模型之间是one-to-one;也可以和作者模型和成1张表

出版商模型:出版商有名称/地址/所在城市/省/国家/网站

书籍模型:书籍有书名/出版日期,1本书可能有多个作者,反之亦然,1本书只应该由1家出版商出版,所以出版商和书籍是one-to-many(外键)

1.表的创建:

ORM中创建表实际上就是创建类;创建记录实际上就是实例化类,生成对象

#实例:
from django.db import models<br>

class Publisher(models.Model):#继承models.Model对象
    name=models.CharField(max_length=30,verbose_name="名称")#varchar类型
    address=models.CharField("地址",max_length=50)
    city=models.CharField('城市',max_length=60)
    state_province=models.CharField(max_length=30)
    country=models.CharField(max_length=50)
    website=models.URLField()
 
    class Meta:
        verbose_name='出版商'
        verbose_name_plural=verbose_name
 
    def __str__(self):#打印实例对象时显式其name属性
        return self.name
 
class Author(models.Model):
    name=models.CharField(max_length=30)

    def __str__(self):
        return self.name
 
class AuthorDetail(models.Model):
    sex=models.BooleanField(max_length=1,choices=((0,'男'),(1,'女'),))
    email=models.EmailField()
    address=models.CharField(max_length=50)
    birthday=models.DateField()
    author=models.OneToOneField(Author)#一对一的外键
 
class Book(models.Model):
    title=models.CharField(max_length=100)
    authors=models.ManyToManyField(Author)#多对多的外键
    publisher=models.ForeignKey(Publisher)
    publication_date=models.DateField()#date类型
    price=models.DecimalField(max_digits=5,decimal_places=2,default=10)#decimal类型

    def __str__(self):
        return self.title

#然后在Pycharm的终端中执行:
python manage.py makemigrations
#在应用文件夹下的migrations文件夹中创建了1个0001_initial.py
#0001_initial.py中生成了了以上代码中创建的类

#然后在Pycharm的终端中执行:
python manage.py migrate
#创建了表(除了以上各表,还有默认的表)
#注意:
1.先在settings里的INSTALLED_APPS中加入'app01',然后同步数据库
2.models.ForeignKey("Publish") & models.ForeignKey(Publish)
3.1张表中如果没有主键,会自动创建id字段并设为主键
4.对字段的大小写不敏感

2.说明:

1.每个数据模型都是django.db.models.Model的子类
其父类Model包含了所有必要的和数据库交互的方法,并提供了简介漂亮的定义数据库字段的语法
2.每个模型(类)相当于单个数据库表(多对多关系例外,会多生成1张关系表)
每个属性也是这个表中的字段,属性名就是字段名,属性的类型(如CharField)相当于数据库的字段类型(如varchar)

二.字段参数
1.常用字段类型:

全部在models下面,即models.<field_type>()
通过Django Admin及ModelForm验证合法性
所有参数均为关键字参数
##############################################################################
AutoField(Field):添加记录时会自动增长的IntegerField
  #相当于MySQL中的Auto Increment
  #通常不需要直接使用这个字段的数据
  #自定义1个主键:如果不指定主键,系统会自动添加1个名为id的主键字段
    my_id=models.AutoField(primary_key=True)#该字段类型必须被指定为主键
##############################################################################
BinaryField(Field):二进制类型字段
##############################################################################
BigAutoField(AutoField):Bigint自增字段(和AutoField的区别在于存储的范围更大)
  #该字段类型必须被指定为主键
##############################################################################
BigIntegerField(IntegerField):长整型字段
  范围为[-9223372036854775808,9223372036854775807]
##############################################################################
BooleanField(Field):布尔值字段
  #admin用1个checkbox来表示此类字段的数据
##############################################################################
CharField(CharField):字符字段,用于较短的字符串
  #参数说明:
    max_length:从数据库层和Django校验层限制该字段的最大字符数
      #为int;必选
##############################################################################
CommaSeparatedIntegerField(CharField):用逗号分隔的整数值字段
  #类似于CharField
  #参数说明:必选
    maxlength:字段的最大字符数
##############################################################################
DateField(DateTimeCheckMixin,Field):日期字段
  格式:YYYY-MM-DD
  #参数说明:均可选
    Argument:描述
    auto_now:对象被保存时,自动将该字段的值设为当前时间
      #通常用于表示"last-modified"时间戳
    auto_now_add:对象首次被创建时,自动将该字段的值设为当前时间
      #通常用于表示对象创建时间
  #仅在admin中有意义...
##############################################################################
DateTimeField(DateField):日期时间字段,类似 DateField,支持同样的附加选项
  格式:YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
##############################################################################
DecimalField(Field):10进制小数字段(没有误差)
  #实际是把num当成str来存储
  #参数说明:
    max_digits:总位数
    decimal_places:小数点后位数
##############################################################################
DurationField(Field):时间间隔字段
  在数据库中按Bigint存储,在ORM中获取的值为datetime.timedelta类型
##############################################################################
EmailField(CharField):带有检查Email合法性的CharField
  #不接受maxlength参数
##############################################################################
FileField(Field):文件上传字段
  #admin用1个<input type="file">部件表示该字段保存的数据(1个文件上传部件)
  #参数说明:必选
    upload_to:用于保存上载文件的本地文件系统路径
      #这个路径必须包含strftime #formatting,该格式将被上载文件的date/time替换(so that uploaded files don't fill up the given directory)
    storage:存储组件;默认django.core.files.storage.FileSystemStorage

#注意:在model中使用FileField/ImageField需要以下步骤:
  1.在settings.py中定义1个完整路径给MEDIA_ROOT以便让 Django在此处保存上传文件
    #出于性能考虑,这些文件并不保存到数据库
    #定义MEDIA_URL作为该目录的公共URL,要确保该目录对WEB服务器用户帐号是可写的
  2.在model中添加FileField/ImageField
  并确保定义了upload_to 选项,以告诉Django使用MEDIA_ROOT的哪个子目录保存上传文件
    #数据库中要保存的只是文件的路径(相对于MEDIA_ROOT)
    #出于习惯你一定想使用Django提供的get_<#fieldname>_url函数
    #举例来说,如果你的ImageField叫作mug_shot,你就可以在模板中以{{ object.#get_mug_shot_url }}的方式得到图像的绝对路径
##############################################################################
FilePathField(Field):文件系统中某个特定目录下的文件
  #参数说明:path必选,其余可选
    path:文件的系统绝对路径,:"/home/images";用于得到文件
    match:1个正则表达式;str;用于过滤文件名
      #如:match="foo.*\.txt^",将匹配文件foo23.txt而不匹配bar.txt/foo23.gif
      #注意:该参数仅应用到base filename而非路径全名
        #如:FilePathField(path="/home/images",match="foo.*",recursive=True)
        #会匹配 /home/images/foo.gif而不匹配/home/images/foo/bar.gif
    recursive:是否包括path下的全部子目录;bool;默认为False
    allow_files:是否允许文件;默认为True
    allow_folders:是否允许文件夹;默认为False
##############################################################################
FloatField(Field):浮点数字段(可能存在误差)
  #admin用1个文本框(<input type="text">)表示该字段的数据
  #参数说明:
    max_digits:总位数(不包括小数点和符号)
    decimal_places:小数位数
  #实例:
    #保存最大值为999(小数点后保留2位)的浮点数:
    models.FloatField(max_digits=5,decimal_places=2)
    #保存最大值为一百万(小数点后保存10位):
    models.FloatField(max_digits=19,decimal_places=10)
##############################################################################
GenericIPAddressField(Field):可支持IPv4和IPv6的IPAddressField
  #参数说明:均可选
    protocol:指定支持IPv4还是Ipv6;可为"both"(默认值)/"ipv4"/"ipv6"
    unpack_ipv4:如为True,则输入::ffff:192.0.2.1,可解析为192.0.2.1;默认为False
      #开启此功能需要protocol="both"
##############################################################################
ImageField(FileField):类似FileField,不过要校验上传对象是否是合法图片
  #路径保存在数据库,文件上传到指定目录
  #参数说明:均可选
    upload_to:文件的保存路径
    storage:存储组件;默认django.core.files.storage.FileSystemStorage
    height_field:指定图片保存的高度规格
    width_field:指定图片保存的宽度规格    
##############################################################################
IntegerField(Field):整数字段
  范围为[-2147483648,2147483647]
##############################################################################
IPAddressField(Field):str形式的IP地址字段,仅支持IPv4
  #如:"24.124.1.30"
##############################################################################
NullBooleanField(Field):类似BooleanField,不过允许NULL作为其中的选项
  #推荐使用这个字段而不要用BooleanField并设置null=True
  #admin用1个选择框<select>(3个可选择的值:"Unknown"/"Yes"/"No")来表示该种类型
##############################################################################
PositiveIntegerField(PositiveIntegerRelDbTypeMixin,,IntegerField):正整数字段
  范围为[0,2147483647]
##############################################################################
PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin,IntegerField):正小整数字段
  范围为[0,32767]
##############################################################################
SlugField(CharField):短签字段,即只包含字母/数字/下划线(_)/减号(-),通常用于URLs
  #参数说明:
    max_length:字段的最大字符数;默认为50
      #在旧版本中无法更改默认值
##############################################################################
SmallIntegerField(IntegerField):小整数字段
  范围为[-32768,32767]
##############################################################################
TextField(Field):文本字段,用于长文本
  #admin用1个文本区域(<textarea>)来表示该字段的数据
    #文本区域是1个多行编辑框
##############################################################################
TimeField(DateTimeCheckMixin,Field):时间字段
  格式:HH:MM[:ss[.uuuuuu]]
##############################################################################
URLField(CharField):URL字段
  #admin用1个<input type="text">文本框表示该字段保存的数据(1个单行编辑框)
  #参数说明:
    verify_exists:若为True(默认),给定的URL会预先检查是否存在( 即URL是否被有效装入且没有返回404响应)
##############################################################################
UUIDField(Field):UUID字段
##############################################################################
XMLField:用于校验值是否为合法XML的TextField
  #参数说明:必选
    schema_path:用来校验文本的RelaxNG schema的文件系统路径
向表中添加字段时表中可能已经有记录,会提示设置默认值还是取消本次操作

2.主要字段共用参数:

  • 这些参数可以用于任何字段类型
  • 均为关键字参数
blank:在Admin中是否允许用户输入空值;bool
##############################################################################
choices:选择框中的选项
  为12tuple构成的tuple;1个值是实际存储的值,2个用来进行选择
  #把不变的数据放在内存中从而避免跨表操作:SEX_CHOICES=(('F','Female'),('M','Male'),)
     gender=models.CharField(max_length=2,choices=SEX_CHOICES)
##############################################################################
db_column:数据库中的字段名;str;默认和Model中相同
##############################################################################
db_index:是否在数据库中为该字段建立索引;bool
  #索引其实是存储在另1个文件中的二叉树,可以加速查找
##############################################################################
default:字段的默认值
##############################################################################
editable:在Admin中是否允许编辑;bool;默认为True
##############################################################################
error_messages:自定义的错误信息(用于定制显示的错误信息);dict
  字典的健可为:null/blank/invalid/invalid_choice/unique/unique_for_date
  如:{"null":"不能为空.","invalid":"格式错误"}
##############################################################################
help_text:在Admin中该字段的提示信息;str
##############################################################################
null:在数据库中字段是否可为空;bool;默认为True
##############################################################################
primary_key:是否为主键;bool
  如果没有设置django创建表时会自动加上:
    id=meta.AutoField('ID',primary_key=True)
    primary_key=True implies blank=False,null=False and unique=True.
    Only one primary key is allowed on an object.
  #也是1种特殊的索引,可以加速查找+限制字段值唯一且非空
##############################################################################
unique:是否在数据库中为该字段建立唯一索引;bool
  OneToOneField=Foreign Key+唯一索引
##############################################################################
unique_for_date:是否在数据库中为该字段[]部分建立唯一索引;bool
  #除了可以加速查找,还可以约束字段中的值唯一
##############################################################################
unique_for_month:是否在数据库中为该字段[]部分建立唯一索引;bool
##############################################################################
unique_for_year:是否在数据库中为该字段[]部分建立唯一索引;bool
##############################################################################
validators:自定义错误验证(用于定制验证规则);list
  #需要:
    from django.core.validators import RegexValidator
    from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
        MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
  #如:
      test=models.CharField(
          max_length=32,
          error_messages={
              'c1':'优先错信息1',
              'c2':'优先错信息2',
              'c3':'优先错信息3',
          },
          validators=[
              RegexValidator(
                  regex='root_\d+',
                  message='错误了',
                  code='c1'
              ),
              RegexValidator(
                  regex='root_112233\d+',
                  message='又错误了',
                  code='c2'
              ),
              EmailValidator(
                  message='又错误了',
                  code='c3'
              ),
          ]
##############################################################################
verbose_name:Admin中显示的字段名称;str

3.Model中字段类型在MySQL中的属性:

'AutoField': 'integer AUTO_INCREMENT',
'BigAutoField': 'bigint AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
'CharField': 'varchar(%(max_length)s)',
'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'DurationField': 'bigint',
'FileField': 'varchar(%(max_length)s)',
'FilePathField': 'varchar(%(max_length)s)',
'FloatField': 'double precision',
'IntegerField': 'integer',
'BigIntegerField': 'bigint',
'IPAddressField': 'char(15)',
'GenericIPAddressField': 'char(39)',
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(max_length)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'UUIDField': 'char(32)',

4.自定义无符号的整数字段:

class UnsignedIntegerField(models.IntegerField):
    def db_type(self,connection):
        return 'integer UNSIGNED'

#注意:返回值为字段在数据库中的属性

三.其他相关事项
1.原生SQL:

Raw SQL(原生SQL):
Django中Models的操作,也是调用了ORM框架来实现的,PyMySQL或MySQLdb
所以也可以使用原生SQL语句来操作数据库
#每次创建1个对象,想显示对应的原生SQL语句(Raw SQL)
#需要在settings.py中加上日志记录(LOGGING)部分:
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

2.元信息:
更多属性参见:https://www.cnblogs.com/flash55/p/6265405.html

class Info(models.Model):
    nid=models.AutoField(primary_key=True)
    name=models.CharField(max_length=32)
    date=models.DateField()
    pub=models.CharField(max_length=32)
    writer=models.CharField(max_length=16)
    class Meta:
        #当前类是不是1个抽象类:
          #抽象类不对应表:一般用来归纳公共属性字段,然后继承它的子类可以继承这些字段
        abstract=False
        #数据库中生成的表名:
          #默认为:<应用名>_<类名>
        db_table="table_name"
        #联合索引:
        index_together=[
            ("date","name"),
        ]
        #联合唯一索引:
          #ManyToManyField就在多对多关系中的第3张表中使用了本约束
          #以防止2个表中相同字段重复建立关联
        unique_together=(
            ("pub","writer"),
        )
        #admin中显示的表名称:
        verbose_name="BookInfo"

3.关于验证和错误提示:

1.触发错误提示:
  a.在Admin中优先显示Admin内的ModelForm的错误信息,然后才是Model字段的错误信息
  b.调用Model对象的clean_fields方法(如下例)

#models.py:
class UserInfo(models.Model):
    nid=models.AutoField(primary_key=True)
    username=models.CharField(max_length=32)
    email=models.EmailField(error_messages={'invalid':'格式错了.'})

#views.py:
def index(request):
    obj=models.UserInfo(username='11234',email='uu')
    try:
        print(obj.clean_fields())
   except Exception as e:
        print(e)
    return HttpResponse('ok')
#Model的clean()是1个钩子函数,可用于定制操作,如:上述的异常处理

##############################################################################

2.Admin中修改错误提示:
#admin.py:
from django.contrib import admin
from model_club import models
from django import forms

class UserInfoForm(forms.ModelForm):
    age=forms.IntegerField(
        initial=1,
        error_messages={
            'required':'请输入数值.',
            'invalid':'年龄必须为数值.'
        }
    )
    class Meta:
        model = models.UserInfo
        #fields=('username',)
        fields="__all__"
        exclude=['title']
        labels={'name':'Writer',}
        help_texts={'name':'some help text.',}
        error_messages={'name':{'max_length':"The name is too long"}}
        widgets={'name':Textarea(attrs={'cols':80,'rows':20})}

class UserInfoAdmin(admin.ModelAdmin):
    form=UserInfoForm

admin.site.register(models.UserInfo, UserInfoAdmin)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值