2011-10-06 39 views
15

Tôi làm cách nào để truy vấn tên đầy đủ ở Django?Truy vấn tên đầy đủ ở Django

Để làm rõ, tôi chủ yếu muốn làm tạo ra một cột tạm thời, kết hợp first_name và LAST_NAME để cung cấp cho một fullname, sau đó làm một NHƯ vào đó, như vậy:

select [fields] from Users where CONCAT(first_name, ' ', last_name) LIKE '%John Smith%"; 

Các truy vấn trên sẽ trả lại tất cả người dùng tên là John Smith. Nếu có thể tôi muốn tránh sử dụng một cuộc gọi SQL thô.

Mô hình tôi đang nói đến cụ thể là mô hình người dùng django.contrib.auth.models cổ phiếu. Thay đổi mô hình trực tiếp không phải là vấn đề.

Ví dụ: nếu người dùng tìm kiếm 'John Paul Smith', nó phải khớp với người dùng có tên 'John Paul' và họ 'Smith', cũng như người dùng có tên 'John' và họ 'Paul Smith'.

+0

Vui lòng bao gồm các mô hình Django của bạn. Nếu bạn muốn có một "giá trị dẫn xuất" (như 'CONCAT (first_name, '', last_name)' trong SQL), bạn sẽ phải thêm nó vào mô hình. Do đó, bao gồm mô hình trong câu hỏi của bạn. –

+0

Bạn có biết, BTW, rằng 'CONCAT (first_name, '', last_name) LIKE '% John Smith%" 'là không hiệu quả khủng khiếp? Sử dụng' first_name LIKE'% John 'AND last_name LIKE' Smith% ''có thể hiệu quả hơn Tại sao bạn sử dụng CONCAT khi có những cách không CONCAT để làm điều này? –

+0

Đó là mô hình người dùng django.contrib.auth.models chuẩn. Chúng tôi đã thêm/thay đổi các trường trong mô hình này, vì vậy sửa đổi không phải là –

Trả lời

5

Trừ khi tôi là thiếu một cái gì đó, bạn có thể sử dụng python để truy vấn DB của bạn như vậy:

from django.contrib.auth.models import User 
x = User.objects.filter(first_name='John', last_name='Smith') 

Edit: Để trả lời câu hỏi của bạn:

Nếu bạn cần phải trả lại 'John Paul Smith 'khi người dùng tìm kiếm' John Smith ', sau đó bạn có thể sử dụng' contains 'để dịch thành một THÍCH SQL. Nếu bạn chỉ cần khả năng lưu trữ tên 'John Paul' đặt cả hai tên trong cột first_name.

User.objects.filter(first_name__contains='John', last_name__contains='Smith') 

Điều này được chuyển tới:

SELECT * FROM USERS 
WHERE first_name LIKE'%John%' 
AND last_name LIKE'%Smith%' 
+1

Điều gì sẽ xảy ra nếu truy vấn là "John Paul Smith"? –

+0

Nếu first_name == "John Paul" hoặc last_name == "Paul Smith", nó vẫn sẽ khớp với cách này. – jdi

+0

Điều tôi đang nói, là, nếu người dùng nhập vào John Paul Smith thì sao? –

4
class User(models.Model): 
    first_name = models.CharField(max_length=64) 
    last_name = models.CharField(max_length=64) 
    full_name = models.CharField(max_length=128) 
    def save(self, *args, **kw): 
     self.full_name = '{0} {1}'.format(first_name, last_name) 
     super(User, self).save(*args, **kw) 
9

dễ dàng hơn:

from django.db.models import Q 

def find_user_by_name(query_name): 
    qs = User.objects.all() 
    for term in query_name.split(): 
    qs = qs.filter(Q(first_name__icontains = term) | Q(last_name__icontains = term)) 
    return qs 

đâu QUERY_NAME có thể là "John Smith" (nhưng cũng sẽ lấy người dùng Smith John nếu có).

+0

Tôi đã bắt đầu sử dụng tính năng này và ngay sau khi có nhiều hơn một cụm từ tìm kiếm, thời gian phản hồi http đi từ 100ms đến 5 giây. Bất kỳ ý tưởng tại sao điều này sẽ là? – abarax

+0

Bạn phải xác định đâu là vấn đề đầu tiên. Cơ sở dữ liệu? ORM? Bản mẫu? Thực hiện truy vấn ('print qs.query') trong máy khách sql để xem sự cố có trong db hay không. Nếu không, bằng cách loại trừ (loại bỏ các đoạn mã), hãy thử đoán nếu nó trong mẫu. Nếu không, nó có thể là trên ORM (thử truy vấn trả về ít hàng hơn). Bạn đang đối mặt với một vấn đề ORM N + 1 (sửa nó bằng 'select_related' và' prefetch_related'). Bạn có thể đoán bất cứ điều gì sai bằng cách sử dụng giải thích (mysql/postgres) với các truy vấn (từ một khách hàng sql)? Bạn có bàn lớn không? Nếu vậy, không lập chỉ mục first_name và last_name giảm bớt vấn đề? – laffuste

+0

Cảm ơn các mẹo – abarax

0

gì về điều này:

query = request.GET.get('query') 
users = [] 

try: 
    firstname = query.split(' ')[0] 
    lastname = query.split(' ')[1] 
    users += Users.objects.filter(firstname__icontains=firstname,lastname__icontains=lastname) 
    users += Users.objects.filter(firstname__icontains=lastname,lastname__icontains=firstname) 

users = set(users) 

Cố gắng và thử nghiệm!

Các vấn đề liên quan