Django知识碎片整理(四)

碎片一:ORM一对一表

ORM一对一的表是完全可以写在一张表当中的,但是出于部分字段可能被经常调用,而部分字段偶尔调用,所以将一张表拆分开,形成一对一形式的表结构,下面两个表就是一对一关系,两个表的关系是一一对应的

#作者
class Author(models.Model):
    '''作者数据表'''
    id=models.AutoField(primary_key=True)
    name=models.CharField(max_length=50,verbose_name='作者名称',null=False,unique=True)
    book=models.ManyToManyField(to='Book')      #Django自动建立多对多关系表
    detail=models.OneToOneField(to='AuthorDetail')  #建立一对一关系表

    def __str__(self):
        return '{},{},{}'.format(self.id,self.name,self.book)

#作者extends
class AuthorDetail(models.Model):
    '''作者扩展表'''
    id=models.AutoField(primary_key=True)
    #爱好
    hobby=models.CharField(max_length=50,verbose_name='爱好')
    #地址
    addr=models.CharField(max_length=200,verbose_name='地址')
    
    def __str__(self):
        return '{},{},{}'.format(self.id,self.hobby,self.addr)

上面的表,Author中的字段会被经常使用到,而AuthorDetail当中的字段不会经常使用到,所以就拆分成两个表,通过Django的OneToOneField进行一对一关系建立

1、什么时候使用一对一?

当一张表的某一些字段查询的比较频繁,另外一些字段查询的不是特别频繁,把不怎么常用的字段 单独拿出来做成一张表 然后用过一对一关联起来

2、使用一对一的优势:

既保证数据都完整的保存下来,又能保证大部分的检索更快

3、ORM中的用法:OneToOneField(to="")

作者表:

作者详情表:

 4、一对一关系表在Django当中的查询

import os

if __name__=='__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
    import django
    django.setup()

    from bookapp.models import *

    #一对一查询
    author_obj=Author.objects.get(id=1)
    detail_obj=author_obj.detail
    print(detail_obj.hobby,detail_obj.addr)

解析上面代码:

1、首先得到作者的对象author_obj

2、通过author_obj得到对应的作者详情对象detail_obj,然后打印出对象的属性值

篮球 成都

碎片二:ORM建立多对多表结果的三种方式

第一种:通过ManyToMany,ORM自动帮我们创建多对多关系表

在数据库当中会自动生成第三张表

 

第二种:自己手动添加第三张表,利用外键分别关联具有多对多关系的两个表

#书
class Book(models.Model):
    '''书数据表'''
    id=models.AutoField(primary_key=True)
    title=models.CharField(max_length=50,verbose_name='书名',null=False,unique=True)
    price=models.DecimalField(max_digits=5,decimal_places=2,default=99.99)
    kucun=models.IntegerField(default=0)
    maichu=models.IntegerField(default=0)
    publisher=models.ForeignKey(to="Publisher",related_name='books')

    def __str__(self):
        return '{},{},{}'.format(self.id,self.title,self.publisher)

#作者
class Author(models.Model):
    '''作者数据表'''
    id=models.AutoField(primary_key=True)
    name=models.CharField(max_length=50,verbose_name='作者名称',null=False,unique=True)
    detail=models.OneToOneField(to='AuthorDetail',null=True)  #建立一对一关系表

    def __str__(self):
        return '{},{}'.format(self.id,self.name)

#手动创建作者和书多对多关联的第三张表,此时在orm层面没有书和作者的多对多关系
class Author2Book(models.Model):
    '''作者与书籍的多对多关系'''
    id=models.AutoField(primary_key=True)
    #外键author
    author_id=models.ForeignKey(to='Author')
    #外键book
    book_id=models.ForeignKey(to='Book')

    #创建联合唯一,防止重复
    class Meta:
        unique_together=('author_id','book_id')

 引申:如何进行查询?

import os

if __name__=='__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
    import django
    django.setup()

    from app02.models import *

    #1、查找作者id为1的关联的书
    book_obj=Author2Book.objects.filter(author_id=2).values('book_id')
    books=Book.objects.filter(id__in=book_obj)
    print(books)

解析上面的代码:

1、先获取到多对多关联表当中作者id为2的对象

2、直接获取对象当中的book_id的value

3、将获取到的book_id放到Book表进行查询,使用id__in=xxx,查询出对应的书籍对象并打印出来

<QuerySet [<Book: 1,《战狼3》,1,邮电大学出版社,成都市动物园>]>

该方式的缺点是关联查询比较麻烦,因为没办法使用ORM提供的便利方法

第三种:自己创建第三张表,使用ORM 的ManyToManyFiled()

#书
class Book(models.Model):
    '''书数据表'''
    id=models.AutoField(primary_key=True)
    title=models.CharField(max_length=50,verbose_name='书名',null=False,unique=True)
    price=models.DecimalField(max_digits=5,decimal_places=2,default=99.99)
    kucun=models.IntegerField(default=0)
    maichu=models.IntegerField(default=0)
    publisher=models.ForeignKey(to="Publisher",related_name='books')

    def __str__(self):
        return '{},{},{}'.format(self.id,self.title,self.publisher)

#作者
class Author(models.Model):
    '''作者数据表'''
    id=models.AutoField(primary_key=True)
    name=models.CharField(max_length=50,verbose_name='作者名称',null=False,unique=True)
    book=models.ManyToManyField(to='Book',through='Author2Book',through_fields=('author_id','book_id'))   #通过自定义的关联表来建立orm的多对多关系
    detail=models.OneToOneField(to='AuthorDetail',null=True)  #建立一对一关系表

    def __str__(self):
        return '{},{}'.format(self.id,self.name)

#手动创建作者和书多对多关联的第三张表
class Author2Book(models.Model):
    '''作者与书籍的多对多关系'''
    id=models.AutoField(primary_key=True)
    #外键author
    author_id=models.ForeignKey(to='Author')
    #外键book
    book_id=models.ForeignKey(to='Book')

    #创建联合唯一,防止重复
    class Meta:
        unique_together=('author_id','book_id')
book=models.ManyToManyField(to='Book',through='Author2Book',through_fields=('author_id','book_id'))

详细解析上面这个代码:

上面这段代码是在Author表中通过ManyToManyField创建多对多关系,然后through是指通过我们自定义的关系表建立关系,through_fields是指通过哪些字段建立关系,需要注意的是through_fields中字段的位置有顺序的区别,比如Author表可以通过author_id找到的,那么author_id放在最前面,其他表也是这个道理,如果顺序不对,系统会报错

引申:如何进行查询?

import os

if __name__=='__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE','booksys.settings')
    import django
    django.setup()

    from app03.models import *

    #1、查找作者id为1的关联的书
    books=Author.objects.get(id=1).book.all()
    print(books)
<QuerySet [<Book: 1,《战狼3》,1,邮电大学出版社,成都市动物园>, <Book: 2,《春思》,2,北京大学附属中学出版社,成都市动物园>]>

虽然使用了第三张表,但是查询的用法和ORM自动创建的多对多关系的查询用法是一样的

该方式的缺点是没有add()和remove()方法

引申:我们用哪种?

看情况:
1. 如果你第三张表没有额外的字段,就用第一种
2. 如果你第三张表有额外的字段,就用第三种或第一种

碎片三、CSRF的简单用法

1、什么是csrf?

csrf就是跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装成受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

2、钓鱼网站的页面和正经网站的页面对浏览器来说有什么区别? (页面是怎么来的?)
钓鱼网站的页面是由 钓鱼网站的服务端给你返回的
正经网站的网页是由 正经网站的服务端给你返回的

3、Django中内置了一个专门处理csrf问题的中间件
django.middleware.csrf.CsrfViewMiddleware
这个中间件做的事情:
第一是在render返回页面的时候,在页面中塞了一个隐藏的input标签,会有csrf的key和value值,当进行请求时一并提交给服务端,服务端进行校验,看是否是原生的网站发来的请求
用法:
我们在页面上 form表单 里面 写上 {% csrf_token %}
<input type="hidden" name="csrfmiddlewaretoken" value="8gthvLKulM7pqulNl2q3u46v1oEbKG7BSwg6qsHBv4zf0zj0UcbQmpbAdijqyhfE">
第二是当你提交POST数据的时候,它帮你做校验,如果校验不通过就拒绝这次请求

4、{% csrf_token %}一定要加在form表单当中才能生效

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值