2009-06-11 2 views
13

저는 40,000 개의 행으로 이루어진 모델의 ForeignKey 값인 하나의 필드를 가진 modelform을가집니다. 기본 modelform은 40,000 개 옵션을 가진 선택 상자를 만들려고하는데, 가장 이상적이지는 않습니다. 이 modelform이 formset 팩토리에서 사용될 때 더욱 그렇습니다!raw_id_fields for modelform

관리자의 경우 "raw_id_fields"을 사용하면 쉽게 피할 수 있지만 동일한 모델 양식은없는 것 같습니다. 어떻게해야합니까?

class OpBaseForm(ModelForm): 

    base = forms.CharField() 

    class Meta: 
     model = OpBase 
     exclude = ['operation', 'routes'] 
     extra = 0 
     raw_id_fields = ('base',) #does nothing 

첫 번째 굵은 선이 거대한 다루기 힘든 선택 박스를 생성하지 않음으로써 작동하지만이 양식의 필드 셋을 저장하려고하면 다음과 같은 에러가 발생합니다 : "OpBase

여기 내 modelform입니다. base "는"Base "인스턴스 여야합니다. modelform을 저장하려면 'base'가 Base 인스턴스 여야합니다. 분명히 기본 기본 키의 문자열 표현으로는 충분하지 않습니다 (적어도 자동으로는 안됨). 내 양식에 주어진 문자열을 Base 인스턴스로 변경하는 메커니즘이 필요합니다. 그리고이 메커니즘은 formset에서 작동해야합니다. 어떤 아이디어? raw_id_fields 만 작동하면 케이크처럼 쉬울 것입니다. 하지만 내가 말할 수있는 한, 그것은 관리자 만이 사용할 수 있습니다.

답변

10

필드 유형이 아닌 base 필드의 경우 위젯을 변경해야합니다. 나는이 일 것이라고 생각 :

class OpBaseForm(ModelForm): 
    base = forms.ModelChoiceField(queryset=Base.objects.all(), 
            widget=forms.TextInput) 

    class Meta: 
     model = OpBase 
     ... etc... 
+1

명확히하기 위해 raw_id_field 속성은 ModelAdmin 속성입니다. http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.raw_id_fields ModelForm 속성이 아닙니다. –

13

당신은 또한 관리자 페이지가 가지고있는 편리한 JS 팝업 검색 완료 전체 raw_id_field 관리 위젯을 사용할 수 있습니다. 모델 양식조차 필요하지 않습니다.

from django.contrib import admin 
admin.autodiscover() 

from django.contrib.admin.widgets import ForeignKeyRawIdWidget 
from django import forms 

from .models import Post, Photo 

class PostForm(forms.ModelForm): 
    photo = forms.ModelChoiceField(
     Photo.objects.all(), 
     widget=ForeignKeyRawIdWidget(Post._meta.get_field("photo").rel,admin.site) 
    ) 

그리고 :

import string 
from django.contrib.admin.widgets import ForeignKeyRawIdWidget 
from django import forms 
from models import MyModel 

# Have to subclass widget b/c 
# django hardcodes a relative path to Admin Root URL: ../../.. 
class HardcodedURLForeignKeyRawIdWidget(ForeignKeyRawIdWidget): 
    def render(self, *args, **kwargs): 
     original_render = super(HardcodedURLForeignKeyRawIdWidget, 
      self).render(*args, **kwargs) 
     ADMIN_ROOT_URL = "/admin/" 
     return string.replace(original_render,"../../../", ADMIN_ROOT_URL) 


class FieldLookupForm(forms.Form): 
    my_foreignkey_field = forms.CharField(max_length=10, 
     widget=HardcodedURLForeignKeyRawIdWidget(
      MyModel._meta.get_field("foreignkey_field").rel)) 

가 장고 1.4 솔루션은 위의 볼테르의 발언을 확장하려면

{% block header %} 
<script type="text/javascript">window.__admin_media_prefix__ = "/static/admin/";</script> 
<script type="text/javascript" src="/admin/jsi18n/"></script> 
<script type="text/javascript" src="/static/admin/js/core.js"></script> 
<script type="text/javascript" src="/static/admin/js/admin/RelatedObjectLookups.js"></script> 
<script type="text/javascript" src="/static/admin/js/jquery.min.js"></script> 
<script type="text/javascript" src="/static/admin/js/jquery.init.js"></script> 
<script type="text/javascript" src="/static/admin/js/actions.min.js"></script> 
{% endblock %} 
+1

Django 1.4에서는 ForeignKeyRawIdWidget의 생성자가 변경된 것처럼 보입니다.이 코드를 사용하면 __init를 던져 버리기 때문에 __()은 정확히 3 개의 인수 (2 개)를 사용합니다. django.contrib.admin을 가져온 경우 admin.site를 누락 된 인수로 ForeignKeyRawIdWidget에 직접 전달할 수 있으며 HardcodedUrl 버전으로 감쌀 필요가 없습니다. – Voltaire

+0

이 작업을하려면'admin.autodiscover()'해야합니다. 조금 더 누락 된 부분이 있으므로 대답에이 글을 쓰고 있습니다. – chriscauley

+0

관리자로 리디렉션하지 않으려면 어떻게해야합니까? – thumbtackthief

12

을 템플릿에 관련 관리자 JS를 추가하고 비올라 방법은 다음과 같습니다 : 추가로 필요한 javascript는 다음과 같습니다.

<script type="text/javascript" src="/static/admin/js/admin/RelatedObjectLookups.js"></script> 

여기서 중요한 점은 관리자가 Autodiscover를 호출한다는 것입니다. 그렇지 않으면 RawIdWidget에 링크가 없습니다. 또한 ModelChoiceField에는 실제로 사용되지 않는 쿼리 세트가 필요합니다. CharField가 제대로 유효성을 검사하지 않기 때문에 ModelChoiceField가 CharField보다 바람직합니다 (Photo 인스턴스를 찾는 대신 ID를 저장하려고 시도 함).

+0

admin 사이트로 리디렉션하지 않고이 작업을 수행 할 수있는 방법이 있습니까? 이상적으로 jquery 자동 완성 기능과 같은 것? – thumbtackthief