Python全栈 Web(Django框架、后台管理,ORM关系)

F查询和Q查询:
    F()
        在之执行中获取某字段的值
        F("字段名")
        将所有人的年龄加10
        form django.db.models import F
        Author.objects.all().update(age=F("age")+10)

def doF_views(request):
  Author.objects.all().update(age=F('age')+10)
  return redirect('/07-queryall')

    Q()
        在查询条件中可以完成or操作
        Q(条件)|Q(条件)
        查询所有id为1或年龄为48的人的信息
        form django.db.models import Q
        Author.objects.filter(Q(id=1)|Q(age=48))

  authors = Author.objects.filter(Q(age=30|Q(id__gt=20)))

原生的数据库操作方法:
    查询:
        函数:raw(sql)
            Entry.objects.raw(sql)
            返回值:QuerySet
    增删改:
        from django.db import connection
        with connection.cursor() as cursor
            sql = "delete from ..."
            cursor.execute(sql)
            return ""

def raw_views(request):
  sql = "select * from index_author where age>45"
  authors = Author.objects.raw(sql)
  for au in authors:
    print(au.name,au.age,au.email)
  return HttpResponse("Query OK")

使用后台管理 models
    创建后台管理员
      ./manage.py createsuperuser
        username:输入用户名  如果不写默认为系统名称
        email Address:电子邮件
        Password:密码
        Password(agian):重复密码
    基本管理:
        在应用中的admin.py中注册要管理的数据
        1.admin.py
            注册需管理的models类  只有在此注册的models类才允许被管理
        2.注册models
            from .models import *
            admin.site.register(Entry)
    通过models类的内部类 meta 来定义展现形式
        class Author(models.Model):
            ...
            ...
            class Meta:
                db_table
                    指定实体类映射到表的名字
                    (该属性设置完成后会同步到数据库)
                verbose_name
                    定义实体类在admin中现显示的名字(单数)
                verbose_name_plural
                    定义实体类在admin中显示的名字(复数)

#创建 Author 的实体类
#1.name - 姓名(CharField -> varchar)
#2.age - 年龄(IntegerField -> int)
#3.email - 电子邮件(EmailField -> varchar)
class Author(models.Model):
  name = models.CharField(max_length=30,verbose_name='姓名')
  age = models.IntegerField(verbose_name='年龄')
  email = models.EmailField(null=True,verbose_name='邮件')
  #表示用户的激活状态:True,表示已激活,False,表示未激活
  #由于是新增列,所以必须要给默认值或允许为空
  #由于BooleanField默认是不允许为空的,所以此处选择了增加默认值
  isActive = models.BooleanField(default=True,verbose_name='激活用户')
  #增加一个字段,表示用户的头像,可以上传的
  picture = models.ImageField(upload_to="static/upload",null=True,verbose_name='头像')

  # 重写 __str__ ,来定义该对象的字符串表示
  def __str__(self):
    return self.name

  #增加内部类Meta来定义其展现形式
  class Meta:
    #1.修改表名为author
    db_table = 'author'
    #2.指定后台管理时要显示的名字
    verbose_name = '作者'
    verbose_name_plural = verbose_name
    #3.指定排序规则
    ordering = ['-age']
  def __repr__(self):
    return "<Author:%r>" % self.name

    高级管理:
        在admin.py中创建高级管理类并注册
        定义EntryAdmin 类 继承admin.ModelAdmin
        class AuthorAdmin(admin.ModelAdmin):
            pass
        注册高级管理类
        admin.site.register(Entry, EntryAdmin)

        允许在EntryAdmin中增加属性
        list_display
            定义在列表页上显示的字段们
            取值:
                由属性名组成的元组或列表
        list_display_links
            定义在列表页也能链接到详情页的字段们
            取值:
                同上
                这里的取值必须要出现在list_display中
        list_editable
            定义在列表页中允许被修改的字段们
            取值:
                同上
                必须出现在list_display中 但是不能出现在list_display_links中
        search_fields
            添加允许搜索的字段们
            取值 同上
        list_filter
            列表页的右测增加过滤器  实现快速筛选
        date_hierarchy
            列表页的顶部增加时间选择器
            DateField 或 DateTimeField的列名
        fields
            在详情页中  指定显示那些字段 并按照什么样式的顺序显示
            取值:
                由属性名组成的列表或元组
        fieldsets
            在详情页面中 对字段们进行分组显示的
            fieldsets 与 fields不能共存
            取值:
                fieldsets = [
                    # 分组1
                    ("分组名称", {
                        "fields":("属性1", "属性2")
                        "classes": ("collapse")
                    }),
                    # 分组2
                    (),

                ]

from django.contrib import admin
from .models import *

#声明高级管理类
class AuthorAdmin(admin.ModelAdmin):
  #指定在列表页中显示的字段们
  list_display = ('name','age','email')
  #指定能够连接到详情页的字段们
  list_display_links = ('name','email')
  #指定在列表页中就允许被修改的字段们
  list_editable = ('age',)
  #指定条件的搜索字段们
  search_fields = ('name','email')
  #指定右侧过滤器
  list_filter=('name',)
  #指定显示的字段以及显示的顺序
  # fields = ('name','isActive','email')
  #指定显示的字段分组
  fieldsets = (
    #分组1
    ('基本信息',{
      'fields':('name','email'),
    }),
    #分组2
    ('可选信息',{
      'fields':('age','isActive','picture'),
      'classes':('collapse',),
    })
  )


class BookAdmin(admin.ModelAdmin):
  #指定时间选择器
  date_hierarchy = "publicate_date"


class PublisherAdmin(admin.ModelAdmin):
  list_display = ('name','address','city','website')
  list_editable = ('address','city')
  list_filter = ('address','city')
  search_fields = ('name','website')
  fieldsets = (
    ('基本选项',{
      'fields':('name','address','city'),
    }),
    (
      '高级选项',{
        'fields':('country','website'),
        'classes':('collapse',)
      }
    )
  )


# Register your models here.
# 注册高级管理类
admin.site.register(Author,AuthorAdmin)
admin.site.register(Publisher,PublisherAdmin)
admin.site.register(Book,BookAdmin)
# 注册普通管理类
admin.site.register(Wife)


关系映射:
    一对一的关系映射
        语法:
            在关联的连个类的任何一个中增加
            属性 = models.OneToOneField(Entry)

            class Author(models.Model):
                ....

            class Wife(models.Model);
                ....
                # 增加对Author的一对一引用
                author = models.OneToOneField(Author)
                # 在数据库中生成一个外键列在wife表中  要引用自author 表中的主键
                # 在Author模型中也会增加一个隐式属性叫wife

  #引用Author,实现一对一映射
  author = models.OneToOneField(Author,verbose_name='相公')

        查询:
            正向查询:
                直接通过关联属性就能获取到关联数据
                通过wife找author
                wife = Wife.objects.get(id=1)
                author = wife.author
            反向查询:
                通过反向引用属性查询
                通过author找wife
                author = Author.objects.get(id=1)
                # 反向引用的属性就是模型类的全小写
                wife = author.wife

  #正向查询
  wife = Wife.objects.get(id=1)
  wife_author = wife.author
  #反向查询
  author = Author.objects.get(id=1)
  author_wife = author.wife
  return render(request,'14-oto.html',locals())

    一对多关系映射:
        语法:
            在"多"的模型中对"一"的模型引用
            属性 = models.ForeignKey(Entry)
            class Publisher(models.Model):
                ....

            class Book(models.Model):
                ....

                publisher = modelsForeignKey(Publisher)

  #增加对Publisher的引用(1:M)
  publisher = models.ForeignKey(Publisher,null=True)

        查询:
            正向查询:
                book = Book.objects.get(id=1)
                publisher = book.publisher
            反向查询:
                django 会默认在publisher中增加book_set属性  来表示对应的所有书籍的查询对象
                publisher = Publisher.objects.get(id=1)
                publisher = publisher.book_set.all()


def otm_views(request):
  # 正向查询:通过Book查询Publisher,在15-otm.html中显示每个book对应的publisher
  books = Book.objects.all()
  # 反向查询
  pub = Publisher.objects.get(id=1)
  pub_books = pub.book_set.all()
  return render(request,'15-otm.html',locals())

    多对多关系映射:
        语法:
            在关联地 任意一个类中都可以增加
            属性 = models.ManyToManyField(Entry)
            class Author(models.Model):
                ....

            class Book(models.Model):
                ....

                authors = models.ManyToManyField(Author)

  #增加对Author的引用(M:N)
  authors = models.ManyToManyField(Author)

        查询:
            正向查询;
                通过Book查询Author
                authors 属性只是提供了关联表的查询引用 还需要使用all() values()等方法来获取真实的数据


def mtm_views(request):
  #正向查询:通过 book 查询 authors
  book = Book.objects.get(id=1)
  authors = book.authors.all()
  #反向查询:通过 author 查询 book
  author = Author.objects.get(id=2)
  books = author.book_set.all()
  return render(request,'16-mtm.html',locals())


上一篇:Python全栈 Web(Django框架、forms对象、cookie、session)


下一篇:Python全栈 Web(Django框架、HttpRequest,csrf跨域攻击)