天天看點

Python使用Django的自定義查詢方法

作者:你的老師父

Django是一個基于Python的Web架構,它提供了強大的ORM(對象關系映射)系統,可以友善地進行資料庫操作。Django的ORM系統支援多種查詢方式,包括原生SQL查詢、ORM查詢、QuerySet查詢等。其中,自定義查詢是一種非常常見和實用的查詢方式,它允許開發者根據自己的需求,自定義特定的查詢方式,以便更好地滿足業務需求。

自定義查詢是指在Django中,通過編寫特定的查詢函數或方法,實作對資料庫資料的查詢和過濾。自定義查詢函數或方法可以接受各種參數,包括關鍵字參數、位置參數、可變參數和關鍵字可變參數等,以便更靈活地滿足不同的查詢需求。自定義查詢可以用于實作各種複雜的資料查詢和過濾,如分組查詢、聚合查詢、多表聯查等。

用法

Django的自定義查詢功能非常強大和靈活,可以用于各種場景。使用自定義查詢的基本步驟如下:

  1. 建立一個查詢函數或方法,命名通常以get_或filter_等開頭,以便區分系統自帶的查詢函數或方法。
  2. 在查詢函數或方法中,使用Django的QuerySet API對資料庫進行查詢和過濾。QuerySet API提供了豐富的查詢方法,包括filter、exclude、annotate、aggregate等方法,可以滿足各種查詢需求。
  3. 在視圖函數中調用查詢函數或方法,傳遞必要的參數,以擷取查詢結果。

下面是一個簡單的自定義查詢函數的例子:

from django.db.models import Q

def get_articles_by_keyword(keyword):
    return Article.objects.filter(Q(title__icontains=keyword) | Q(content__icontains=keyword))
           

上面的代碼中,我們定義了一個名為get_articles_by_keyword的查詢函數,它接受一個關鍵字參數keyword,用于查詢文章标題和内容中包含關鍵字的文章。在函數中,我們使用了Django的QuerySet API中的filter方法和Q對象,實作了查詢條件的拼接和查詢結果的過濾。

使用步驟

下面是使用自定義查詢的步驟:

  1. 定義一個自定義查詢函數或方法,命名通常以get_或filter_等開頭,以便區分系統自帶的查詢函數或方法。
  2. 在查詢函數或方法中,使用Django的QuerySet API對資料庫進行查詢和過濾。QuerySet API提供了豐富的查詢方法,可以滿足各種查詢需求。
  3. 在視圖函數中調用查詢函數或方法,傳遞必要的參數,以擷取查詢結果。

下面是一個使用自定義查詢的例子:

# models.py

from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=50)
    content = models.TextField()

# utils.py

from django.db.models import Q

def get_articles_by_keyword(keyword):
    return Article.objects.filter(Q(title__icontains=keyword) | Q(content__icontains=keyword))

# views.py

from django.shortcuts import render
from .utils import get_articles_by_keyword

def search(request):
    keyword = request.GET.get('keyword', '')
    articles = get_articles_by_keyword(keyword)
    return render(request, 'search.html', {'articles': articles})
           

上面的代碼中,我們定義了一個名為get_articles_by_keyword的查詢函數,用于查詢文章标題和内容中包含關鍵字的文章。在視圖函數search中,我們調用了查詢函數,并将查詢結果傳遞給模闆渲染,以展示查詢結果。

常用方法代碼示例

Django的QuerySet API提供了豐富的查詢方法,包括filter、exclude、annotate、aggregate等方法,可以滿足各種查詢需求。下面是一些常用的查詢方法的代碼示例:

filter

filter方法用于對查詢結果進行過濾,可以傳遞多個查詢條件,多個條件之間是"與"的關系。下面是一個查詢文章标題中包含關鍵字的文章的例子:

articles = Article.objects.filter(title__icontains='keyword')
           

exclude

exclude方法用于排除滿足指定查詢條件的結果,可以傳遞多個查詢條件,多個條件之間是"與"的關系。下面是一個排除文章标題中包含關鍵字的文章的例子:

articles = Article.objects.exclude(title__icontains='keyword')
           

annotate

annotate方法用于對查詢結果進行注釋,可以添加統計資訊、計算資訊等。下面是一個統計每篇文章的評論數的例子:

from django.db.models import Count

articles = Article.objects.annotate(comment_count=Count('comments'))
           

aggregate

aggregate方法用于對查詢結果進行聚合計算,可以添加聚合函數,如Sum、Avg、Min、Max等。下面是一個統計所有文章的閱讀量的例子:

from django.db.models import Sum

total_views = Article.objects.aggregate(total_views=Sum('views'))
           

一套完整可運作的代碼

下面是一套完整可運作的使用自定義查詢的代碼示例:

models.py

from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=50)
    content = models.TextField()
    views = models.IntegerField(default=0)

class Comment(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='comments')
    content = models.TextField()
           

上面的代碼中,我們定義了兩個模型類Article和Comment,分别表示文章和評論。Article類有三個字段,分别是title、content和views,分别表示文章标題、内容和閱讀量;Comment類有兩個字段,分别是article和content,分别表示評論所屬的文章和評論内容。

utils.py

from django.db.models import Q

def get_articles_by_keyword(keyword):
    return Article.objects.filter(Q(title__icontains=keyword) | Q(content__icontains=keyword))

def get_articles_by_views():
    return Article.objects.order_by('-views')

def get_comments_by_article(article_id):
    return Comment.objects.filter(article_id=article_id)
           

上面的代碼中,我們定義了三個自定義查詢函數,分别表示根據關鍵字查詢文章、按閱讀量排序查詢文章和根據文章ID查詢評論。這些查詢函數都使用了Django的QuerySet API進行查詢和過濾。

views.py

from django.shortcuts import render, get_object_or_404
from .models import Article
from .utils import get_articles_by_keyword, get_articles_by_views, get_comments_by_article

def index(request):
    articles = get_articles_by_views()[:10]
    return render(request, 'index.html', {'articles': articles})

def article_detail(request, article_id):
    article = get_object_or_404(Article, pk=article_id)
    comments = get_comments_by_article(article_id)
    return render(request, 'article_detail.html', {'article': article, 'comments': comments})

def search(request):
    keyword = request.GET.get('keyword', '')
    articles = get_articles_by_keyword(keyword)
    return render(request, 'search.html', {'articles': articles})
           

上面的代碼中,我們定義了三個視圖函數,分别表示展示最熱門的10篇文章、展示文章詳情和展示搜尋結果。這些視圖函數都調用了自定義查詢函數,從資料庫中擷取資料,并将結果傳遞給模闆渲染。

templates/index.html

{% extends 'base.html' %}

{% block content %}
<h1>最熱門的10篇文章</h1>
<ul>
  {% for article in articles %}
  <li><a href="{% url 'article_detail' article.id %}">{{ article.title }}</a></li>
  {% endfor %}
</ul>
{% endblock %}
           

上面的代碼中,我們定義了一個模闆index.html,用于展示最熱門的10篇文章。在模闆中,我們使用了Django的模闆語言,周遊了文章清單,并為每篇文章添加了超連結,以便使用者點選檢視文章詳情。

templates/article_detail.html

{% extends 'base.html' %}

{% block content %}
<h1>{{ article.title }}</h1>
<p>{{ article.content }}</p>
<p>閱讀量:{{ article.views }}</p>
<h2>評論</h2>
<ul>
  {% for comment in comments %}
  <li>{{ comment.content }}</li>
  {% empty %}
  <li>沒有評論</li>
  {% endfor %}
</ul>
{% endblock %}
           

上面的代碼中,我們定義了一個模闆article_detail.html,用于展示文章詳情和評論。在模闆中,我們使用了Django的模闆語言,展示了文章的标題、内容和閱讀量,以及評論清單。

templates/search.html

{% extends 'base.html' %}

{% block content %}
<h1>搜尋結果</h1>
<form method="get" action="{% url 'search' %}">
  <input type="text" name="keyword" value="{{ request.GET.keyword }}">
  <button type="submit">搜尋</button>
</form>
<ul>
  {% for article in articles %}
  <li><a href="{% url 'article_detail' article.id %}">{{ article.title }}</a></li>
  {% empty %}
  <li>沒有比對結果</li>
  {% endfor %}
</ul>
{% endblock %}
           

上面的代碼中,我們定義了一個模闆search.html,用于展示搜尋結果。在模闆中,我們使用了Django的模闆語言,展示了搜尋框和搜尋結果清單,以便使用者檢視搜尋結果。

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('article/<int:article_id>/', views.article_detail, name='article_detail'),
    path('search/', views.search, name='search'),
]
           

上面的代碼中,我們定義了路由規則,将URL路徑與視圖函數對應起來。其中,index路徑對應index視圖函數,用于展示最熱門的10篇文章;article/<int:article_id>/路徑對應article_detail視圖函數,用于展示文章詳情;search路徑對應search視圖函數,用于展示搜尋結果。我們在路由規則中使用了<int:article_id>這樣的URL參數,将文章ID作為參數傳遞給視圖函數。