A Survey On QuerySet In Django (Part II)
Bài đăng này đã không được cập nhật trong 3 năm
Như các bạn đã biết, với bất kỳ ngôn ngữ lập trình nào, việc truy vấn dữ liệu đều sắm vai trò tối quan trọng. Tất nhiên là trong Django cũng vậy (Django là một web framework trên nền tảng ngôn ngữ Python)
Trong phần I của loạt bài viết này, chúng ta đã đề cập đến một số method cơ bản trong QuerySet như là filter
, include
, exclude
, all
, get
, hay chaining filters
Ở phần II này, chúng ta sẽ xét đến một kỹ thuật filter nâng cao hơn trong QuerySet như là limiting
hay field lookups
Để thuận tiện cho việc minh họa, chúng ta sử dụng một số model với quan hệ như sau:
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __str__(self): # __unicode__ on Python 2
return self.name
class Author(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
def __str__(self): # __unicode__ on Python 2
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
n_comments = models.IntegerField()
n_pingbacks = models.IntegerField()
rating = models.IntegerField()
def __str__(self): # __unicode__ on Python 2
return self.headline
Limiting QuerySets
Để giới hạn số object trả về, ta sử dụng array-slicing:
Ví dụ, để trả lại 5 object đầu tiên của bảng Entry
:
Entry.objects.all()[:5]
Câu lệnh này tương đương với việc sử dụng mệnh đề LIMIT x
trong SQL.
Còn nếu muốn trả về năm object từ thứ 6 đến 10, ta dùng lệnh sau:
Entry.objects.all()[5:10]
Array-slicing ở đây tương đương với mệnh đề OFFSET x LIMIT y
trong SQL
Để lấy ra một object đơn lẻ thay vì một list, ta sử dụng index:
Entry.objects.all()[1000]
Field lookups
Argument của các lookup có dạng field__lookuptype=value
(hai ký tự gạch dưới). Ví dụ:
Entry.objects.filter(pub_date__lte='2006-01-01')
Câu lệnh này tương đương với câu query sau trong SQL:
SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
Chú ý: Nếu keyword argument truyền vào không hợp lệ, ví dụ:
Entry.objects.filter(topicCategory__exact='HaHaHa')
thì exception TypeError
sẽ được raise lên.
Django hỗ trợ hơn 20 lookup, nhưng ở đây, chúng ta chỉ xét đến một số lookup phổ biến sau:
exact
Entry.objects.get(headline__exact="Man bites dog")
Câu lệnh này tương đương với câu query sau:
SELECT * FROM blog_entry WHERE headline = 'Man bites dog';
Một chú ý nhỏ là ở đây, ta có thể lược bỏ lookup exact
, tức là hai câu lệnh sau tương đương:
Blog.objects.get(id__exact=14) # Explicit form
Blog.objects.get(id=14) # __exact is implied
iexact
Giống như exact
nhưng iexact
có tính case-insensitive (không phân biệt chữ cái in hoa hay thường)
Vậy nên, với câu query sau:
Blog.objects.get(name__iexact="beatles blog")
các Blog
có name là "Beatles Blog", "beatles blog" hay "BeAtlES blOG" đều thỏa mãn.
contains
contains
tương với mệnh đề LIKE
trong SQL.
Ví dụ:
Entry.objects.get(headline__contains='Lennon')
tương đương với
SELECT * FROM blog_entry WHERE headline LIKE '%Lennon%';
icontains
Tương tự như iexact
, icontains
có ý nghĩa như contains
nhưng là case-insensitive.
startswith
Entry.objects.filter(headline__startswith='Will')
tương đương với
SELECT * FROM blog_entry WHERE headline LIKE 'Will%';
endswith
Entry.objects.filter(headline__endswith='Khanh')
tương đương với
SELECT * FROM blog_entry WHERE headline LIKE '%Khanh';
istartswith
,iendswith
có ý nghĩa nhưstartswith
,endswith
nhưng là case-insensitive
Lookups that span relationships
Giả sử chúng ta muốn lấy ra tất cả các Entry
thuộc về Blog
có tên là "Beatles Blog", thì thay vì sử dụng một câu query SQL thông thường với các câu mệnh đề JOIN
, ở đây chúng ta dùng lookup như sau:
Entry.objects.filter(blog__name='Beatles Blog')
Ngoài cách tham chiếu xuôi như vậy, lookup còn hỗ trợ tham chiếu ngược.
Ví dụ, câu query sau sẽ lấy ra các Blog
mà tồn tại ít nhất một Entry
thuộc nó có headline
chứa chuỗi "Lennon":
Blog.objects.filter(entry__headline__contains='Lennon')
Chú ý, ở đây các model tham chiếu phải ở dạng lowercase (chữ cái in thường)
Phần II của loạt bài viết về QuerySet trong Django xin được kết thúc ở đây
Hope you enjoy this and thank you all for reading!
BÀI VIẾT ĐƯỢC DỊCH VÀ THAM KHẢO TỪ TÀI LIỆU CHÍNH THỨC CỦA djangoproject:
[1] https://docs.djangoproject.com/en/1.8/topics/db/queries/
[2] https://docs.djangoproject.com/en/1.8/ref/models/querysets/
All rights reserved