Django QuerySet을 목록으로 변환하는 방법


121

다음이 있습니다.

answers = Answer.objects.filter(id__in=[answer.id for answer in answer_set.answers.all()])

그리고 나중에 :

for i in range(len(answers)):
    # iterate through all existing QuestionAnswer objects
    for existing_question_answer in existing_question_answers:
        # if an answer is already associated, remove it from the
        # list of answers to save
        if answers[i].id == existing_question_answer.answer.id:
            answers.remove(answers[i])           # doesn't work
            existing_question_answers.remove(existing_question_answer)

오류가 발생합니다.

'QuerySet' object has no attribute 'remove'

QuerySet을 표준 세트 또는 목록으로 변환하기 위해 모든 종류를 시도했습니다. 아무것도 작동하지 않습니다.

데이터베이스에서 항목을 삭제하지 않고 새 QuerySet을 반환하지 않도록 QuerySet에서 항목을 제거하려면 어떻게해야합니까 (작동하지 않는 루프에 있기 때문에)?

답변:


42

다음과 같이 할 수 있습니다.

import itertools

ids = set(existing_answer.answer.id for existing_answer in existing_question_answers)
answers = itertools.ifilter(lambda x: x.id not in ids, answers)

QuerySet이 평가 될 때 읽고 전체 결과를 메모리에로드하는 것은 좋지 않습니다 (예 :를 통해 list()).

참고: itertools.ifilter

댓글에 대한 업데이트 :

이를 수행하는 방법에는 여러 가지가 있습니다. 하나는 (아마도 기억력과 시간면에서 가장 좋은 것은 아닐 것입니다) 정확히 똑같이하는 것입니다 :

answer_ids = set(answer.id for answer in answers)
existing_question_answers = filter(lambda x: x.answer.id not in answers_id, existing_question_answers)

exising_question_answers에서 동일한 항목을 삭제하여 위의 코드 샘플에 한 줄을 더 추가했습니다. 어떻게 든 ifilter를 사용할 수 있습니까?
john

필터에 대해 몰랐고 람다에 대해 잊었 기 때문에 올바른 것으로 표시하겠습니다.
john

315

왜 그냥 전화 list()Queryset?

answers_list = list(answers)

이것은 또한 QuerySet쿼리를 실행합니다. 그런 다음 해당 목록에서 제거 / 추가 할 수 있습니다.


9
이것에 조심하십시오. 이것을 목록에 캐스팅하면 고유 한 플래그가 무시 될 수 있습니다.
rh0dium

나는 독립적으로 할 수 있지만 django 형식의 queryset에서 할 수 있습니다. 왜 그런지 아세요?
ismailsunni

그렇다면 캐스트했다가 set다시 돌아가서 list고유 한 항목을 얻으십시오.
radtek

36

당신이 정말로하려는 일을 따르는 것은 약간 어렵습니다. 첫 번째 문은 동일한 정확한 QuerySet of Answer 개체를 두 번 가져 오는 것처럼 보입니다. 를 통해 먼저 answer_set.answers.all()다음 다시 통해 .filter(id__in=...). 셸을 다시 확인하고 원하는 답변 목록을 제공하는지 확인하십시오.

answers = answer_set.answers.all()

일단 정리를 마치면 (그리고 코드를 작업하는 다른 사람들이) 좀 더 쉽게 읽을 수 있도록 .exclude ()__in 필드 조회 를 살펴볼 수 있습니다 .

existing_question_answers = QuestionAnswer.objects.filter(...)

new_answers = answers.exclude(question_answer__in=existing_question_answers)

위의 조회는 모델 정의와 동기화되지 않을 수 있지만 작업을 직접 완료 할 수있을만큼 가까이 다가 갈 수 있습니다.

여전히 id 값 목록을 가져와야한다면 .values_list () 를 사용하고 싶을 것 입니다. 귀하의 경우에는 선택 사항 인 flat = True를 추가하고 싶을 것입니다.

answers.values_list('id', flat=True)

답변 해 주셔서 감사합니다. 안타깝게도 귀하의 접근 방식을 사용할 수 없음을 보여주기에 충분한 세부 정보를 제공하지 않았습니다.
john

1
설명 된 문제에 대한 최상의 솔루션입니다. 내가 추가 할 new_answers = answers.exclude(question_answer__in=existing_question_answers.values_list('id', flat=True))@istruble
아쿠아

가장 깨끗한 방법은 flat=True감사합니다 !!!!!!!
Cho

18

단계 매개 변수와 함께 슬라이스 연산자를 사용하여 쿼리 세트를 평가하고 목록을 생성합니다.

list_of_answers = answers[::1]

또는 처음에는 다음을 수행 할 수 있습니다.

answers = Answer.objects.filter(id__in=[answer.id for answer in
        answer_set.answers.all()])[::1]

내가 아는 한 django queryset은 음수 인덱싱을 지원하지 않습니다.
Alexey Sidash

알렉세이. 당신은 바로 여기에 있습니다. 답변을 업데이트했습니다.
Ankit Singh

15

list키워드를 사용하여 직접 변환 할 수 있습니다 . 예를 들면 :

obj=emp.objects.all()
list1=list(obj)

위의 코드를 사용하여 쿼리 세트 결과를 list.

다음 list은 키워드이며 obj쿼리 집합의 list1결과이며 list.


1
그러나 이렇게하면 작동하지 않습니다. list1 = list(emp.objects.all())이는 직관에 반하는 것처럼 보입니다.
geoidesic

4

왜 그냥 전화 .values('reqColumn1','reqColumn2')또는 .values_list('reqColumn1','reqColumn2')의 검색어에?

answers_list = models.objects.values('reqColumn1','reqColumn2')

result = [{'reqColumn1':value1,'reqColumn2':value2}]

또는

answers_list = models.objects.values_list('reqColumn1','reqColumn2')

result = [(value1,value2)]

이 QuerySet에서 모든 작업을 수행 할 수 있습니다.이 작업은 list에 대해 수행합니다.


1
def querySet_to_list(qs):
    """
    this will return python list<dict>
    """
    return [dict(q) for q in qs]

def get_answer_by_something(request):
    ss = Answer.objects.filter(something).values()
    querySet_to_list(ss) # python list return.(json-able)

이 코드는 django queryset을 파이썬 목록으로 변환합니다.


0

이것을 시도하십시오 values_list('column_name', flat=True).

answers = Answer.objects.filter(id__in=[answer.id for answer in answer_set.answers.all()]).values_list('column_name', flat=True)

지정된 열 값이있는 목록을 반환합니다.


0

대신 함수를 remove()사용 exclude()하여 쿼리 세트에서 개체를 제거 할 수 있습니다 . 구문은 다음과 유사합니다.filter()

:-

qs = qs.exclude(id= 1)

위의 코드에서는 ID가 '1'인 qs에서 모든 객체를 제거합니다.

추가 정보 :-

filter()특정 개체를 선택하는 데 사용되지만 exclude()제거하는 데 사용됨

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.