1. 程式人生 > >day53:django:URL別名/反向解析&URL分發&名稱空間&ORM多表操作修改/查詢

day53:django:URL別名/反向解析&URL分發&名稱空間&ORM多表操作修改/查詢

目錄

1.URL別名&反向解析

2.URL分發&名稱空間

3.ORM多表操作-修改

4.ORM多表操作-查詢

  4.1 基於物件的跨表查詢

  4.2 基於雙下劃線的跨表查詢

  4.3 聚合查詢

  4.4 分組查詢

  4.5 F查詢

  4.6 Q查詢

URL別名&反向解析

urls.py的別名寫法

from django.conf.urls import url
from django.contrib import admin

from app01 import views
from app01 import views
'''給URL起別名,在URL後面加name引數'''
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^book/list/', views.book_list, name='book_list'),
    url(r'^book/add/', views.book_add,name='book_add'),
    url(r'^book/edit/(\d+)/', views.book_edit, name='book_edit'), # /book/edit/2/
    url(r'^book/del/(?P<n>\d+)/', views.book_del,name='book_del'), # /book/edit/2/
]

檢視函式部分

from django.urls import reverse

print(reverse('book_list')) #/book/list/
print(reverse('book_edit',args=(2,))) # /book/edit/1/  URL的無名分組引數
print(reverse('book_edit',kwargs={'n': 1,})) # /book/edit/1/  URL的有名分組引數


return redirect('book_list')
'''redirect重定向可以不用寫reverse就可以反向解析,因為redirect方法裡有reverse方法'''
return redirect(reverse('book_list'))

模板部分

<!-- 無引數的  -->
<a class="btn btn-primary" href="{% url 'book_add' %}">新增書籍</a>

<!-- 無名分組引數的 -->
<a href="{% url 'book_edit' books.id 3 4 %}" class="btn btn-warning">編輯</a>

<!-- 有名分組 -->
<!-- 以下兩種方法都可以 -->
<a href="{% url 'book_del' books.id %}" class="btn btn-danger">刪除</a>
<a href="{% url 'book_del' n=books.id %}" class="btn btn-danger">刪除</a>

URL分發&名稱空間

專案主目錄下的urls.py

from django.conf.urls import url, include
from django.contrib import admin

from app01 import views

'''URL分發使用include方法,名稱空間使用namespace屬性'''
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/', include('app01.urls',namespace='app01')),
    url(r'^app02/', include('app02.urls',namespace='app02')),
]

app01/urls.py

from app01 import views

urlpatterns = [
    url(r'^index/', views.index, name='index'),
    url(r'^book/list/', views.book_list, name='book_list'),
    url(r'^book/add/', views.book_add, name='book_add'),
    url(r'^book/edit/(\d+)/', views.book_edit, name='book_edit'), 
    url(r'^book/del/(?P<n>\d+)/', views.book_del, name='book_del'), 
]

app02/urls.py

from app02 import views

urlpatterns = [
    url(r'^index/', views.index, name='index'),
]

app01/views.py

def index(request):
    print(reverse('app01:index'))
    return HttpResponse('app01的路徑:' + reverse('app01:index'))

app02/views.py

def index(requset):
    print(reverse('app02:index'))
    return HttpResponse('app02的路徑: ' + reverse('app02:index'))

ORM多表操作-修改

修改

# 一對一修改和一對多修改
models.Author.objects.filter(name='張三').update(
    name='李四',
    age=50,
    # ad=models.AuthorDetail.objects.get(id=1), 兩種方式都可以
    ad_id=1,
)
# 多對多修改
obj = models.Book.objects.get(id=2)
obj.authors.set(['3',])
'''多對多修改使用set方法 注意:set的值是字串,set的原理是clear+add'''

Tip:檢視和執行原生sql

# 方式1
from django.db import connection
print(connection.queries)

# 方式2
'''settings.py檔案中配置如下內容'''
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}
'''方式1:配置之後,可以使用下面的程式碼執行sql語句'''
cursor = connection.cursor()
cursor.execute('select * from app01_book;')
print(cursor.fetchall())

'''方式2:也可以使用pymysql執行sql語句'''


'''方式3:可以使用objects下的raw方法執行sql語句'''
ret = models.Author.objects.raw('select * from app01_author;')  # 注意:只限於本表操作
print(ret)
for i in ret:
    print(i.name)

ORM多表操作-查詢

基於物件的跨表查詢

正向查詢和反向查詢

正向查詢:A表關聯了B表,關聯屬性在A表,那麼通過A表資料查詢B表中資料時,叫做正向查詢

正向查詢語法:正向查詢使用物件.關聯屬性名稱

反向查詢:反之,叫做反向查詢

反向查詢語法:反向查詢使用物件.關聯模型類名小寫

一對一

'''一對一:正向查詢'''
# 檢視張三作者的家庭住址

# 1.sql語句查詢 select app01_authordetail.addr from app01_author inner join app01_authordetail on app01_author.ad_id app01_atuhordetail.id where app01_author.name='張三' # 2.基於物件的跨表查詢 obj = models.Author.objects.get(name='張三') print(obj.ad.addr) '''一對一:反向查詢''' # 查詢北京的作者名稱 obj = models.AuthorDetail.objects.get(addr='北京') print(obj.author.name) # 反向查詢:物件.表名小寫.屬性

一對多

'''一對多:正向查詢'''
# 查詢西遊記這本書的出版社
obj = models.Book.objects.get(title='西遊記')
print(obj.publishs.name)

'''一對多:反向查詢'''
'''一對多查詢,給一查多,結果有多個:要使用物件.表名_set.all()'''
# 查詢馬哥出版社出版的書籍有哪些
ret = models.Publish.objects.get(name='馬哥出版社')
books = ret.book_set.all()  # <QuerySet [<Book: Book object>, <Book: Book object>]>
print(books.values('title')) # all()查詢的是queryset物件,想得到裡面的具體內容,要用values(欄位)

多對多

'''一對一:正向查詢'''
# 檢視張三作者的家庭住址
# 1.sql語句查詢
select app01_authordetail.addr from app01_author inner join app01_authordetail on app01_author.ad_id app01_atuhordetail.id where app01_author.name='張三'
# 2.基於物件的跨表查詢
obj = models.Author.objects.get(name='張三')
print(obj.ad.addr) 

'''一對一:反向查詢'''
# 查詢北京的作者名稱
obj = models.AuthorDetail.objects.get(addr='北京')
print(obj.author.name) # 反向查詢:物件.表名小寫.屬性
    

'''一對多:正向查詢'''
# 查詢西遊記這本書的出版社
obj = models.Book.objects.get(title='西遊記')
print(obj.publishs.name)

'''一對多:反向查詢'''
'''一對多查詢,給一查多,結果有多個:要使用物件.表名_set.all()'''
# 查詢馬哥出版社出版的書籍有哪些
ret = models.Publish.objects.get(name='馬哥出版社')
books = ret.book_set.all()  # <QuerySet [<Book: Book object>, <Book: Book object>]>
print(books.values('title')) # all()查詢的是queryset物件,想得到裡面的具體內容,要用values(欄位)
    
'''多對多:正向查詢'''
# 查詢西遊記是誰寫的
# 1.sql查詢
select app01_author.name from app01_book inner join app01_book_authors on app01_book.id =
app01_book_authors.book_id inner join app01_author on app01_author.id = app01_book_authors.author_id

# 2.正向查詢
obj = models.Book.objects.get(title='西遊記')
print(obj.authors.all().values('name'))

'''多對多:反向查詢'''
# 查詢張三寫了哪些書
obj = models.Author.objects.get(name='張三')
print(obj.book_set.all().values('title'))    

基於雙下劃線的跨表查詢

# 一對一
# 檢視張三作者的家庭住址
'''正向寫法'''
ret =  models.Author.objects.filter(name='張三').values('ad__addr')
'''反向寫法'''
ret = models.AuthorDetail.objects.filter(author__name='張三').values('addr')
print(ret) # <QuerySet [{'addr': '北京'}]>

# 一對多
# 查詢西遊記這本書的出版社
'''正向寫法'''
ret = models.Book.objects.filter(title='西遊記').values('publishs__name')
print(ret) # <QuerySet [{'publishs__name': '小馬哥出版社'}]>
'''反向寫法'''
ret = models.Publish.objects.filter(book__title='西遊記').values('name')
print(ret) # <QuerySet [{'name': '小馬哥出版社'}]>

# 多對多
# 查詢水滸傳是誰寫的
'''正向寫法'''
ret = models.Book.objects.filter(title='水滸傳').values('authors__name')
print(ret)
'''反向寫法'''
ret = models.Author.objects.filter(book__title='水滸傳').values('name')
print(ret) #<QuerySet [{'name': '王五'}, {'name': '趙六'}]>

聚合查詢

from django.db.models import Avg,Max,Min,Count,Sum
# 聚合查詢
'''聚合查詢使用aggregate()方法'''
ret = models.Book.objects.all().aggregate(Avg('price'))
ret = models.Book.objects.all().aggregate(a=Avg('price'),m=Max('price'))
print(ret,type(ret)) #{'price__avg': 15.0} <class 'dict'>
'''注意結果為字典型別.'''

分組查詢

# 統計一下每個出版社出版書的平均價格
# 1.sql查詢
select publishs_id,avg(price) from app01_book group by publishs_id;
select avg(app01_book.price) from app01_book inner join app01_publish on 
app01_book.publishs_id = app01_publish.id group by app01_publish.name;

# 2.分組查詢
ret = models.Book.objects.values('publishs_id').annotate(a=Avg('price')) # 方式一

ret = models.Publish.objects.annotate(a=Avg('book__price')) # 方式二
# <QuerySet [<Publish: Publish object>, <Publish: Publish object>]>
print(ret.values('a','name'))

F查詢

# 查詢一下點贊數大於評論數的書籍
'''1.傳統方法'''
ret = models.Book.objects.all()
book_list = []
for i in ret:
    if i.dianzan > i.comment:
        book_list.append(i)

'''2.F查詢'''
from django.db.models import F
''''針對本表不同欄位資料進行對比時或者本表字典做一些統一修改時使用F查詢'''
# 點贊數大於評論數的
ret = models.Book.objects.filter(dianzan__gt=F('comment'))

'''F查詢也支援統一修改'''
# 所有書籍上調10塊
models.Book.objects.all().update(price=F('price')+10) # 支援四則運算

Q查詢

from django.db.models import Q
'''
| -- or
& -- and
~ -- not
'''

'''and與和or或'''
ret = models.Book.objects.filter(Q(comment__gt=30)|Q(dianzan__gt=50))

ret = models.Book.objects.filter(Q(comment__gt=30)&Q(dianzan__gt=50))
# 等同於# ret = models.Book.objects.filter(comment__gt=30,dianzan__gt=50)

ret = models.Book.objects.filter(Q(comment__gt=30)|Q(dianzan__gt=50),publishDate__year='2018')
# 注意沒有Q包裹的條件,寫在Q包裹的條件後面.並且Q查詢和publishyear之間是and的關係

'''Q查詢多層巢狀'''
ret = models.Book.objects.filter(Q(Q(comment__gt=30)|Q(dianzan__gt=50))&Q(xx=11),publishDate__year='2018')

'''條件取反:波浪線寫在Q前面'''
# 取評論數小於等於30 的,或者點贊數大於50的
ret = models.Book.objects.filter(~Q(comment__gt=30)|Q(dianzan__gt=50))

&n