课程前期准备

默认数据库配置sqlite

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}

修改为mysql

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': MYSQL_DB_NAME,
'USER': MYSQL_DB_USER,
'PASSWORD': MYSQL_DB_PASSWORD,
'HOST': '127.0.0.1',
'PORT': 3306,
}
}

创建app

startapp <app_label>

下载mysqlclient

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01', # 添加此项
)

  • 创建book类
class Book(models.Model): 
    id = models.AutoField(primary_key=True) # id 会自动创建,可以手动写入
    title = models.CharField(max_length=32) # 书籍名称
    price = models.DecimalField(max_digits=5, decimal_places=2) # 书籍价格
    publish = models.CharField(max_length=32) # 出版社名称
    pub_date = models.DateField() # 出版时间
makemigrations
migrate

配置url

urlpatterns = [
path('add_book/', views.add_book),
]

  • view.py
from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
book = models.Book(title="菜鸟教程",price=300,publish="菜鸟出版社",pub_date="2008-8-8")
book.save()
return HttpResponse("<p>数据添加成功!</p>")

# def add_book(request):
# books = models.Book.objects.create(title="如来神掌",price=200,publish="功夫出版社",pub_date="2010-10-10")
# print(books, type(books)) # Book object (18)
# return HttpResponse("<p>数据添加成功!</p>")

查询

all(), filter, exclude(), get(), order_by(), first(), __contains, __range

  • 使用模型类的 对象.delete()

  • 使用 QuerySet 类型数据.delete()

  • ```
    模型类的对象.属性 = 更改的属性值
    模型类的对象.save()

    * QuerySet 类型数据.update(字段名=更改的数据)

    > `objects` 是该模型的默认管理器。通过这个管理器,你可以执行各种数据库查询操作

    SQL语句

    insert into app02_publish(name,city,email) values (“华山出版社”, “华山”, “[email protected]”), (“明教出版社”, “黑木崖”, “[email protected]”)

先插入 authordetail 表中多数据

insert into app02_authordetail(gender,tel,addr,birthday) values (1,13432335433,”华山”,”1994-5-23”), (1,13943454554,”黑木崖”,”1961-8-13”), (0,13878934322,”黑木崖”,”1996-5-20”)

再将数据插入 author,这样 author 才能找到 authordetail

insert into app02_author(name,age,au_detail_id) values (“令狐冲”,25,1), (“任我行”,58,2), (“任盈盈”,23,3)


多表实例


class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
pub_date = models.DateField()
publish = models.ForeignKey(“Publish”, on_delete=models.CASCADE)
authors = models.ManyToManyField(“Author”)

class Publish(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=64)
email = models.EmailField()

class Author(models.Model):
name = models.CharField(max_length=32)
age = models.SmallIntegerField()
au_detail = models.OneToOneField(“AuthorDetail”, on_delete=models.CASCADE)

class AuthorDetail(models.Model):
gender_choices = (
(0, “女”),
(1, “男”),
(2, “保密”),
)
gender = models.SmallIntegerField(choices=gender_choices)
tel = models.CharField(max_length=32)
addr = models.CharField(max_length=64)
birthday = models.DateField()


![img](https://www.runoob.com/wp-content/uploads/2020/05/Django-orm2_1.png)



表与表直接的关系

![img](https://www.runoob.com/wp-content/uploads/2020/05/orm11.png)

### 一对多


def add_book(request):

#  获取出版社对象
pub_obj = models.Publish.objects.filter(pk=1).first()
#  给书籍的出版社属性publish传出版社对象
book = models.Book.objects.create(title="菜鸟教程", price=200, pub_date="2010-10-10", publish=pub_obj)
print(book, type(book))
return HttpResponse(book)

def add_book(request):

#  获取出版社对象
pub_obj = models.Publish.objects.filter(pk=1).first()
#  获取出版社对象的id
pk = pub_obj.pk
#  给书籍的关联出版社字段 publish_id 传出版社对象的id
book = models.Book.objects.create(title="冲灵剑法", price=100, pub_date="2004-04-04", publish_id=pk)
print(book, type(book))
return HttpResponse(book)

> 小写表名_set

在 Django 中,当你定义一个模型(Model)并创建与之关联的外键或多对多关系(ForeignKey 或 ManyToManyField)时,Django 会自动为你的模型生成一个属性,该属性的命名规则是小写的目标模型名称加上 "_set"。

这个属性允许你在查询中访问与当前模型相关的对象集合。这通常用于反向关联,允许你通过外键或多对多关系查找与当前模型相关的对象。

下面是一个示例,演示如何使用小写的目标模型名称加上 "_set" 访问与当前模型相关的对象集合:

from django.db import models

class Author(models.Model):
name = models.CharField(max_length=100)

class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE)

创建作者和书籍对象

author = Author.objects.create(name=’John Smith’)
book1 = Book.objects.create(title=’Book 1’, author=author)
book2 = Book.objects.create(title=’Book 2’, author=author)

通过 Author 模型的小写名称 + “_set” 访问与作者相关的书籍

books = author.book_set.all()

打印作者的书籍

for book in books:
print(book.title)

输出:

Book 1

Book 2


## 多对多

在 Django 中,多对多(Many-to-Many)关系用于建立模型之间的多对多关联。这意味着一个模型的实例可以与多个另一个模型的实例关联,并反之亦然。多对多关系在许多应用中都很常见,例如,在一个音乐应用中,歌曲可以有多个标签,而标签也可以应用到多首歌曲。

以下是如何在 Django 中定义和使用多对多数据表的基本步骤:

1. **定义模型**:首先,你需要定义两个或更多模型,并在其中一个模型中创建多对多关系字段,通常是 `models.ManyToManyField` 字段。例如,假设我们有两个模型:`Song` 和 `Tag`。

pythonCopy codefrom django.db import models

class Song(models.Model):
title = models.CharField(max_length=100)
tags = models.ManyToManyField(‘Tag’)

class Tag(models.Model):
name = models.CharField(max_length=50)


2. **创建数据**:你可以创建模型实例并将它们相关联,以建立多对多关系。在上述示例中,你可以创建歌曲和标签的实例,并使用多对多关系字段来指定它们之间的关联。


pythonCopy coderock = Tag.objects.create(name=’Rock’)
pop = Tag.objects.create(name=’Pop’)

song1 = Song.objects.create(title=’Song 1’)
song1.tags.add(rock)

song2 = Song.objects.create(title=’Song 2’)
song2.tags.add(rock, pop)


3. **查询数据**:你可以查询多对多关系中的数据,查找特定模型实例的相关对象或反之亦然。


pythonCopy code# 找到具有特定标签的歌曲
rock_songs = Song.objects.filter(tags__name=’Rock’)

找到特定歌曲的标签

song_tags = song1.tags.all()


4. **更新和删除数据**:你可以更新多对多关系,添加或删除关联。例如,你可以为现有的歌曲添加或删除标签。


pythonCopy code# 为歌曲添加标签
song1.tags.add(pop)

为歌曲删除标签

song2.tags.remove(rock)


5. **反向关联**:多对多关系允许反向查找关联数据。例如,你可以查找具有特定标签的所有歌曲。


pythonCopy code# 找到具有特定标签的所有歌曲
rock_songs = rock.song_set.all()

### F() 查询

F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

之前构造的过滤器都只是将字段值与某个常量做比较,如果想要对两个字段的值做比较,就需要用到 F()。

使用前要先从 django.db.models 引入 F:

``` python
from django.db.models import F

用法:

F(“字段名称”)

F 动态获取对象字段的值,可以进行运算。

Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取余的操作。

修改操作(update)也可以使用 F() 函数。

res = models.Book.objects.update(price=F("price")+100)
print(res)

Q() 查询

使用前要先从 django.db.models 引入 Q:

from django.db.models import Q

用法:

Q(条件判断)

例如:

Q(title__startswith=”菜”)

之前构造的过滤器里的多个条件的关系都是 and,如果需要执行更复杂的查询(例如 or 语句),就可以使用 Q 。

Q 对象可以使用 & | ~ (与 或 非)操作符进行组合。

优先级从高到低:~ & |。

可以混合使用 Q 对象和关键字参数,Q 对象和关键字参数是用”and”拼在一起的(即将逗号看成 and ),但是 Q 对象必须位于所有关键字参数的前面。

res=models.Book.objects.filter(Q(price__gt=350)|Q(title__startswith="菜")).values("title","price")
print(res)

附加

class Meta:
db_table = 'book' # 命名
verbose_name = '图书' # 模型别名
verbose_name_plural = '图书列表' # 模型的复数形式别名

抽象类模型(Abstract Base Class)

  • 抽象类模型是一种不会被数据库创建的模型。它不会生成数据库表,而仅用于继承。
  • 用于将共享的字段和方法封装在一个基类中,以供多个子类模型继承和重用。
  • 抽象类模型通常包含一些通用的字段和方法,可以在多个模型中共享。
  • 不能直接使用抽象类模型创建数据库记录,只能通过子类模型创建记录。

示例:

pythonCopy codefrom django.db import models

class BaseModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Meta:
abstract = True # 将模型设置为抽象类

class Post(BaseModel):
title = models.CharField(max_length=100)
content = models.TextField()

class Comment(BaseModel):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
text = models.TextField()

代理类模型(Proxy Model)

  • 代理类模型是一个已存在模型的代理,它可以被用来扩展或修改现有模型的行为,而不需要修改原始模型。
  • 代理类模型基于现有模型创建,因此它与原始模型共享相同的数据库表。
  • 代理类模型可以用于添加新方法、属性或定制查询,而不会对数据库结构产生影响。

示例:

pythonCopy codefrom django.db import models

class MyModel(models.Model):
name = models.CharField(max_length=100)
value = models.IntegerField()

class MyModelProxy(MyModel):
class Meta:
proxy = True

def double_value(self):
return self.value * 2