Django学习5

多表相关操作

三种关系 : 一对一 , 一对多 , 多对多

创建表

一对一:
	xx = models.OneToOneField(to='表名',to_field='字段名',on_delete=models.CASCADE)	# 级联删除,# to_field可以不写,默认是关联到另一张表的主键
一对多:
    xx = models.ForeignKey(to='表名',to_field='字段名',on_delete=models.CASCADE)
多对多:
    xx = models.ManyToManyField(to='表名',)	# 自动创建第三张表

示例:
# 作者 <-一对一-> 作者信息
# 出版社 <-一对多-> 书籍  (外键加在多的表里面)
# 书籍 <-多对多-> 作者

# 作者表
class Author(models.Model): #比较常用的信息放到这个表里面
    # nid = models.AutoField(primary_key=True)		# id可以不写,默认会加上并设为主键
    name=models.CharField( max_length=32)
    age=models.IntegerField()
    authorDetail=models.OneToOneField(to="AuthorDetail",on_delete=models.CASCADE)   # 一对一 
    def __str__(self):
        return self.name

# 作者详细信息表(不常用的信息分到另一张表)
class AuthorDetail(models.Model):#不常用的放到这个表里面
    # nid = models.AutoField(primary_key=True)
    birthday=models.DateField()
    # telephone = models.BigIntegerField()
    telephone=models.CharField(max_length=32)   # 方便后面模糊查询
    addr=models.CharField( max_length=64)
    def __str__(self):
        return self.addr

# 出版社表
class Publish(models.Model):
    # nid = models.AutoField(primary_key=True)
    name=models.CharField( max_length=32)
    city=models.CharField( max_length=32)
    email=models.EmailField()   # 实际上是CharField -- 数据字段验证,可以帮我们校验保存进来的数据是否为email格式的
    def __str__(self):
        return self.name

# 书籍表
class Book(models.Model):
    # nid = models.AutoField(primary_key=True)
    title = models.CharField( max_length=32)
    publishDate=models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2)

    publishs=models.ForeignKey(to="Publish",on_delete=models.CASCADE)
    authors=models.ManyToManyField(to='Author',)    # authors这个属性自动创建第三张表,建立多对多关系 不会生成字段
    def __str__(self):
        return self.title

# 手动创建第三张表,连接书籍和作者多对多的关系(在orm中不方便使用,除非第三张表有自己独立的字段)
# class BookToAuthor(models.Model):
#     book_id = models.ForeignKey(to='Book')
#     author_id = models.ForeignKey(to='Author')

增删改查

# 1.增
# 1.1 一对一添加(作者表和作者信息表)
new_author_detail = models.AuthorDetail.objects.create(
    birthday='1979-08-08',
    telephone='13838383838',
    addr='黑龙江哈尔滨'
)
obj = models.AuthorDetail.objects.filter(addr='山西临汾').first()
# 方式一
models.Author.objects.create(
    name='王涛',
    age=40,
    authorDetail=new_author_detail    # 放model对象 obj
)
# 方式二(常用)
models.Author.objects.create(
    name='文洋',
    age=41,
    authorDetail_id=obj.id     # 放 mysql字段名称
)

# 1.2 一对多添加(书籍表和出版社表)
# 方式一
obj = models.Publish.objects.get(id=2)
models.Book.objects.create(
    title='小李的床头故事',
    publishDate='2019-07-22',
    price=3,
    # publishs=models.Publish.objects.get(id=1),  # model对象
    publishs=obj,    # model对象
)
# 方式二(常用)
models.Book.objects.create(
    title='小李的床头故事2',
    publishDate='2019-07-21',
    price=3.5,
    publishs_id=obj.id,  # mysql字段
)

# 1.3 多对多添加(作者表和书籍表)
# 方式一(常用)
book_obj = models.Book.objects.get(id=1)  # 找到书籍
book_obj.authors.add(*[1,2])    # 找到第三张表并直接添加作者id,多个值用*[,]
# 方式二
author1 = models.Author.objects.get(id=1)  # 先找到2个作者
author2 = models.Author.objects.get(id=3)
book_obj = models.Book.objects.get(id=5)  # 找到书籍

book_obj.authors.add(*[author1,author2])

一对一和一对多的删除和单表删除操作一样
# 一对一
    models.AuthorDetail.objects.get(addr='山西运城').delete()
    # 作者信息表删除信息,对应的作者也被级联删除了...
    models.Author.objects.get(id=3).delete()
    # 作者表删除信息,对应的作者信息不受影响!
    # 通俗点就是: 我和你关联,你不能随便删,会影响我.但我可以随便删,我不影响你(追星??)

# 一对多(书籍表和出版社表)
    models.Publish.objects.get(id=1).delete()
    # 出版社表删除信息,对应出版的书也会一同删除
    models.Book.objects.get(id=1).delete()
    # 书籍表删除信息,对应的出版社不受影响
    
# 多对多(书籍表和作者表)
    book_obj = models.Book.objects.get(id=6)
    # book_obj.authors.remove(*[4,])
    book_obj.authors.remove(*[4,6])
    
    book_obj.authors.clear()	# clear清空,全删的时候用
    book_obj.authors.set('1')   # 清空原来的记录,并重新添加(字符串)
    book_obj.authors.set(['4','6'])

# 更新
# 一对一
    models.Author.objects.filter(id=6).update(
    name='崔老师',
    age=16,
    # authorDetail=models.AuthorDetail.objects.get(id=6)
    authorDetail_id=4
    )
# 一对多
    models.Book.objects.filter(id=4).update(
        # publishs=models.Publish.objects.get(id=3)
        publishs_id=2
    )
# 多对多
	上面删除的set方法

# orm似乎没有级联更新的方法...
models.Publish.objects.filter(id=2).update( 
        id=4		# 报错!
    )

零碎知识点

外部文件操作django的models:
    # 外部文件使用django的models,需要配置django环境
    import os
    if __name__ == '__main__':
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "singletablehw.settings")
        import django
        django.setup()

        from app01 import models
        .......


时区问题:
    settings.py
    USE_TZ = False


form表单中:
    novalidate   去除浏览器帮忙做的事


python后端的url别名反向解析:
    urls.py:
        url(r'^lib/', views.lib, name='lib'), 
        url(r'^add_book/', views.add_book, name='add_book'),
    views.py:
        from django.urls import reverse     # 做urls别名反向解析的
        def add_book(request):
            ......
            # return redirect(reverse('lib'))
            return redirect('lib')	# redirect里用别名解析不用写reverse,直接写别名	不带参数的
        	
            print(reverse('delete_book',arg=(71,)))  # /delete_book/71/  带参数的

前端html模板语法中的url别名反向解析:
	<a href="{% url 'add_book' %}" class="btn btn-primary">添加书籍</a>		# 无参数的
    <a href="{% url 'edit_book' obj.id %}" class="btn btn-warning btn-sm">编辑</a>	# 有参数的


查看mysql当前会话是否为严格模式
      select @@sql_mode;
查看全局
      select @@global.sql_mode;


使用django提供的admin:
    1.执行manage.py createsuperuser指令,创建超级管理员
    2.admin.py文件中注册要管理的表
        from app01 import models
        admin.site.register(models.Author)
        admin.site.register(models.AuthorDetail)
        admin.site.register(models.Publish)
        admin.site.register(models.Book)
    3.执行django项目,访问/admin/
      

主键简写 --- pk
(假设id为主键)  id=4 --- pk=4
    
原文地址:https://www.cnblogs.com/straightup/p/13437069.html