A Survey On QuerySet In Django (Part II)

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

django-body1.jpeg

Để 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/