Django 模型

模型

# -*- coding:utf-8 -*-
from django.db import models

class Colors(models.Model):
    colors = models.CharField(max_length=10)
    def __str__(self):
        return self.colors
    
class Ball(models.Model):
    color = models.OneToOneField('Colors')
    description = models.CharField(max_length=10)
    def __str__(self):
        return self.description
    
class Clothes(models.Model):
    color = models.ForeignKey('Colors')
    description = models.CharField(max_length=10)
    def __str__(self):
        return self.description
    
class Child(models.Model):
    name = models.CharField(max_length=10)
    favor = models.ManyToManyField('Colors')

相关概念

  • 一对一:子表从母表中选出一条数据一一对应。
  • 一对多:子表从母表中选出一条数据一一对应,但母表中这条数据还可以被其他子表数据选择。
  • 多对多:关联的两表可以互相选择。

应用场景

  • 一对一:一般用于某张表的补充,比如用户基本信息是一张表,但并非每个用户都需要有登录的权限,不需要记录用户名和密码,此时,合理的做法就是新建一张记录登陆信息的表,与用户信息进行一对一的关联,可以方便的从子表查询母表信息或反向查询。
  • 外键:有很多的应用场景,比如每个员工归属于一个部门,那么就可以让员工表的部门字段和部门表进行一对多关联,可以查询到一个员工归属于哪个部门,也可以反向查询某一部门有哪些员工。
  • 多对多:比如公司服务器可能会有多种用途,归属于多个产品线当中,那么服务器与产品线之间就可以做成多对多,多对多在A表添加ManyToMany字段或者从B表添加,效果一致。

一对一

# 添加一种颜色黑,并添加黑球
color_obj = Colors.objects.create(colors='黑') # 先在母表中创建颜色,并实例化颜色对象
Ball.objects.create(color=color_obj, description='黑球') # 添加黑球信息

备注:增添数据的三种常用方式

# 增添数据的四种写法
# 写法1:
color_obj = Colors.objects.create(colors='黑')
Ball.objects.create(color=color_obj, description='黑球')
# 写法1补充:
color_id = Colors.objects.create(colors='黑').id
Ball.objects.create(color_id=color_id, description='黑球')
# 写法2:
color_obj = Colors.objects.create(colors='黑')
ball_obj = Ball(color=color_obj, description='黑球')
ball_obj.save()
# 写法3(字典导入):
color_obj = Colors.objects.create(colors='黑')
ball_dict = {'description': '黑球'}
Ball.objects.create(color=color_obj, **ball_dict)
# 写法4(多实例列表导入):
ball1 = Ball(color=color_obj1, description='黑')
ball2 = Ball(color=color_obj2, description='白')
ball3 = Ball(color=color_obj3, description='灰')
...
ball_list = [ball1, ball2, ball3...]
Ball.objects.bulk_create(ball_list)

Ball.objects.get(description='灰球').delete() #对象和QuerySet都有方法delete()
Colors.objects.filter(colors='灰').delete()
Colors.objects.all().delete()	#清空一张表

.get()类似于.filter().first()get能够返回model对象,但是只支持严格匹配,如果返回多条对象或者没有找到记录都会抛出异常;filter返回QuerySet对象,支持链式操作。

color_obj = Colors.objects.get(colors='黑')
color_obj.colors = '灰'
color_obj.save()
Ball.objects.filter(description='黑球').update(color=color_obj, description='灰球') #update()是QuerySet的方法

备注:修改数据的常见方式

# 更新一条数据
color_obj = Colors.objects.get(colors='黑')
color_obj.colors = '灰'
color_obj.save()
# 更新多条数据,把满足条件的球的description都变为灰球
# 写法1:
Ball.objects.filter(color__colors='红').update(description='灰球')
# 写法2:
up_dict = {'description': '灰球'}
Ball.objects.filter(id__gt=0).update(**up_dict)

# 子表查询母表,找到红球对应的颜色
# 写法1:
Ball.objects.get(description='红球').color.colors
# 写法2:
Colors.objects.get(ball__description='红球').colors

# 母表查询子表,找到红色对应的球的名字
# 写法1:
Colors.objects.get(colors='红').ball.description
# 写法2:
Ball.objects.get(color__colors='红').description

一对多(外键)

# 外键表联合查询:

# 外键子表查询母表,与一对一子表查询母表形式一致
# 找到红夹克所属的颜色表中的颜色--返回:红
# 写法1:
Clothes.objects.get(description='红夹克').color.colors  #返回红
# 写法2,反向从母表入手:
Colors.objects.get(clothes__description='红夹克').colors

# 外键母表查询子表,与一对一形式不同,因为母表为"多",不能像一对一一样通过.get().子表.子表字段的方式获取,但与多对多母表查询子表一致
# 找到颜色为红的所有服装--返回:[<Clothes: 红T恤>, <Clothes: 红夹克>]
# 写法1:
color_obj = Colors.objects.get(colors='红')
color_obj.clothes_set.all()  #子表小写_set的写法,实际上是一个QuerySet,可以用update,delete,all,filter等方法
# 写法2:
Clothes.objects.filter(color=Colors.objects.get(colors='红'))
# 写法2简便写法(推荐):
Clothes.object.filter(color__colors='红')
# 写法3:
color_id = Colors.objects.get(colors='红').id  #通过母表取得颜色为红的id
Clothes.objects.filter(color_id=color_id)  #写法 filter(子表外键字段_母表主键=母表主键对象)

备注:通过QuerySet的.value()方法,将QuerySet转化为ValueQuerySet

Clothes.objects.filter(color=Colors.objects.get(colors='红')).value('color__colors', 'description')
# 简写形式补充:
Clothes.objects.filter(color__colors='红').values('color__colors', 'description')
# 返回
>>> [{'description': u'\u7ea2\u5185\u8863', 'color__colors': u'\u7ea2'}, {'description': u'\u7ea2\u5185\u88e4', 'color__colors': u'\u7ea2'}]
# 如果不加values(),返回的是[<Clothes: 红T恤>, <Clothes: 红夹克>]这样的QuerySet集合,通过values可以形成一个列表,列表中的每一个元素是一个字典,可以通过list()将ValueQuerySet转化为列表,之后返回给template

# 另外可以通过.values_list()将QuerySet转化为ValuesListQuerySet。返回:[(u'\u7ea2', u'\u7ea2\u889c\u5b50'), (u'\u7ea2', u'\u7ea2\u889c\u5b50')]
#得到的是一个列表,列表中是多个元组,每个元组是ValuesQuerySet中字典的value,常用于从models里将数据取出后动态添加到前端模板中的select选项中。
#通过forms.py从models取值传给前端select选项,需重启django后,select选项才能更新,可在定义form时,添加如下关键字保障动态更新select选项
# forms.py
from django import forms
class ClothesForm(forms.Form):
    color = forms.IntegerField(required=True, widget=forms.Select(),) #定义这个关键字段,当使用form时,colors表新增了颜色,前端ClothesForm的color字段的选项会自动更新
    def __init__(self, *args, **kwargs):
        super(ClothesForm, self).__init__(*args, **kwargs)
        self.fields['color'].widget.choices=Colors.objects.all().order_by('id').values_list('id', 'colors')

# 增添子表数据,形式与一对一一致
# 添加颜色为绿的服装:小绿
# 方法1:
Clothes.objects.create(color=Colors.objects.get(colors='绿'), description='小绿')
# 方法1补充:
Clothes.objects.create(color_id=Colors.objects.get(colors='绿').id, description='小绿')
# 方法2:
c_obj = Clothes(color=Colors.objects.get(colors='绿'), description='小绿')
c_obj.save()
# 方法3、4参考一对一

# 颜色为红的服装,description都更新为红T恤
# 写法1:
Clothes.objects.filter(color__colors='红').update(description='红T恤')
# 写法2:
Clothes.objects.filter(color_id=Colors.objects.get(colors='红').id).update(description='红T恤')
# 写法3:
colors_obj = Colors.objects.get(colors='红')
colors_obj.clothes_set.filter(id__gte=1).update(description='红T恤')
# 其他写法参考一对一的修改和外键的查询

Clothes.objects.get(description='灰裙子').delete()
Clothes.objects.filter(colors='灰').delete()

多对多

# 多对多子表查询母表,查找小明喜欢哪些颜色--返回:[<Colors: 红>, <Colors: 黄>, <Colors: 蓝>]
# 与一对多子表查询母表的形式不同,因为一对多查询的是母表的"一";多对多查询的是母表的"多"
# 写法1:
child_obj = Child.objects.get(name='小明')
child_obj.favor.all()
# 写法2,反向从母表入手:
Colors.objects.filter(child__name='小明')	# 母表对象.filter(子表表名小写__子表字段名='过滤条件')


# 多对多母表查询子表,查找有哪些人喜欢黄色--返回:[<Child: 小明>, <Child: 小红>]
# 与一对多母表查询子表的形式完全一致,因为查到的都是QuerySet,一对多和多对多,都是在查询子表的"多"
# 写法1:
color_obj = Colors.objects.get(colors='黄')
color_obj.child_set.all()
# 写法2:
Child.objects.filter(favor=Colors.objects.get(colors='黄'))
# 写法2简便写法:
Child.objects.filter(favor__colors='黄')
# 写法3:
color_id = Colors.objects.get(colors='黄').id
Child.objects.filter(favor=color_id)

增与改(增添子表或母表数据参照一对一的增,多对多重点在于关系表的对应关系变更)

# 添加子表关联关系
# 添加小虎并让他喜欢所有颜色
# 写法1:
child_obj = Child.objects.create(name='小虎')
colors_obj = Colors.objects.all()
child_obj.favor.add(*colors_obj)
# 写法2:
child_obj = Child.objects.get(name='小虎')
colors_obj = Colors.objects.all()
child_obj.favor = colors_obj
child_obj.save()
# 让小虎喜欢黄色和蓝色(两种写法和上边一致,只展示一种写法)
child_obj = Child.objects.get(name='小虎')
colors_obj = Colors.objects.filter(colors__in=['蓝', '黄'])
child_obj.favor.clear()	# 清空小虎已经喜欢的颜色(清空该对象多对多中间表的所有数据)
child_obj.favor.add(*colors_obj)  # add是追加模式,如果当前小虎已经喜欢了绿色,那么执行后小虎喜欢绿色
child_obj = Child.objects.get(name='小虎')
colors_obj = Colors.objects.get(colors='绿')
child_obj.favor.clear()
child_obj.favor.add(colors_obj) # 单个对象不需要*

# 添加母表关联关系
# 通过反向插入(从母表入手)的写法
child_obj = Child.objects.get(name='小虎')
colors_obj = Colors.objects.get(name='蓝')
colors_obj.child_set.add(child_obj)
# 让所有人都喜欢蓝色
children_obj = Child.objects.all()
colors_obj = Colors.objects.get(colors='蓝')
colors_obj.child_set.add(*children_obj)
# 关于_set写法,只有子表才有"子表名(小写)_set"的写法,得到的是一个QuerySet集合,后面可以接.add(), .remove(), .update(), .delete(), .clear()
# 另外,colors_obj.child_set.clear()是让所有喜欢的颜色里去掉蓝色,colors_obj.child_set.all().delete()是删除.child_set的所有人

# 删除子表与母表关联关系
# 让小虎不喜欢任何颜色
# 写法1:
child_obj = Child.objects.get(name='小虎')
child_obj.favor = ''
child_obj.save()
# 写法2:
child_obj = Child.objects.get(name='小虎')
colors_obj = Colors.objects.all()
child_obj.favor.remove(*colors_obj)
# 写法3:
child_obj = Child.objects.get(name='小虎')
child_obj.favor.clear()

# 删除母表与子表关联关系
# 让所有人不再喜欢蓝色
# 写法1:
children_obj = Child.objects.all()
colors_obj = Colors.objects.get(colors='蓝')
colors_obj.child_set.remove(*children_obj)
# 写法2:
colors_obj = Colors.objects.get(colors='蓝')
colors_obj.child_set.clear()

删除多对多表数据

# 删除子表数据
# 喜欢蓝色的所有人都删掉
colors_obj = Colors.objects.get(colors='蓝')
colors_obj.child_set.all().delete()	# 注意有.all()
# 删除所有child
Child.objects.all().delete()

choice

# choices相当于一个简化版外键,将特定的值相关联
class Child(models.Model):
    gender_choice = (
    	(0, 'Male'),
        (1, 'Female'),
    )
    name = models.CharField(max_length=10)
    favor = models.ManyToManyField('Colors')
    gender = models.IntegerField(choices=gender_choice, default=0)
    
    def __str__(self):
        return self.name
   
# views.py中调用
child_obj = Child.objects.get('小虎')
child_obj.gender	# 返回0或者1
child_obj.get_sex_display()	# 返回Male或者Female
# 对于设置了choices的字段,django提供了get_(字段名)_display()的方法取得所要展示的值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django模型是ORM(Object Relational Mapping)的实现,它允许你通过Python代码来操作数据库,而不必手动编写SQL语句。下面是一些常见的Django模型操作: 1. 定义模型 在models.py文件中,定义一个继承自django.db.models.Model的类作为模型。在该类中定义属性,每个属性都是一个字段,可以是CharField、IntegerField、BooleanField等等。 2. 迁移数据库 运行`python manage.py makemigrations`命令,将模型定义转换为迁移文件。然后运行`python manage.py migrate`命令,将迁移应用到数据库。 3. 创建、查询、更新和删除对象 创建对象的方法是通过模型类的构造函数来实现的,例如`MyModel.objects.create(field1=value1, field2=value2)`。查询对象的方法是通过模型类的Manager对象来实现的,例如`MyModel.objects.filter(field1=value1)`。更新对象的方法是通过查询得到的QuerySet对象调用update函数来实现的,例如`MyModel.objects.filter(field1=value1).update(field2=new_value)`。删除对象的方法是通过查询得到的QuerySet对象调用delete函数来实现的,例如`MyModel.objects.filter(field1=value1).delete()`。 4. 关联查询 在模型中定义外键或多对多关系字段,然后可以使用ORM进行关联查询。例如,如果一个模型有一个外键字段指向另一个模型,那么可以使用`my_model.related_field`来获取该关联对象。 5. 聚合和分组查询 使用ORM可以很方便地进行聚合和分组查询。例如,可以使用`MyModel.objects.aggregate(Sum('field'))`来计算某个字段的总和,使用`MyModel.objects.annotate(count=Count('field')).filter(count__gt=10)`来查询某个字段的值大于10的数据。 以上是Django模型操作的一些基本方法,还有很多高级用法可以去官方文档中了解。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值