동적 선택 필드 작성


136

장고에서 동적 선택 필드를 만드는 방법을 이해하려고하는데 문제가 있습니다. 다음과 같은 모델을 설정했습니다.

class rider(models.Model):
     user = models.ForeignKey(User)
     waypoint = models.ManyToManyField(Waypoint)

class Waypoint(models.Model):
     lat = models.FloatField()
     lng = models.FloatField()

내가하려는 것은 선택 사항을 만드는 것입니다. 필드 whos 값은 해당 라이더 (로그인 한 사람)와 관련된 웨이 포인트입니다.

현재 다음과 같이 내 형식으로 init를 재정의하고 있습니다.

class waypointForm(forms.Form):
     def __init__(self, *args, **kwargs):
          super(joinTripForm, self).__init__(*args, **kwargs)
          self.fields['waypoints'] = forms.ChoiceField(choices=[ (o.id, str(o)) for o in Waypoint.objects.all()])

그러나 모든 것은 모든 웨이 포인트를 나열하는 것이며, 특정 라이더와 관련이 없습니다. 어떤 아이디어? 감사.

답변:


191

사용자를 양식 init에 전달하여 경유지를 필터링 할 수 있습니다.

class waypointForm(forms.Form):
    def __init__(self, user, *args, **kwargs):
        super(waypointForm, self).__init__(*args, **kwargs)
        self.fields['waypoints'] = forms.ChoiceField(
            choices=[(o.id, str(o)) for o in Waypoint.objects.filter(user=user)]
        )

양식을 시작하는 동안 사용자의 입장에서

form = waypointForm(user)

모델 형태의 경우

class waypointForm(forms.ModelForm):
    def __init__(self, user, *args, **kwargs):
        super(waypointForm, self).__init__(*args, **kwargs)
        self.fields['waypoints'] = forms.ModelChoiceField(
            queryset=Waypoint.objects.filter(user=user)
        )

    class Meta:
        model = Waypoint

20
ModelForm인지 여부에 관계없이 ModelChoiceField를 사용하십시오. 일반 양식에서도 작동합니다.
Daniel Roseman

9
그래도 요청 데이터를 가져 오려면 어떻게해야합니까? 유효성 검사 할 데이터가 더 이상 없으므로 waypointForm (request.POST)은 첫 번째 형식에서 유효성을 검사하지 않습니다.
Breedly

1
@Ashok이 인스턴스에서 CheckboxSelectMultiple 위젯을 어떻게 사용할 수 있습니까? 특히 모델 양식의 경우.
wasabigeek

2
당신이 사용하려는 경우 CheckboxSelectMultiple이와 위젯을, 당신은 사용할 수 있습니다 MultipleChoiceField또는 ModelMultipleChoiceField. 처음에는와 함께 작동하는 것처럼 보이지만 ChoiceField양식을 저장하려고하면 내부가 손상됩니다.
coredumperror

1
@CoreDumpError에게 감사드립니다-의견을 읽기 전에 거의 2 시간 동안 싸웠습니다 (doh!). CheckboxSelectMultiple이 코드와 함께 위젯 을 사용하려는 경우 양식 제출을 위반하지 않도록주의하십시오 (유니 코드 문제) . 변경해야 ChoiceForm하는MultipleChoiceForm
sofly

11

문제에 대한 솔루션이 내장되어 있습니다 : ModelChoiceField .

일반적으로 ModelForm데이터베이스 객체를 생성 / 변경해야 할 때 항상 사용하는 것이 좋습니다 . 사례의 95 %에서 작동하며 자체 구현을 만드는 것보다 훨씬 깨끗합니다.


8

문제는 당신이 할 때입니다

def __init__(self, user, *args, **kwargs):
    super(waypointForm, self).__init__(*args, **kwargs)
    self.fields['waypoints'] = forms.ChoiceField(choices=[ (o.id, str(o)) for o in Waypoint.objects.filter(user=user)])

업데이트 요청에서 이전 값이 손실됩니다!


3

초기화하는 동안 라이더 인스턴스를 폼에 전달하는 것은 어떻습니까?

class WaypointForm(forms.Form):
    def __init__(self, rider, *args, **kwargs):
      super(joinTripForm, self).__init__(*args, **kwargs)
      qs = rider.Waypoint_set.all()
      self.fields['waypoints'] = forms.ChoiceField(choices=[(o.id, str(o)) for o in qs])

# In view:
rider = request.user
form = WaypointForm(rider) 

2

일반적인 선택 필드가있는 작업 솔루션 아래. 내 문제는 각 사용자가 몇 가지 조건에 따라 자체 CUSTOM 선택 필드 옵션을 가지고 있다는 것입니다.

class SupportForm(BaseForm):

    affiliated = ChoiceField(required=False, label='Fieldname', choices=[], widget=Select(attrs={'onchange': 'sysAdminCheck();'}))

    def __init__(self, *args, **kwargs):

        self.request = kwargs.pop('request', None)
        grid_id = get_user_from_request(self.request)
        for l in get_all_choices().filter(user=user_id):
            admin = 'y' if l in self.core else 'n'
            choice = (('%s_%s' % (l.name, admin)), ('%s' % l.name))
            self.affiliated_choices.append(choice)
        super(SupportForm, self).__init__(*args, **kwargs)
        self.fields['affiliated'].choices = self.affiliated_choice

정확히 내가 찾던 것! 감사!
랩터

이것은 내 인생을 더 쉽게 만들었습니다 .. 정말 고마워요 .. :)
Aravind R Pillai

1

Breedly와 Liang이 지적한 것처럼 Ashok의 솔루션은 양식을 게시 할 때 선택 가치를 얻지 못하게합니다.

약간 다르지만 여전히 불완전한 방법은 다음과 같습니다.

class waypointForm(forms.Form):
    def __init__(self, user, *args, **kwargs):
        self.base_fields['waypoints'].choices = self._do_the_choicy_thing()
        super(waypointForm, self).__init__(*args, **kwargs)

그러나 일부 동시성 문제가 발생할 수 있습니다.


1

필드를 양식의 1 급 속성으로 선언하고 선택 사항을 동적으로 설정할 수 있습니다.

class WaypointForm(forms.Form):
    waypoints = forms.ChoiceField(choices=[])

    def __init__(self, user, *args, **kwargs):
        super().__init__(*args, **kwargs)
        waypoint_choices = [(o.id, str(o)) for o in Waypoint.objects.filter(user=user)]
        self.fields['waypoints'].choices = waypoint_choices

ModelChoiceField를 사용하고 비슷한 방식으로 init에 쿼리 셋을 설정할 수도 있습니다.


0

django admin에서 동적 선택 필드가 필요한 경우; django> = 2.1에서 작동합니다.

class CarAdminForm(forms.ModelForm):
    class Meta:
        model = Car

    def __init__(self, *args, **kwargs):
        super(CarForm, self).__init__(*args, **kwargs)

        # Now you can make it dynamic.
        choices = (
            ('audi', 'Audi'),
            ('tesla', 'Tesla')
        )

        self.fields.get('car_field').choices = choices

    car_field = forms.ChoiceField(choices=[])

@admin.register(Car)
class CarAdmin(admin.ModelAdmin):
    form = CarAdminForm

도움이 되었기를 바랍니다.

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