django orm

 orm字段及参数

orm字段

1. null
2. default
3. unique
4. db_index

5. DateField和DateTimeField才有的参数:
	auto_now_add=True     --> 创建数据的时候自动把当前时间赋值
	auto_add=True         --> 每次更新数据的时候更新当前时间
	
	上述两个不能同时设置!!!

5. class Meta:
	 db_table = "表名"

  

创建表

索引

联合唯一

class Meta:
        # 建立联合唯一约束
    unique_together = ("author", "book")
View Code

一对一

# 作者
class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    phone = models.IntegerField()
    books = models.ManyToManyField(to="Book", related_name="authors")
    detail = models.OneToOneField(to="AuthorDetail")

    def __str__(self):
        return self.name


# 作者详情
class AuthorDetail(models.Model):
    # 爱好
    hobby = models.CharField(max_length=32)
    # 地址
    addr = models.CharField(max_length=128)
View Code

一对多

使用外键:

class Book(models.Model):
    id=models.AutoField(primary_key=True)
    title=models.CharField(max_length=64,unique=True)
    price = models.DecimalField(max_digits=5, decimal_places=2, default=99.99)
    publisher=models.ForeignKey(
        to="Publisher",
        related_name='books',#用于外键反向查询,代替book__set,添加后book_set将不能用。
        related_query_name="xxoo",#用于双下方法查询
        on_delete=True,
    )

    def __str__(self):
        return "<Book Object:{}>".format(self.title)
View Code

 关联表内字段

class Comment(models.Model):
    """
    评论表
    """
    nid=models.AutoField(primary_key=True)
    article=models.ForeignKey(to="Article",to_field="nid")
    user=models.ForeignKey(to="UserInfo",to_field="nid")
    content=models.CharField(max_length=255)
    create_time=models.DateTimeField(auto_now_add=True)
    parent_comment=models.ForeignKey("self",null=True)
View Code

多对多

方式一:自动生成,第三张表

#
class Book(models.Model):
    id=models.AutoField(primary_key=True)
    title=models.CharField(max_length=64,unique=True)
    price = models.DecimalField(max_digits=5, decimal_places=2, default=99.99)
    publisher=models.ForeignKey(
        to="Publisher",
        related_name='books',#用于外键反向查询,代替book__set,添加后book_set将不能用。
        related_query_name="xxoo",#用于双下方法查询
        on_delete=True,
    )

    def __str__(self):
        return "<Book Object:{}>".format(self.title)

#作者
class Author(models.Model):
    id=models.AutoField(primary_key=True)
    name=models.CharField(max_length=16,unique=True)
    book=models.ManyToManyField(to="Book")
    def __str__(self):
        return "<Author Object:{}>".format(self.name)
View Code

方式二:手动创建第三张表

# 出版社
class Publisher(models.Model):
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)

    def __str__(self):
        return self.name


#
class Book(models.Model):
    title = models.CharField(max_length=32)
    publish_date = models.DateField(auto_now_add=True)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    # 创建外键,关联publish
    publisher = models.ForeignKey(to="Publisher")

    def __str__(self):
        return self.title


# 作者
class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    phone = models.IntegerField()
    books = models.ManyToManyField(to="Book", related_name="authors")
    detail = models.OneToOneField(to="AuthorDetail")

    def __str__(self):
        return self.name


# 作者详情
class AuthorDetail(models.Model):
    # 爱好
    hobby = models.CharField(max_length=32)
    # 地址
    addr = models.CharField(max_length=128)
View Code

方式三:指定关联创建

class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name="书名")


# 自己创建第三张表,并通过ManyToManyField指定关联
class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="作者姓名")
    books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book"))
    # through_fields接受一个2元组('field1','field2'):
    # 其中field1是定义ManyToManyField的模型外键的名(author),field2是关联目标模型(book)的外键名。


class Author2Book(models.Model):
    author = models.ForeignKey(to="Author")
    book = models.ForeignKey(to="Book")

    class Meta:
        unique_together = ("author", "book")
View Code

orm操作

查询

查询示例

model1

from django.db import models

# Create your models here.
'''
图书馆里系统
'''
#出版社
class Publisher(models.Model):
    id=models.AutoField(primary_key=True)
    name=models.CharField(max_length=64,unique=True)
    addr=models.CharField(max_length=128)
    def __str__(self):
        return "<Publisher Object:{}>".format(self.name)

#
class Book(models.Model):
    id=models.AutoField(primary_key=True)
    title=models.CharField(max_length=64,unique=True)
    publish_date = models.DateField(verbose_name='出版日期',auto_now_add=True,null=True,blank=True)
    # 库存数
    kucun = models.IntegerField(default=1000)
    # 卖出数
    maichu = models.IntegerField(default=0)
    price = models.DecimalField(max_digits=5, decimal_places=2, default=99.99)
    publisher=models.ForeignKey(
        to="Publisher",
        related_name='books',#用于外键反向查询,代替book__set,添加后book_set将不能用。
        related_query_name="xxoo",#用于双下方法查询
        on_delete=True,
    )

    def __str__(self):
        return "<Book Object:{}>".format(self.title)

#作者
class Author(models.Model):
    id=models.AutoField(primary_key=True)
    name=models.CharField(max_length=16,unique=True)
    book=models.ManyToManyField(to="Book")
    detail=models.OneToOneField(verbose_name="用户详情",to="AuthorDetail",on_delete=models.CASCADE,null=True,blank=True)
    def __str__(self):
        return "<Author Object:{}>".format(self.name)


class Person(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField(default=18)
    birthday = models.DateField(auto_now_add=True)

    def __str__(self):
        return "<Person Object:{}>".format(self.name)

#作者详情
class AuthorDetail(models.Model):
    hobby=models.CharField(verbose_name='爱好',max_length=32,null=True)
    addr=models.CharField(verbose_name='地址',max_length=128,null=True)

#手动创建第三张表
# class Author2Book(models.Model):
#     id = models.AutoField(primary_key=True)
#     # 作者id
#     author = models.ForeignKey(to="Author")
#     # 书id
#     book = models.ForeignKey(to="Book")
#
#     class Meta:
#         # 建立联合唯一约束
#         unique_together = ("author", "book")
View Code

orm1

"""
ORM小练习

如何在一个Python脚本或文件中 加载Django项目的配置和变量信息
"""
import os
if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dnp.settings')
    import django
    django.setup()
    from app01 import models
    #查询所有
    # ret=models.Person.objects.all()
    # print(ret)
    #get查询(不存在会报错)
    # ret2=models.Person.objects.get(name='李世民1')
    # print(ret2)
    #filter
    # ret3=models.Person.objects.filter(id=1)
    # print(ret3)
    #查询结果只有一个也返回queryset
    # ret4=models.Person.objects.filter(id=1)[0]
    # print(ret4)
    # print("exclude".center(80, "*"))
    # #查询除了id=1的
    # ret5=models.Person.objects.exclude(id=1)
    # print(ret5)
    #只查询指定字段,里面是字典
    # ret6=models.Person.objects.values('name','birthday')
    # print(ret6)
    # 只查询指定字段,里面是元祖
    # ret7=models.Person.objects.values_list('name','birthday')
    # print(ret7)
    #字段排序
    # ret8 = models.Person.objects.order_by('birthday')
    # print(ret8)
    #将有序的Querysset进行反转
    # ret9 = models.Person.objects.order_by('id').reverse()
    # print(ret9)
    #返回queryset中对象的数量
    # ret10=models.Person.objects.count()
    # print(ret10)
    #返回QuerySet中第一个对象
    # ret11=models.Person.objects.first()
    # print(ret11)
    #返回QuerySet中最后一个对象
    # ret12=models.Person.objects.last()
    # print(ret12)
    #判断表中有没有数据
    # ret13=models.Person.objects.exists()
    # print(ret13)
    #


    # 单表查询双下划线
    #查询id大于1小于4的内容
    # r1=models.Person.objects.filter(id__gt=1,id__lt=4)
    # print(r1)
    #查询id在[1,3,5,7]中的结果
    # r2=models.Person.objects.filter(id__in=[1,3,5,7])
    # print(r2)
    #查询id不在[1,3,5,7]中的数据
    # r3 = models.Person.objects.exclude(id__in=[1, 3, 5, 7])
    # print(r3)
    #查询名字中包含李的字段
    # r4=models.Person.objects.filter(name__contains='李')
    # print(r4)
    # # icontains 忽略大小写包含指定值
    # r5=models.Person.objects.filter(name__icontains='C')
    # print(r5)
    # # range
    # # 判断id值在 哪个区间的 SQL语句中的between and  1<= <=3
    # r6=models.Person.objects.filter(id__range=[1,3])
    # print(r6)
    #日期和时间字段查询
    # r7=models.Person.objects.filter(birthday__year='2018')
    # print(r7)
    # r8 = models.Person.objects.filter(birthday__year=2018, birthday__month=10)
    # print(r8)

    #外键查询
    #正向查询
    #基于对象跨表查询
    # book_obj = models.Book.objects.all().first()
    # f1 = book_obj.publisher  # 和我这本书关联的出版社对象
    # print(f1, type(f1))
    # f2=book_obj.publisher.name
    # print(f2)
    #查询id为1的书的出版社
    #使用双下方法进行跨表查询
    # f3=models.Book.objects.filter(id=2).values_list('price','publisher__name')
    # print(f3)
    #反向查询,
    #1.基于对象查询
    #publisher_obj=models.Publisher.objects.get(id=1)
    # f4= publisher_obj.book_set.all()
    # print(f4)
    #配置related_name='books'后book_set将不再可用。
    # f5= publisher_obj.books.all()
    # print(f5)
    #2.基于双下方法
    #添加related_query_name="xxoo",#用于双下方法查询
    # f5=models.Publisher.objects.filter(id=1).values_list('xxoo__title')
    # print(f5)

    #多对多
    # 查询
    # author_obj=models.Author.objects.all().first()
    # print(author_obj)
    # #查看所有书
    # f6=author_obj.book.all()
    # print(f6,type(f6))
    #通过作者添加一本书
    # author_obj = models.Author.objects.all().first()
    # author_obj.book.create(title='明朝那些事',publisher_id=2)
    #add()
    #给id为3的作者添加id为10的一本书,必须使用get()查
    #get获取的是类,filter,获取的是querySet()
    # author_obj=models.Author.objects.get(id=3)
    # book_obj=models.Book.objects.get(id=10)
    # author_obj.book.add(book_obj)
    #添加多个
    # book_objs=models.Book.objects.filter(id__gt=1)
    # print(book_objs)
    # author_obj.book.add(*book_objs)
    #直接添加id
    # author_obj.book.add(9)
    # 删除关联
    #把id为3的作者,的id为10的书取消关联
    # author_obj=models.Author.objects.get(id=3)
    # author_obj.book.remove(10)
    #也可以使用对象
    # book_obj=models.Book.objects.get(id=8)
    # author_obj.book.remove(book_obj)

    #clear
    #清除所有关联
    # author_obj=models.Author.objects.get(id=3)
    # author_obj.book.clear()
    # 使用反向关联
    # 找到id是1的出版社
    # publisher_obj = models.Publisher.objects.get(id=2)
    # publisher_obj.books.clear()

    #聚合
    from django.db.models import Avg,Max,Min,Count,Sum
    #获取所有书的平均价格
    # h1= models.Book.objects.all().aggregate(price_avg=Avg("price"))
    # print(h1)
    #平均,最大,最小价格
    # h2=models.Book.objects.all().aggregate(price_avg=Avg("price"),price_max=Max("price"),price_min=Min("price"))
    # print(h2)

    #分组查询
    #查询每本书对应作者数量
    # h3=models.Book.objects.all().annotate(author_num=Count("author"))
    # print(h3)
    # for book in h3:
    #     print('书名{},作者数量:{}'.format(book.title,book.author_num))

    #查询作者数量大于1的书
    # h4=models.Book.objects.all().annotate(author_num=Count("author")).filter(author_num__gt=1)
    # for book in h4:
    #     print('书名{},作者数量:{}'.format(book.title, book.author_num))
    #查询每个作者出的书的总价格
    # h5=models.Author.objects.all().annotate(price_sum=Sum("book__price")).values_list('name','price_sum')
    # for author in h5:
    #     print(author)
    # h6=models.Author.objects.all().annotate(price_sum=Sum("book__price"))
    # for i in h6:
    #     print(i,i.name,i.price_sum)
    #
    # print(h6.values_list("name","price_sum"))


    #F和Q
    from django.db.models import F
    #查出库存数大于卖出数的所有书】
    # f1=models.Book.objects.filter(kucun__gt=F("maichu"))
    # print(f1)
    # for i in f1:
    #     print(i.title,i.kucun,i.maichu)
        # print('库存{},卖出{}'.format(f1.kucun,f1.maichu))
    #把每一本书的卖出数乘3
    # book_obj=models.Book.objects.first()
    # book_obj.maichu=book_obj.maichu*3
    # book_obj.save()
    #
    # models.Book.objects.update(maichu=(F("maichu")+1)*3)
    #给每一本书名后面加上第一版
    from django.db.models.functions import Concat
    from django.db.models import Value
    # models.Book.objects.update(title=Concat(F("title"),Value("第一版")))
    from django.db.models import Q
    #查询卖出数大于1000,价格小于100的所有书
    # q1=models.Book.objects.filter(maichu__gt=1000,price__lt=100)
    # print(q1)
    #查询卖出数大于1000或价格小于100的所有书
    # q2=models.Book.objects.filter(Q(maichu__gt=1000)|Q(price__lt=100))
    # print(q2)
    #Q查询和字段查询同时存在的,字段查询要放在后面
    # q3=models.Book.objects.filter(Q(maichu__gt=1000)|Q(price__lt=100),title__contains='go')
    # print(q3)

    # Django ORM 事务

    # try:
    #     from django.db import transaction
    #     with transaction.atomic():
    #         # 创建一个出版社
    #         new_publisher = models.Publisher.objects.create(name="火星出版社", addr="火星路")
    #         # 创建一本书
    #         models.Book.objects.create(
    #             title='橘子物语',
    #             price=11.11,
    #             kucun=100,
    #             maichu=10,
    #             publisher_id=1000#指定一个不存在的出版社
    #         )
    # except Exception as e:
    #     print(str(e))


    #没有指定原子操作
    # try:
    #     #创建一个出版社
    #     new_publisher=models.Publisher.objects.create(title="火星出版社",addr="火星路")
    #     #创建一本书
    #     models.Book.objects.create(
    #         title='橘子物语',
    #         price=11.11,
    #         kucun=100,
    #         maichu=10,
    #         publisher_id=1000
    #     )
    # except Exception as e:
    #     print(str(e))



    #执行原生sql
    from django.db import connection
    # cursor=connection.cursor()
    # cursor.execute("select * from app01_book where id=%s",[2])
    # #多条查询
    # # ret=cursor.fetchall()
    # #单条查询
    # ret=cursor.fetchone()
    # print(ret)

    # 在QuerSet查询的基础上自己指定其他的SQL语句(了解即可)
View Code

orm2

import sys,os


if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dnp.settings')
    import django
    django.setup()
    from app01 import models
    #一对一关联
    o1=models.Author.objects.first();
    print(o1.detail.hobby)
    #查询id为2作者关联的书
    # author_obj=models.Author.objects.get(id=2)
    # print(author_obj.book.all())
    #从作者2关联的书中移除id为2的书
    # models.Author.objects.get(id=2).book.remove(2)
    #在app01中,查询,作者id为1,的所有书的id,
    from app02 import models
    # o3=models.Author2Book.objects.filter(author_id=1).values_list('book_id')
    # ret=[i[0] for i in o3]
    # print(ret)
    # o4=models.Book.objects.filter(id__in=ret)
    # print(o4)
    #刪除关联
    # models.Author2Book.objects.get(book_id=1,author_id=1).delete()
View Code

orm3

import sys,os


if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dnp.settings')
    import django
    django.setup()
    from app01 import models
    #查询名字里面包含go的书
    # q1=models.Book.objects.filter(title__contains='go')
    # print(q1)
    #查询2019年出版的书
    # q2=models.Book.objects.filter(publish_date__year=2019)
    # print(q2)
    #去重distinct()
    #查询所有书关联的出版社
    # q3=models.Book.objects.all().values_list("publisher__name")
    # print(q3.distinct())
    #把所有的书按照价格倒序排列
    # q4=models.Book.objects.all().order_by('price').reverse()
    #     # print(q4)
    #支持负号
    # q5=models.Book.objects.all().order_by('-price')
    # print(q5)
    #查询go法典的出版社城市
    # q6=models.Book.objects.filter(title='go法典').values_list("publisher__addr")
    # print(q6)
    #查询go法典作者的爱好
    # q7=models.Book.objects.filter(title='go法典').values_list("author__detail__hobby")
    # print(q7)
    #
View Code

增加

models.UserInfo.objects.create(name="张三")

修改

删除

 del_obj = models.Publisher.objects.get(id=del_id)
        # 删除
        del_obj.delete()

 其他技巧

自定义数据类型

from django.db import models
'''
自定义char字段
'''
class FixedCharField(models.Field):
    """
    自定义的char类型的字段类
    """
    def __init__(self, max_length, *args, **kwargs):
        super().__init__(max_length=max_length, *args, **kwargs)
        self.length = max_length

    def db_type(self, connection):
        """
        限定生成数据库表的字段类型为char,长度为length指定的值
        """
        return 'char(%s)' % self.length
View Code

在python脚本中调用django环境

import os

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

    from app01 import models

    books = models.Book.objects.all()
    print(books)

 在django终端打印sql语句

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

 

原文地址:https://www.cnblogs.com/huay/p/11306873.html