2013-01-20 35 views
6

Tôi có khó khăn bằng cách sử dụng search_fields khi biểu thức tìm kiếm có nhiều lời nói và tôi muốn thực hiện một startswith tìm kiếmdjango tìm kiếm quản trị với nhiều lời

Tôi có một lớp

class Foo(models.Model): 
    kw = models.CharField(max_length = 255) 
    ... 

class FooAdmin(admin.ModelAdmin): 
    search_fields = ('^kw',) 

Các '^' chỉ tôi muốn thực hiện tìm kiếm bắt đầu. Nếu tôi đang tìm kw 'foo fuu', django sẽ thực hiện truy vấn:

select * from app_foo where `foo`.`kw` like 'foo%' and `foo`.`kw` like 'fuu%' 

Truy vấn này rõ ràng không mang lại kết quả nào. Tôi nên làm gì để làm cho động cơ tìm kiếm 'foo fuu%'?

+0

Dường như Django chia các truy vấn trên không gian vì vậy đây có thể không thể làm. Bạn đã xem xét tùy chọn toàn văn với '@' chưa? –

+0

Điều này có thể thay đổi mã thông báo tách không? –

+0

Không phải là tôi biết. Các tài liệu nói: 'Lưu ý rằng đầu vào truy vấn được phân cách bằng dấu cách, vì vậy, theo ví dụ này, hiện tại không thể tìm kiếm tất cả các bản ghi trong đó first_name chính xác là 'john winston' (chứa khoảng trắng). ' –

Trả lời

12

Cách ghi đè self.query để split() không hoạt động?

class UnsplitableUnicode(unicode): 
    "An object that behaves like a unicode string but cannot be split()" 
    def split(self, *args, **kwargs): 
     return [self] 

class MultiWordSearchChangeList(ChangeList): 
    "Changelist that allows searches to contain spaces" 
    def get_query_set(self, request): 
     self.query = UnsplitableUnicode(self.query) 
     return super(MultiWordSearchChangeList, self).get_query_set(request) 

class FooAdmin(admin.ModelAdmin): 
    def get_changelist(self, request, **kwargs): 
     return MultiWordSearchChangeList 
+0

Giải pháp này có vẻ thanh lịch nhưng tôi không thể làm cho nó hoạt động. Bạn đã thử chưa? Tôi không thể nhập vào phương pháp phân chia bị ghi đè và tôi không thể hiểu tại sao –

+0

Cảm ơn, đã cập nhật. Tôi nên được tát cho đăng mã trên SO mà không thử nghiệm nó đầu tiên ... nó đã không làm việc trong '__init__' bởi vì' ChangeList .__ init__' cả hai bộ 'self.query' * và * sử dụng nó. Việc ghi đè nó trong 'get_query_set()' cho phép chúng ta bắt 'self.query' trước khi nó được sử dụng. –

2

Như đã đề cập bởi Thái Trần thì hơi lộn xộn một chút. Đây là phần bạn sẽ phải chỉnh sửa.

from django.contrib import admin 
from django.contrib.admin.views.main import ChangeList 

class CustomChangeList(ChangeList): 
    def get_query_set(self, request): 
     #Basically copy and paste in entire function and edit the piece copied in here. 

     if self.search_fields and self.query: 
      orm_lookups = [construct_search(str(search_field)) 
          for search_field in self.search_fields] 
      for bit in self.query.split(): 
       or_queries = [models.Q(**{orm_lookup: bit}) 
           for orm_lookup in orm_lookups] 
       qs = qs.filter(reduce(operator.or_, or_queries)) 
      if not use_distinct: 
       for search_spec in orm_lookups: 
        if lookup_needs_distinct(self.lookup_opts, search_spec): 
         use_distinct = True 
         break 


class FooAdmin(admin.ModelAdmin): 
    def get_changelist(self, request, **kwargs): 
     return CustomChangeList 

Phát biểu từ trải nghiệm, ghi đè Danh sách thay đổi đã gây ra sự cố trên đường.

+0

Cho đến nay, đó là giải pháp ít nhất nhưng tôi sợ khả năng tương thích sau khi phát hành một phiên bản mới của Django. Nhưng cảm ơn –

+0

Có. Chúng tôi đã overrode một ChangeList vì một lý do nào đó vào năm ngoái và khi 1.4 ra mắt chúng tôi phải tách nó ra ... bài học kinh nghiệm. Nếu chúng tôi buộc phải làm lại, tôi sẽ ghi rõ nó. – Nathaniel

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