2013-01-20 23 views
6

mam kłopoty z wykorzystaniem search_fields gdy wyrażenie wyszukiwania ma wielu słów i chcę wykonać startswith przeszukiwaniedjango z wieloma słowami

Mam klasy

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

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

'^' wskazuje że chcę przeprowadzić wyszukiwanie startswith. Jeśli szukam KW „foo Fuu” Django wykona zapytanie:

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

To zapytanie oczywiście daje zerowe wyniki. Co powinienem zrobić, aby silnik szukał 'foo fuu%'?

+0

Wydaje Django dzieli zapytanie na przestrzeni więc nie może to być możliwe do zrobienia. Czy rozważałeś opcję pełnotekstową z '@'? –

+0

Czy można zmienić token podziału? –

+0

Nie jestem tego świadomy. Dokumenty mówią: "Zauważ, że dane wejściowe zapytania są dzielone spacjami, więc, po tym przykładzie, obecnie nie jest możliwe wyszukiwanie wszystkich rekordów, w których imię_nazw jest dokładnie" john winston "(zawiera spację)." –

Odpowiedz

12

Co powiecie na zastąpienie self.query, więc split() nie działa?

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

To rozwiązanie wydawało się eleganckie, ale nie mogę go uruchomić. Próbowałeś tego? Nie mogę wprowadzić metody dzielenia nadrzędnego i nie rozumiem, dlaczego –

+0

Dzięki, zaktualizowane. Powinienem zostać spolszczony do umieszczania kodu na SO bez testowania go pierwszy ... nie działał w '__init__' ponieważ' ChangeList .__ init__' zarówno ustawia 'self.query' * i * używa go. Przesłonięcie go w 'get_query_set()' pozwala nam złapać 'self.query' zanim zostanie użyte. –

2

Jak wspomniano w Thai Tran, jest to nieco kłopotliwe. Oto sekcja, którą musiałbyś edytować.

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 

Mówiąc z doświadczenia, nadpisanie listy zmian spowodowało problemy na drodze.

+0

Do tej pory jest to najmniej złe rozwiązanie, ale obawiam się, że będzie kompatybilny po wydaniu nowej wersji Django. Ale dzięki –

+0

Tak. Przejęliśmy zmienną zmian z jakiegoś powodu w zeszłym roku, a kiedy wyszło 1.4, musieliśmy ją zgrać ... lekcję nauczyliśmy się. Gdybyśmy musieli to zrobić ponownie, wyraźnie to udokumentowałbym. – Nathaniel

Powiązane problemy