django框架学习之django模型

模型,就是python中的类对应数据库中的表

​ORM 就是通过实例对象的语法,完成关系型数据库的操作的技术,是"对象-关系映射"(Object/Relational Mapping) 的缩写。

1.模型类生成数据库表

1.创建项目

  在cmd中运行:

#创建项目
django-admin startproject model_study
#进入项目目录创建子应用
python manage.py startapp model_app

2.配置应用

1.将模型对应的应用程序添加到项目的settings中:

INSTALLED_APPS = [
    'model_app'
]

2.在settings中配置正确的数据库连接:

# sqlite3
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

# mysql
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'model_study',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

3.编写模型

from django.db import models

# 创建模型类必须继承models.Model
class Question(models.Model):
  question_title=models.CharField(max_length=20,default="")
  question_text = models.CharField(max_length=200)
  pub_date = models.DateTimeField()

4. 预备迁移 

  在cmd项目根目录中运行        

python manage.py makemigrations model_app

5.正式迁移

  在cmd项目根目录中运行

python manage.py migrate

2.数据库表逆向生成模型类

  在根目录的cmd中运行:

python manage.py inspectdb > model_app/models.py

3.Field字段 

1.命名规则:数字,字母,下划线组成,字母不能在开头,且不能为Python保留字

2.AutoField和primary_key

  默认会自动创建一个自增,主键的id列,如果指定了 primary_key 为其它列,那么不会自动创建id    列​  可以在模型中指定:

id = models.AutoField(primary_key=True)

3.常见Field

所有的Field类型,见 Field类型

常见的Field类型:

 AutoField

​ BooleanField

​ CharField

​ DateField

​ DateTimeField

​ FloatField

​ SmallIntegerField

​ IntegerField

​ TextField

4.Field常见参数

  • max_length:字段最大长度,用于字符串等,字符串类型CharField必须设置该值
  • null:如果True,Django将在数据库中存储NULL空值。默认是False
  • blank:如果True,该字段被允许为空白("")。默认是False。请注意,这不同于null。null纯粹是与数据库相关的,而blank与验证相关。如果一个字段有blank=True,表单验证将允许输入一个空值。如果一个字段有blank=False,该字段将是必需的。
  • choices:示例:YEAR_IN_SCHOOL_CHOICES = (('FR', 'Freshman'),('SO', 'Sophomore'),('JR', 'Junior'),('SR', 'Senior'),('GR', 'Graduate')) ,中文示例:SEX_CHOICES=((1, '男'),(2, '女')),元组中的第一个元素是将存储在数据库中的值,第二个元素是将在页面中显示的值,最常见用于下拉选择框select
  • default:字段的默认值
  • help_text:用于显示额外的“帮助”文本
  • primary_key:如果True,这个字段是模型的主键,默认是False
  • unique:如果True,该字段在整个表格中必须是唯一的
  • verbose_name:详细字段名,不指定则是属性名的小写,并且用 空格 替换 '_'

5、模型之间的关系

  • 主外关系中,关联操作最常用的是: models.CASCADE 级联删除 和 models.SET_NULL 设置为null

  • 一对多关系中,ForeignKey 写在一对多关系中,多的那个模型中

1.一对一关系

  OneToOneField写在任何一方都可以

from django.db import models

# Create your models here.
class Place(models.Model):
    name=models.CharField(max_length=20)
    address=models.CharField(max_length=20)
    def __str__(self):
        return f"the place's name is {self.name}"

class School(models.Model):
    place=models.OneToOneField(
        Place,
        on_delete=models.CASCADE,
        primary_key=True
    )
    name=models.CharField(max_length=20)
    has_teacher=models.BooleanField(default=True)
    has_car=models.BooleanField(default=False)
    def __str__(self):
        return f"the school's name is {self.place}"

 2.一对多关系

  ForeignKey写在多的一方

from django.db import models

# Create your models here.
class Teacher(models.Model):
    name=models.CharField(max_length=20)
class Student(models.Model):
    teacher=models.ForeignKey(Teacher,on_delete=models.CASCADE)
    name=models.CharField(max_length=20)

3.多对多关系

from django.db import models

# Create your models here.
# 1.自关联
# ManyToManyField写在本类中
class Student(models.Model):
    name=models.CharField(max_length=10)
    friends=models.ManyToManyField("self")

# 2.多对多
class schoolClass(models.Model):
    name=models.CharField(max_length=10)
class Teacher(models.Model):
    name=models.CharField(max_length=10)
    school_class=models.ManyToManyField(schoolClass)    

# 3.自定义中间表
class Person(models.Model):
    name=models.CharField(max_length=10)
class Group(models.Model):
    name=models.CharField(max_length=10)
    members=models.ManyToManyField(
        Person,
        through="MemberShip",
        through_fields=("group","person")
    )
class MemberShip(models.Model):
    person=models.ForeignKey(Person,on_delete=models.CASCADE)
    group=models.ForeignKey(Group,on_delete=models.CASCADE)
    level=models.IntegerField(default=1)

4.方法(数据的相关操作)

​ 在根目录的cmd执行:

python manage.py shell

首先导入模块,通过导入的模块中的模型对象objects属性执行操作 

1.新增:

save或create

1.一对多关系新增:

from django.db import models

# Create your models here.
class Teacher(models.Model):
    name=models.CharField(max_length=20)
class Student(models.Model):
    teacher=models.ForeignKey(Teacher,on_delete=models.CASCADE)
    name=models.CharField(max_length=20)

方法一:

在创建Student实例对象的时候对teacher进行赋值

>>> from one_more_app.models import *
>>> Teacher.objects.create(name="王老师") 
<Teacher: Teacher object (1)>
>>> Teacher.objects.create(name="李老师") 
<Teacher: Teacher object (2)>
# 根据查询到的数据进行赋值
>>> t=Teacher.objects.get(pk=1)      
>>> t
<Teacher: Teacher object (1)>
>>> Student.objects.create(teacher=t,name="xialei")
<Student: Student object (1)>

方法二:

创建完Student实例对象后再对类属性teacher赋值

>>> t=Teacher.objects.get(pk=2)     
>>> t
<Teacher: Teacher object (2)>
>>> s=Student(name="zmy")
>>> s.teacher=t
>>> s.save()

2.多对多关系新增:

先各自都创建实例对象,再进行关联操作

from django.db import models

class schoolClass(models.Model):
    name=models.CharField(max_length=10)
class Teacher(models.Model):
    name=models.CharField(max_length=10)
    school_class=models.ManyToManyField(schoolClass) 

>>> from more_more_app.models import *
>>> schoolClass.objects.create(name="class1")
<schoolClass: schoolClass object (1)>
>>> schoolClass.objects.create(name="class2")
<schoolClass: schoolClass object (2)>
>>> schoolClass.objects.create(name="class3")
<schoolClass: schoolClass object (3)>
>>> Teacher.objects.create(name="zhangsan")
<Teacher: Teacher object (1)>
>>> Teacher.objects.create(name="lisi")
<Teacher: Teacher object (2)>
>>> Teacher.objects.create(name="xialei")
<Teacher: Teacher object (3)>
>>> t=Teacher.objects.get(pk=3) 
>>> t
<Teacher: Teacher object (3)>
# set方法不会增加,而是重新赋值
>>> t.school_class.set([2,3]) 
# add方法增加
>>> t.school_class.add(1)

2.查询

1.过滤器:

from django.db import models

# Create your models here.
class Question(models.Model):
  question_title=models.CharField(max_length=20,default="")
  question_text = models.CharField(max_length=200)
  pub_date = models.DateTimeField()

(1)get获取一个对象

>>> Question.objects.get(id=1)
<Question: Question object (1)>
>>> Question.objects.get(question_title='c') 
<Question: Question object (3)>

(2)all获取多个对象

>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>, <Question: Question object (3)>]>

(3)filter过滤

>>> Question.objects.filter(question_title="c")
<QuerySet [<Question: Question object (3)>]>
>>> Question.objects.filter(id=2)               
<QuerySet [<Question: Question object (2)>]>

2.字段查找

完整的字段查找文档:字段检索

常见的字段检索:

exact :判断是否等于value,一般不使用,而直接使用 '='

>>> Question.objects.get(id__exact=3) 
<Question: Question object (3)>

contains:是否包含,大小写敏感,如果需要不敏感的话,使用icontains

>>> Question.objects.filter(question_title__contains='j') 
<QuerySet [<Question: Question object (2)>]>
>>> Question.objects.filter(question_title__contains='J') 
<QuerySet []>
>>> Question.objects.filter(question_title__iscontains='J') 
>>> Question.objects.filter(question_title__icontains='J')  
<QuerySet [<Question: Question object (2)>]>

startswith:以value开头,大小写敏感

>>> Question.objects.filter(question_title__startswith="java") 
<QuerySet [<Question: Question object (2)>, <Question: Question object (4)>]>

endwith:以value结尾,大小写敏感

>>> Question.objects.filter(question_title__endswith="s")      
<QuerySet [<Question: Question object (4)>]>

in:是否包含在范围内

>>> Question.objects.filter(id__in=[1,2,4]) 
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>, <Question: Question object (4)>]>

isnull:是否为null, 如:filter(name__isnull=Flase)

>>> Question.objects.filter(id__isnull=False)  
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>, <Question: Question object (3)>, <Question: Question object (4)>]>

gt:大于,如:filter(sage__gt=30) , 年龄大于30

>>> Question.objects.filter(id__gt=2)         
<QuerySet [<Question: Question object (3)>, <Question: Question object (4)>]>

gte:大于等于

>>> Question.objects.filter(id__gte=2) 
<QuerySet [<Question: Question object (2)>, <Question: Question object (3)>, <Question: Question object (4)>]>

lt:小于

>>> Question.objects.filter(id__lt=2)  
<QuerySet [<Question: Question object (1)>]>

lte:小于等于

>>> Question.objects.filter(id__lte=2) 
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>]>

3.日期时间的过滤

(1)使用gt,gte,lt,lte

>>> Question.objects.filter(pub_date__gt="2015-2-20") 
<QuerySet [<Question: Question object (2)>, <Question: Question object (3)>]>

(2)__range查询时间段

>>> Question.objects.filter(pub_date__range=["2010-1-03","2015-2-23"]) 
<QuerySet [<Question: Question object (1)>, <Question: Question object (4)>]>

(3)__date查询某年某月某日 

>>> Question.objects.filter(pub_date__date="2022-03-22")                 
<QuerySet [<Question: Question object (2)>]>

(4)__year查询某年

>>> Question.objects.filter(pub_date__year="2011")        
<QuerySet [<Question: Question object (1)>, <Question: Question object (4)>]>

  exclude:例外

>>> Question.objects.exclude(pub_date__year="2011") 
<QuerySet [<Question: Question object (2)>, <Question: Question object (3)>]>

(5)filter获取对象列表,支持切片但是不支持负数切片

>>> Question.objects.filter(pub_date__gt="2000-1-2") 
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>, <Question: Question object (3)>, <Question: Question object (4)>]>
>>> Question.objects.filter(pub_date__gt="2000-1-2")[:2] 
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>]>

6)__month查询某月

(7)__day查询某日

(8)__week_day查询星期几(1-7)

4.排序

order_by:默认按照升序排列

>>> Question.objects.filter(pub_date__year="2011").order_by("pub_date") 
<QuerySet [<Question: Question object (4)>, <Question: Question object (1)>]>

order_by括号后传入的参数前加“-”表示降序排列

>>> Question.objects.filter(pub_date__year="2011").order_by("-pub_date") 
<QuerySet [<Question: Question object (1)>, <Question: Question object (4)>]>

5.其他方法

(1)count对结果集进行计数

>>> Question.objects.filter(pub_date__year="2011").count()              
2

(2)reverse对结果集进行反转,可改变无法反向切片的不足之处,使用前必须先排序

>>> Question.objects.filter(pub_date__year="2011").order_by("pub_date")  
<QuerySet [<Question: Question object (4)>, <Question: Question object (1)>]>
>>> Question.objects.filter(pub_date__year="2011").order_by("pub_date").reverse()
<QuerySet [<Question: Question object (1)>, <Question: Question object (4)>]>
>>> Question.objects.filter(pub_date__year="2011").order_by("pub_date").reverse()[:1] 
<QuerySet [<Question: Question object (1)>]>

(3)first返回结果集的第一个对象

>>> Question.objects.filter(pub_date__gt="2000-2-2")  
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>, <Question: Question object (3)>, <Question: Question object (4)>]>
>>> Question.objects.filter(pub_date__gt="2000-2-2").first()
<Question: Question object (1)>

(4)last返回结果集的最后一个对象

>>> Question.objects.filter(pub_date__gt="2000-2-2")  
<QuerySet [<Question: Question object (1)>, <Question: Question object (2)>, <Question: Question object (3)>, <Question: Question object (4)>]>
>>> Question.objects.filter(pub_date__gt="2000-2-2").last()  
<Question: Question object (4)>

(5)values返回一个字典对象列表

<QuerySet [{'id': 1, 'question_title': 'python', 'question_text': 'python is easy', 'pub_date': datetime.datetime(2011, 2, 23, 0, 0, tzinfo=datetime.timezone.utc)}, {'id': 2, 'question_title': 'java', 'question_text': 'java is difficult', 'pub_date': datetime.datetime(2022, 3, 22, 0, 0, tzinfo=datetime.timezone.utc)}, {'id': 3, 'question_title': 'c', 'question_text': 'c is boring', 'pub_date': datetime.datetime(2022, 3, 11, 0, 0, tzinfo=datetime.timezone.utc)}, {'id': 4, 'question_title': 'javaScripts', 'question_text': 'javaScripts是前端', 'pub_date': datetime.datetime(2011, 1, 30, 0, 0, tzinfo=datetime.timezone.utc)}]>

values传参:

>>> Question.objects.filter(pub_date__gt="2000-2-2").values("question_title") 
<QuerySet [{'question_title': 'python'}, {'question_title': 'java'}, {'question_title': 'c'}, {'question_title': 'javaScripts'}]>

6.多对象关联查询

(1)一对一关系查询

from django.db import models

# Create your models here.
class Place(models.Model):
    name=models.CharField(max_length=20)
    address=models.CharField(max_length=20)
    def __str__(self):
        return f"the place's name is {self.name}"

class School(models.Model):
    place=models.OneToOneField(
        Place,
        on_delete=models.CASCADE,
        primary_key=True
    )
    name=models.CharField(max_length=20)
    has_teacher=models.BooleanField(default=True)
    has_car=models.BooleanField(default=False)
    def __str__(self):
        return f"the school's name is {self.place}"

通过一个模型获取另一个模型:通过定义OneToOneField的模型获取另一个模型

>>> school=School.objects.first()
>>> place=school.place
>>> place
<Place: the place's name is 安庆>

(2)一对多关系查询

from django.db import models

# Create your models here.
class Teacher(models.Model):
    name=models.CharField(max_length=20)
class Student(models.Model):
    teacher=models.ForeignKey(Teacher,on_delete=models.CASCADE)
    name=models.CharField(max_length=20)

  从一的模型查找多的模型,通过"多的模型的小写名_set"查找

>>> t=Teacher.objects.first()
>>> t
<Teacher: Teacher object (1)>
>>> s=t.student_set.all() 
>>> s
<QuerySet [<Student: Student object (2)>]>

  从多的模型查找一的模型

>>> s=Student.objects.first() 
>>> s
<Student: Student object (2)>
>>> teacher=s.teacher 
>>> teacher
<Teacher: Teacher object (1)>

(3)多对多关系查询

from django.db import models

# Create your models here.
class schoolClass(models.Model):
    name=models.CharField(max_length=10)
class Teacher(models.Model):
    name=models.CharField(maxt_length=10)
    school_class=models.ManyToManyField(schoolClass)    

  从没有ManyToManyField的模型中查询有ManyToManyField的模型

>>> s=schoolClass.objects.first() 
>>> t=s.teacher_set.all()
>>> t
<QuerySet [<Teacher: Teacher object (2)>]>

  从有ManyToManyField的模型中查询没有ManyToManyField的模型

>>> t=Teacher.objects.first()
>>> t
<Teacher: Teacher object (1)>
>>> s=t.school_class.all() 
>>> s
<QuerySet []>

7.聚合函数

使用aggregate()函数返回聚合函数的值

常用的聚合函数有:Avg、Count、Max、Min、Sum

使用前需要:from django.db.models import 聚合函数

>>> from django.db.models import Max,Min,Avg,Sum,Count
>>> Question.objects.aggregate(Max("id"),Min("id"),Sum("id"),Count("id"),Avg("id")) 
{'id__max': 4, 'id__min': 1, 'id__sum': Decimal('10'), 'id__count': 4, 'id__avg': 2.5}
>>>

8.分组查询

使用annotate()函数实现分组查询,得配合其他函数: 

   - annotate:用于分组,配合 Avg,Count等聚合函数,如:annotate(max=Max('age'))

(即:所需要统计的数据) 

   - filter:用于过滤,在 annotate之前使用表示 where 条件,在annotate之后使用表示having条件

   - values:在annotate之前使用表示分组字段,在annotate之后使用表示取值

(即:所需分组的字段) 

from django.db import models

# Create your models here.
class schoolClass(models.Model):
    name=models.CharField(max_length=10)
class Teacher(models.Model):
    name=models.CharField(maxt_length=10)
    school_class=models.ManyToManyField(schoolClass)    

(1)查询每个班级有几位老师 

Teacher模块有ManyToManyFiled,则values里面传入属性schoo_class即可

>>> from more_more_app.models import *
>>> teacher=Teacher.objects.values("school_class").annotate(Count("id")) 
>>> teacher
<QuerySet [{'school_class': None, 'id__count': 1}, {'school_class': 1, 'id__count': 1}, {'school_class': 2, 'id__count': 2}, {'school_class': 3, 'id__count': 2}]>

  filter表示where条件可以在annotate之前和之后使用,最好在之前使用,表示先过滤后分组,提      高效率;filter表示having条件必须在annotate之后使用,表示对所需统计数据进行过滤

>>> Teacher.objects.values("school_class").annotate(tcount=Count("id")).filter(name__contains="夏磊") 
<QuerySet [{'school_class': 2, 'tcount': 1}, {'school_class': 3, 'tcount': 1}]>
>>> Teacher.objects.values("school_class").annotate(tcount=Count("id")).filter(tcount__gte=2)  
<QuerySet [{'school_class': 2, 'tcount': 2}, {'school_class': 3, 'tcount': 2}]>

(2)查询每个老师带几个班 

schoolClass模块没有ManyToManyFiled,则values里面传入模块Teacher的小写即可

>>> schoolClass.objects.values("teacher").annotate(Count("id")) 
<QuerySet [{'teacher': 2, 'id__count': 3}, {'teacher': 3, 'id__count': 2}, {'teacher': None, 'id__count': 1}]>

3.修改 

from django.db import models

# Create your models here.
class Question(models.Model):
  question_title=models.CharField(max_length=20,default="")
  question_text = models.CharField(max_length=200)
  pub_date = models.DateTimeField()

(1)修改一条数据

>>> from model_app.models import *
>>> q=Question.objects.first()
>>> q
<Question: Question object (1)>
>>> q.question_text="python is interesting"
>>> q.save()

 (2)修改多条数据

>>> Question.objects.filter(id__in=(1,3)) 
<QuerySet [<Question: Question object (1)>, <Question: Question object (3)>]>
>>> Question.objects.filter(id__in=(1,3)).update(pub_date="2000-12-11") 
2

4.删除

from django.db import models

# Create your models here.
class Question(models.Model):
  question_title=models.CharField(max_length=20,default="")
  question_text = models.CharField(max_length=200)
  pub_date = models.DateTimeField()
>>> Question.objects.get(pk=4).delete()
(1, {'model_app.Question': 1})
​

5.Q对象 

filter() 等方法中的关键字参数查询都是并且('AND')的, 如果你需要执行更复杂的查询(例如or语句),那么可以使用Q 对象。

使用Q对象前需要:from django.db.models import Q

  | , &:或,且运算符

>>> from django.db.models import Q
>>> Question.objects.filter(Q(question_title="java")|Q(question_title="c"))
<QuerySet [<Question: Question object (2)>, <Question: Question object (3)>]>

  ~Q:取反运算符

>>> Question.objects.filter(~Q(question_title="java"))
<QuerySet [<Question: Question object (1)>, <Question: Question object (3)>]>

注意:Q对象可以和一般关键字参数一起使用,但必须在一般关键字参数的前面

6.F对象 

from django.db import models

class Person(models.Model):
    name=models.CharField(max_length=10)
class Group(models.Model):
    name=models.CharField(max_length=10)
    members=models.ManyToManyField(
        Person,
        through="MemberShip",
        through_fields=("group","person")
    )
class MemberShip(models.Model):
    person=models.ForeignKey(Person,on_delete=models.CASCADE)
    group=models.ForeignKey(Group,on_delete=models.CASCADE)
    level=models.IntegerField(default=1)

1.模型的属性名出现在操作符的右边,就使用F对象进行包裹

>>> from django.db.models import *
>>> MemberShip.objects.filter(group_id__gte=F("person_id"))
<QuerySet [<MemberShip: MemberShip object (1)>, <MemberShip: MemberShip object (3)>, <MemberShip: MemberShip object (5)>]>

2.可用于计算

>>> MemberShip.objects.filter(person_id=1).update(level=F("level")+1) 
1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值