Django-05

Day05

学习目标

  • 模型迁移问题
  • 模型一对一
    • 添加
    • 删除
    • 查询
  • 模型一对多
    • 添加
    • 删除
    • 查询
  • 模型多对多
    • 添加
    • 删除
    • 查询

学习课程

1.Model--》DB

Model -> DB
          迁移步骤
              生成迁移文件  python manage.py makemigrations
              执行迁移文件  python manage.py migrate
          迁移文件的生成
              根据models文件生成对应的迁移文件
              根据models和已有迁移文件差别 生成新的迁移文件
          迁移原理  了解
              先去迁移记录查找,哪些文件未迁移过
                  app_label + 迁移文件名字
              执行未迁移的文件
              执行完毕,记录执行过的迁移文件
          可以指定迁移的app  python manage.py makemigrations app
                            python manage.py migrate    
          重新迁移
              删除迁移文件
                  migrations所涉及的迁移文件
              删除迁移文件产生的表
              删除迁移记录
                  django-migrations

2.DB --》 Model

DB -> Model
    反向生成到指定得app下 --》  python manager.py inspectdb > App/models.py
    元信息中包含一个属性  managed=False   不支持迁移
    - 如果自己的模型不想被迁移系统管理,也可以使用 managed=False进行声明

3.模型关系

(1)一对一
应用场景
    用于复杂表的拆分
    扩展新功能
    OneToOneField
    确认主从关系,谁声明关系谁就是从表
    底层实现,使用外键实现的,对外键添加了唯一约束
class Student(models.Model):
    s_name = models.CharField(max_length=32)


class IDCard(models.Model):
    id_num = models.CharField(max_length=18, unique=True)
    id_student = models.OneToOneField(Student, null=True, blank=True, on_delete=models.SET_NULL)
添加
添加主表数据
          def add_student(request):
              s_name = request.GET.get('name')
              student = Student()
              student.s_name = s_name
              student.save()
              return HttpResponse('添加学生成功')
添加从表数据
          def add_idcard(request):
              i_card = request.GET.get('id_num')
              id_card = IdCard()
              id_card.id_num = id_num
              id_card.save()
              return HttpResponse('添加card成功')
数据绑定
          def bind(request):
              student = Student.objects.last()
              idcard = IdCard.objects.last()
              idcard.i_student = student
              # idcard.i_student = student.id
              idcard.save()
              return HttpResponse('绑定成功')
思考:
      student是主表  idcard是从表
      1 再添加一个主表数据  然后执行绑定可不可以  可以
      2 再添加一个从表数据  然后执行绑定可不可以  不可以
删除
主表数据删除/on_delete
                默认  CASECADE
                    默认级联数据被删除
                    从表数据删除,主表不受影响
                    主表数据删除,从表数据直接删除
                models
                    SET_NULL
                        置空
                        前提允许为NULL
                        常用
                    SET_DEFAULT
                        置为默认值
                        前提存在默认值
                    SET
                        自己赋值
                models.PROTECT
                    从表数据受保护的
                    当存在级联数据的时候,删除主表数据,会抛出异常
                    主表不存在级联数据的时候,可以删除
                    开发中为了防止误操作,我们通常会设置为此模式
django默认是级联删除   删除主表的时候 从表数据都会删除
执行顺序是:从表的数据删除之后  主表的数据跟着删除
      def delete_student(request):
          student = Student.objects.get(pk=1)
          student.delete()
          return HttpResponse('删除成功')
def delete_idcard(request):
    idcard = IdCard.objects.get(pk=1)
    idcard.delete()
    return HttpResponse('删除成功')
外键的字段的约束  如果将on_delete修改为models.PROTECT 那么如果有级联关系 删除主表的时候 会抛异常
如果没有级联关系  那么就会直接删除
def deleteprotect_student(request):
    student = Student.objects.get(pk=3)
    student.delete()
    return HttpResponse('删除成功')
外键的字段的约束  如果将on_delete设置为models.setnull  那么如果有级联关系 会将从表的外键设置为null
主表数据也会删除   如果没有级联关系  会直接删除主表数据
def deletesetnull_student(request):
    student = Student.objects.get(pk=4)
    student.delete()
    return HttpResponse('删除成功')
查询
查询/获取
    从获取主
        显性属性
            该显性属性会返回一个对象
    主获取从
        隐性属性
        默认就是从表模型名小写
        该表模型名 会返回一个对象
根据idcard 获取student    显性属性
def get_student(request):
    idcard = IdCard.objects.get(pk=3)
    print(idcard.i_student.s_name)
    return HttpResponse('查询student')
根据student 获取 idcard
def get_idcard(request):
    student = Student.objects.get(pk=2)
    主查从   获得主表的对象之后 该对象 有一个属性 是隐形属性
    这个属性 是外键那个模型的小写
    print(student.idcard.i_card)
    return HttpResponse('查询idcard')
(2)一对多
class Dept(models.Model):
    d_name = models.CharField(max_length=32,unique=True)

class Emp(models.Model):
    e_name = models.CharField(max_length=32)
    #外键默认不能为空
    e_dept = models.ForeignKey(Dept,null=True,blank=True,on_delete=models.SET_NULL)
添加:
外键不能为空
def add_dept(request):
    d_name = request.GET.get('name')
    dept = Dept()
    dept.d_name = d_name
    dept.save()
    return HttpResponse('插入dept成功')
def add_emp(request):
    e_name = request.GET.get('name')
    emp = Emp()
    emp.e_name = e_name
    emp.save()
    return HttpResponse('插入emp成功')
def bind(request):
    dept = Dept.objects.last()
    emp = Emp.objects.last()
    emp.e_dept = dept
    emp.save()
    return HttpResponse('绑定成功')

删除:数据删除同一对一一样

删除主表数据 默认级联从表数据
修改on_delete属性为models.PROTECT
    有级联数据数据 抛异常
    没有级联数据 可以正常删除
修改on_delete=models.SET_NULL
    有级联数据 外键值设置为null
    没有级联数据 直接删除
删除字表数据 不管字表返回得是列表还是单个数据 都可以直接删除  应用场景 多选删除
删除默认是级联删除
def deletedept(request):
    dept = Dept.objects.get(pk=2)
    dept.delete()
    return HttpResponse('删除成功')
删除从表的时候  会将所有符合条件的删除
def deleteemp(request):
    Emp.objects.filter(e_dept_id=1).delete()
    return HttpResponse('删除成功')
def deleteprotectdept(request):
    dept = Dept.objects.get(pk=3)
    dept.delete()
    return HttpResponse('删除成功')
def deletesetnulldept(request):
    dept = Dept.objects.get(pk=1)
    dept.delete()
    return HttpResponse('删除成功')

查询:级联对象获取

从获取主
    显性属性
主获取从
    隐性属性
    默认是 模型小写_set
        该属性得返回值类型是relatedManager类型
        注意relatedManager是一个不可以迭代得对象  所以需要调用Manager得方法
    relatedManager也是Manager的一个子类
        filter
        exclude
        all
        切片
        ...
def finddept(request):
    emp = Emp.objects.get(pk=7)
    print(emp.e_dept)
    return HttpResponse('查询成功')
def findemp(request):
    dept = Dept.objects.get(pk=4)
    一对多的时候 如果通过主查从  那么主的对象调用从的模型小写_set   
    xxx_set方法的返回值类型是RelatedManager
    RelatedManager对象可以调用all  fiter exclude。。。。。。
    emps = dept.emp_set
    for emp in emps.all():
        print(emp.e_name)
    return HttpResponse('查询成功')
(3)多对多
ManyToManyField
产生表的时候会产生单独的关系表
关系表中存储关联表的主键,通过多个外键实现的,多个外键联合唯一
会产生额外的关系表
    表中使用多个外键实现
    外键对应关系表的主键
class Custom(models.Model):
    c_name = models.CharField(max_length=32)

class Goods(models.Model):
    g_name = models.CharField(max_length=32)
    g_custom = models.ManyToManyField(Custom)
添加:
主添加从
    customer.goods_set.add(goods)
        隐性属性
从添加主
    goods.g_customer.add(customer)
        显性属性
需要注意的是:关系表中外键的联合唯一
def addcustom(request):
    custom = Custom()
    custom.c_name = 'zs1'
    custom.save()
    return HttpResponse('添加成功')
    
def addgoods(request):
    goods = Goods()
    goods.g_name = '小当家1'
    goods.save()
    return HttpResponse('添加成功')
从 -- 主   从对象.属性.add(主对象)
首先必须有数据才可以插入 该数据必须是查询出来的
def addgoods1(request):
    custom = Custom.objects.get(pk=1)
    goods = Goods.objects.get(pk=1)
    goods.g_custom.add(custom)
    # goods.save() 没有实际作用
    return HttpResponse('添加成功')
主 -- 从   主对象.从模型名_set.add(从对象)
def addcustom1(request):
    custom = Custom.objects.get(pk=3)
    goods = Goods.objects.get(pk=3)
    custom.goods_set.add(goods)
    return HttpResponse('添加成功')
删除:
goods.g_customer.remove(customer)
    显性属性
custom.goods_set.remove(goods)
    隐性属性
删除主表或者从表的数据,都是级联
删除  eg:删除用户  那么关系表的数据会不会删除
会删除  默认是级联删除   不建议
def deletecustom(request):
    custom = Custom.objects.get(pk=1)
    custom.delete()
    return HttpResponse('删除成功')
删除关系表,不影响主从数据
删除    从 -- 主
def deleterelation(request):
    custom = Custom.objects.get(pk=2)
    goods = Goods.objects.get(pk=2)
    goods.g_custom.remove(custom)
    return HttpResponse('删除成功')
删除关系表,不影响主从数据
删除   主 -- 从
def deleterelation1(request):
    custom = Custom.objects.get(pk=3)
    goods = Goods.objects.get(pk=3)
    custom.goods_set.remove(goods)
    return HttpResponse('删除成功')
查询:
customer.goods_set.all()
从 -- 主  显性属性
def findrelation(request):
    goods = Goods.objects.get(pk=3)
    gs = goods.g_custom.all()
    print(gs)
    return HttpResponse('查询成功')
def findrelation1(request):
    custom = Custom.objects.get(pk=3)
    print(custom.goods_set.all())
    return HttpResponse('查询成功')

www.pythontutor.com/visualize.html#mode=display

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335