你們都知道,原生的SQL爲咱們提供了分組以後查找組內數據的辦法:GROUP_CONCAT方法;可是對於用Django開發的程序員來講~Django自帶的ORM並無內置這樣功能的方法,而每一次遇到這樣的需求若是都要用原生SQL去解決的話勢必會下降咱們的開發效率。java
本文爲你們介紹一種在Django項目中自定義類Coucat類的方式去實現對應的效果。python
如今假設咱們的Django項目的book應用中有兩張關聯的表:book表與publish表。表結構以下:linux
book表:程序員
publish表:express
其中:book表的publisher_id是經過ORM語法與publish表創建關聯的外鍵字段。django
按照publisher_id分組查詢每組數據下的書名:ruby
select group_concat(title),publisher_id from book_book GROUP BY(publisher_id);
結果以下:函數
查找每一個出版社出版的書籍的名稱測試
select group_concat(book_book.title),book_publish.name from book_book inner join book_publish on book_book.publisher_id = book_publish.id group by book_publish.name;
結果以下:url
在咱們Django項目中的lib目錄下新建一個concat.py文件,文件中的內容以下:
# -*- coding:utf-8 -*- from django.db.models import Aggregate,CharField class Concat(Aggregate): function = 'GROUP_CONCAT' template = '%(function)s(%(distinct)s%(expressions)s)' def __init__(self,expression,distinct=False,**extra): super(Concat,self).__init__( expression, distinct='DISTINCT' if distinct else '', output_field=CharField(), **extra)
以上的代碼就是咱們實現COUCAT_GROUP效果的類。
而後,建立一條測試路由:
url(r'^concat/',views.concat),
視圖函數中concat函數實現具體的功能:
from django.shortcuts import HttpResponse from lib.concat import Concat def concat(request): # 單表:用publisher_id分組,找每一個分組中的書籍名稱 ret = Book.objects.values('publisher_id').annotate(titles=Concat('title')) print(ret) #<QuerySet [{'publisher_id': 21, 'titles': 'linux,cpp,lsi'}, {'publisher_id': 22, 'titles': 'ruby,c'}, # {'publisher_id': 23, 'titles': 'go,xsd'}, {'publisher_id': 24, 'titles': 'java'}, {'publisher_id': 25, 'titles': 'python,rsb'}]> #跨表:每一個出版社出版的全部的書籍 #方法一:以publish表爲基準去查 ret = Publish.objects.values('name').annotate(titles=Concat('book__title')) print(ret) #<QuerySet [{'name': '櫻桃出版社', 'titles': 'go,xsd'}, {'name': '橘子出版社', 'titles': 'ruby,c'}, # {'name': '橙子出版社', 'titles': 'python,rsb'}, {'name': '蘋果出版社', 'titles': 'linux,cpp,lsi'}, {'name': '西瓜出版社', 'titles': 'java'}]> #方法二:以book表爲基準去查 ret = Book.objects.values('publisher__name').annotate(titles=Concat('title')) print(ret) #<QuerySet [{'publisher__name': '櫻桃出版社', 'titles': 'go,xsd'}, {'publisher__name': '橘子出版社', 'titles': 'ruby,c'}, # {'publisher__name': '橙子出版社', 'titles': 'python,rsb'}, {'publisher__name': '蘋果出版社', 'titles': 'linux,cpp,lsi'}, # {'publisher__name': '西瓜出版社', 'titles': 'java'}]> return HttpResponse('Concat')
你們能夠看到,用法也十分簡單,只須要在分組的annotate方法中加上咱們定義的這個類就能夠了~