2011-04-22 5 views
0

간단한 질문 : 대소 문자를 구분하지 않고 Django에서 일부 필드의 사전 순 정렬을 기반으로 다음 행을 찾는 방법이 있습니까?Django : 여분의 필드에 대한 비교

긴 질문 : 나는 데이터베이스에 몇 가지 단어와 상세한 설명을 가지고 있습니다. 알파벳순으로 단어를 탐색 할 수 있기를 바랍니다. 그래서 알파벳순으로 이전 단어와 다음 단어의 이드를 찾아야합니다. 지금 내가 뭘 다음 (원래 단어의 이름을 저장하는 필드입니다)입니다 :

class Word(models.Model): 
    original = models.CharField(max_length=50) 
    ... 

    def neighbours(self): 
     """ 
     Returns the words adjacent to a given word, in alphabetical order 
     """ 
     previous_words = Word.objects.filter(
      original__lt=self.original).order_by('-original') 
     next_words = Word.objects.filter(
      original__gt=self.original).order_by('original') 
     previous = previous_words[0] if len(previous_words) else None 
     next = next_words[0] if len(next_words) else None 
     return previous, next 

문제는 그렇게 Foo이하지 않은, bar 전에 나타나는이는 대소 문자를 구분 비교를 수행한다는 것입니다 내가 원하는거야. 나는 모든 단어를 나열 곳, 내가

를 추가하려면이

class CaseInsensitiveManager(models.Manager): 

    def get_query_set(self): 
     """ 
     Also adds an extra 'lower' field which is useful for ordering 
     """ 
     return super(CaseInsensitiveManager, self).get_query_set().extra(
      select={'lower': 'lower(original)'}) 

같은 및 Word의 정의에 추가 필드를 추가하는 사용자 정의 모델 관리자의 사용을 만들었습니다 - 또 다른 관점에서이 문제를 방지하려면 내가

Word.alpha.all().order_by('lower') 

같은 쿼리를 수행하고 관계없이 사건의 알파벳 순서에있는 모든 단어를 얻을 수있는이 방법으로

objects = models.Manager() 
alpha = CaseInsensitiveManager() 

. 하지만 하지

class Word(models.Model): 
    original = models.CharField(max_length=50) 
    ... 

    objects = models.Manager() 
    alpha = CaseInsensitiveManager() 

    def neighbours(self): 
     previous_words = Word.objects.filter(
      lower__lt=self.lower()).order_by('-lower') 
     next_words = Word.objects.filter(
      lower__gt=self.lower()).order_by('lower') 
     previous = previous_words[0] if len(previous_words) else None 
     next = next_words[0] if len(next_words) else None 
     return previous, next 

는 사실 장고 extra fields에 따라 field lookups을 허용하지 않습니다 할 수 있습니다. 그래서, 내가해야 할 일은 (커스텀 SQL 작성의 부족) 무엇입니까?

보너스 : 나는 적어도 내가하는 일에 더 많은 문제가 있음을 알고 있습니다. 첫째, 성능에 대해 잘 모르겠습니다. 나는 previous_wordsnext_words을 정의하고 내가 previousnext를 정의 할 때 데이터베이스의 경우에만 조회가 일어날 때 전혀 쿼리가있는 쿼리를 산출 수행하지 않을 것으로 가정 다소

SELECT Word.original, ..., lower(Word.original) AS lower 
WHERE lower < `foo` 
ORDER BY lower DESC 
LIMIT 1 

은이 권리인가 ? 아니면 데이터베이스 속도가 너무 느려지는 무언가를하고 있습니까? Django ORM의 내부 동작에 대한 자세한 내용을 알지 못합니다.

둘째 문제는 실제로 다른 언어로 된 단어에 대처해야한다는 것입니다. 각 단어의 언어를 알고 있다고 가정 할 때 비 ASCII 문자가 있어도 알파벳순으로 가져올 수있는 방법이 있습니까? 예를 들어 méchant, moche 순으로하고 싶지만 moche, méchant이 나옵니다.

답변

1

데이터베이스가이 정렬을 수행 할 수 있어야하며 "하위"기능을 사용하지 않아도 데이터베이스를 정렬 할 수 있어야합니다.

정말로 수정해야 할 것은 데이터베이스 데이터 정렬 및 인코딩입니다. 당신이 MySQL을 사용하는 경우 그 조합이 당신을 위해 작동하지 않는 경우

예를 들어, 당신은

utf8_general_ci 문자 집합 UTF8 및 정렬을 사용할 수 있습니다, 당신은 당신의 필요와 데이터베이스에 따라 다른 정렬을 시도 할 수 있습니다.그러나 쿼리에서 추가 필드와 함수를 사용하는 것은 응용 프로그램을 느리게 진행하는 추악한 해결 방법입니다.

너무 MySQL과 PostgreSQL을 사용할 수 많은 데이터 정렬 옵션이 있습니다

http://dev.mysql.com/doc/refman/5.5/en/charset-mysql.html http://stackoverflow.com/questions/1423378/postgresql-utf8-character-comparison

을하지만 이것은 확실히이다 db 레벨에서 최적화 할 수있는 좋은 기회.

+0

고맙습니다! 프로토 타입 단계에서 SQLite를 사용하고 있었지만 지금 당장 MySQL을 선택해야 할 것입니다. – Andrea

+0

물론 (물론 : sql lite에는 몇 가지 조합 옵션도 있습니다 : http://stackoverflow.com/questions/1188749/how-to-change-the-collation-of-sqlite3-database-to-sort-case - 무감각하게 –

관련 문제