zoukankan      html  css  js  c++  java
  • django学习の模型

    orm:对象数据库和模型的映射。如果想以简单的方式去操作数据库,例如用类的方式去操作,就像 p = Person.get(id = 1),那么就必须使得代码和数据库的结构具有映射关系,实现这种关系,你可以事先就预先好一套创建类以及到数据库表的对应关系,也可以实时追踪数据库结构,很明显,第二张方式实现起来比较影响效率,所以大多数时候,在一开始,就用模型来对应数据库的一种关系,然后保证它们结构统一,就可以实现高度封装sql语句,用简洁明了的方式去操作业务逻辑,就像p = Person.get(id = 1),你就获得了数据库中person表的一个实例(信息)。当然,自己实现这样一个封装框架是比较复杂,django有强大的模型系统.

    模型用类来表示数据库的表,每一个类属性是表中的一个字段,当然这个属性必须是django给出的field子类。先来做一个非常简单的模型。配置好django,创建好django项目以后。

    #-*- coding:utf-8 -*-
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    from django.utils import timezone
    # Create your models here.
    class User(models.Model):
    name = models.CharField(max_length=10)
    sex = models.CharField(max_length=10)

    这样,就得到了一个模型,这个模型会在数据库中创建一个user表,并且有一个name列,和sex列,他们都是varchar类型。modes提供了很多相应的field类型

    CharField(max_lenght=10)中max_lenght是一个必须的字段,表示他的长度。如果需要一个无限长的较大文本,可以考虑用TextField,常用的字段有EmailField,

    URLField,IPAddressField,BooleanField,NullBooleanField,FileField(保存文件),具体细节可以看官方文档,他们都是继承至Field类,在models块中。一般情况你可以用

    IntegerField 表示数字,传入primary_key=True可以定义为主键

    默认系统会自己生成主键。然后现在想写第二个类了,我们有了,User类,可以假设现在这一群User可能是几个团队的分子,并且一人只能参加一个团队,那么先得有个Team

    #-*- coding:utf-8 -*-
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    from django.utils import timezone
    # Create your models here.
    class User(models.Model):
        name = models.CharField(max_length=10)
        sex = models.CharField(max_length=10)
    
    class Team(models.Model):
        name = models.CharField(max_length=10)
    这样就多了一个Team类,按一开始的设定要用到一对多的关系外键,所以要用ForeignKey(Team),像这样
    #-*- coding:utf-8 -*-
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    from django.utils import timezone
    # Create your models here.
    class User(models.Model):
        name = models.CharField(max_length=10)
        sex = models.CharField(max_length=10)
        team = models.ForeignKey(Team)
    
    class Team(models.Model):
        name = models.CharField(max_length=10)

    但是如果现在同步会出错,因为Team在User下面,解释时还没有,会报错,一般输入python manage.py makemigrations创建一个历史迁移文件,然后migrate执行迁移,就会同步到数据库.为了不报错,应该是这样:

    #-*- coding:utf-8 -*-
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    from django.utils import timezone
    # Create your models here.
    
    
    class Team(models.Model):
        name = models.CharField(max_length=10)
    
    class User(models.Model):
        name = models.CharField(max_length=10)
        sex = models.CharField(max_length=10)
        team = models.ForeignKey(Team)

    这个时候,user这个群体可能是好友,好友的关系是多对多,一个人可能有很多好友,并且每个好友也有很多好友,所以有多对多的关系,如下:

    #-*- coding:utf-8 -*-
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    from django.utils import timezone
    # Create your models here.
    class User(models.Model):
        name = models.CharField(max_length=10)
        sex = models.CharField(max_length=10)
        team = models.ForeignKey(Team)
        friend = models.ManyToManyField('self')
    
    class Team(models.Model):
        name = models.CharField(max_length=10)

    'self'表示是自己,如果是Team传入类变量即可,同样适用于外键。django默认表示如果你是我好友,那我也是你好友,用symmetrical = False参数可以打破这种对称,如果需要可以用在ManyToManyField。

    如果有的Team比较特殊,他们不仅有名字,还有特别的字段,比如坦克,但是它们又是Team,可以用继承,也可以用OneToOneField(Team).用继承如下:

    #-*- coding:utf-8 -*-
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    from django.utils import timezone
    # Create your models here.
    class User(models.Model):
        name = models.CharField(max_length=10)
        sex = models.CharField(max_length=10)
        team = models.ForeignKey(Team)
        friend = models.ManyToManyField('self')
    
    class Team(models.Model):
        name = models.CharField(max_length=10)
    
    class SuperTeam(Team):
        tank = models.CharField(max_length=10)

    这样可能看不出用继承有什么优势,如果Team类有一万个属性,而SuperTeam有一万零一,前一万个和Team一样,就可以用继承。

    有时候继承可能不需要Team,就是实际上Team用不到,那么可以把Team设置成抽象继承类,数据库就不会创建这张表,它只是为了继承而存在的,在Team的Meta嵌套类里面

    定义abstruct = True,就像这样:

    #-*- coding:utf-8 -*-
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    from django.utils import timezone
    # Create your models here.
    class User(models.Model):
        name = models.CharField(max_length=10)
        sex = models.CharField(max_length=10)
        team = models.ForeignKey(Team)
        friend = models.ManyToManyField('self')
    
    class Team(models.Model):
        name = models.CharField(max_length=10)
        class Meta:
            abstract = True
    
    class SuperTeam(Team):
        tank = models.CharField(max_length=10)

    嵌套类细节可参考官方文档

    多对多关系实际上是在数据库建立第三张表来保存这种关系,有时候如果希望这张表也有字段,那就可以自己来写这张表,比如User成为好友的时间。

    #-*- coding:utf-8 -*-
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    from django.utils import timezone
    # Create your models here.
    class User(models.Model):
        name = models.CharField(max_length=10)
        sex = models.CharField(max_length=10)
        team = models.ForeignKey(Team)
        friend = models.ManyToManyField('self',through='FriendShip')
    
    class Team(models.Model):
        name = models.CharField(max_length=10)
        class Meta:
            abstract = True
    
    class SuperTeam(Team):
        tank = models.CharField(max_length=10)
    
    class FriendShip(models.Model):
        user = models.ForeignKey(User)
        friend = models.ForeignKey(User)
        data_became_friend = models.DateTimeField(default=timezone.now)

    先通过through指定想成为好友关系的表,然后第三种表中定义这种关系,如果是不同类之间的多对多,那么也一样,只是有一个外键指向另一张成为好友的表就行了,然而这里面有个矛盾,假如关系表里面外键User,像这个例子,多于三个,像这样

    class FriendShip(models.Model):
    user = models.ForeignKey(User,relat_name = 'user_set')
    friend = models.ForeignKey(User)
    three = models.ForeignKey(User)
    data_became_friend = models.DateTimeField(default=timezone.now)

    django并没有智能到可以分辨哪一个字段是他想要对应的,因为本来是两者的好友关系,莫名其妙多了第三种,这时候需要在外键里面加入through_fields = ('user','friend')参数,同理如果是不同类的多对多,也应该按顺序写参数。

    至于操作,django提供了manage,和QuerySet,这都是什么鬼啊。

    而objects就是每个类只想manage的变量,manage获得,提供了all filter exclude get 方法,返回Queryset对象,Queryset本身也提供了manage的方法,所以最后是支持连缀操作的,就像,get(id =1).filter(name__contains = "Tree"),django也提供了很多像__contains这样的过滤操作,只需名字__contains就可以了。修改有update,或者直接属性赋值修改,这种修改把没有修改的值也修改一遍,按照原来的值。最后save函数会把结果在数据库执行,这是一种惰性机制,我并不会第一时间的执行。

    创建:

    创建实例有两种方法,一种是惰性的,比如需要一个user对象,只需要:索隆 = User(name = ‘索隆’,sex='男',),然后调用索隆.save()保存.

    一种是直接   索隆.objects.create(.....)创建。

    对于普通多对多还有,如索隆.friendship.create(name = '路飞')或者 索隆.friendship.add(实例对象)来创建对象或添加对象,并且django会做好所有事情,然而对于上面提到的自定义的多对多关系表则不行,因为既然你用到了自定义关系表,很大意义上是因为你需要额外的字段,如果这样创建,那么django根本不能知道你想为额外的字段添加什么,

    在这种情况下,唯一办法就是先创建好两个实例,如:a = User.objects.create(....),b=User.objects.create(....),然后Friendship.objects.add(a,b,额外字段=好)这样创建。

    获取:

    基于manage的方法,一般是对象.objects.方法()获取。

    get(),获得单一对象。

    filter(),过滤器,获得一个queryset

    all(),如其名,获得所有对象。

    order_by('字段'),按字段排序

    exclude(),和filter相反,获得filter的补集

    返回的queryset是支持切片操作的,同时queryset也支持了filter和exclude以及order_by更多额外的方法。

    还有查询字段时,通过  字段名__contains = 'ssss'可以改变查询方式,默认是__exact精准查询。

    __contains: 即使sql的like

    __icontains:忽略大小写

    __gt    :      大写

    __gte   :      大于等于

    __lt      :      小于

    __lte    :      小于等于

    __in      :      在list范围内

    __startswith 和 __istartswith:以什么开头

    __endswith  __iendswith:结尾

    __range:范围

    __year,__month,__day

    __isnull.

    Q对象:

    django.db.models里面的Q对象,用Q对象包裹以后参数就可以用|  &  ~来查询,如get(Q(name__contains='sss')|Q(,,,,)).

      



  • 相关阅读:
    94. Binary Tree Inorder Traversal
    101. Symmetric Tree
    38. Count and Say
    28. Implement strStr()
    实训团队心得(1)
    探索性测试入门
    LC.278. First Bad Version
    Search in Unknown Sized Sorted Array
    LC.88. Merge Sorted Array
    LC.283.Move Zeroes
  • 原文地址:https://www.cnblogs.com/wuweixin/p/4923771.html
Copyright © 2011-2022 走看看