Tạo trường lựa chọn động


136

Tôi gặp một số khó khăn khi cố gắng hiểu cách tạo trường lựa chọn động trong django. Tôi có một mô hình thiết lập một cái gì đó như:

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

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

Những gì tôi đang cố gắng làm là tạo ra một lựa chọn Giá trị trường là các điểm mốc liên quan đến người lái đó (sẽ là người đăng nhập).

Hiện tại tôi đang ghi đè init trong các biểu mẫu của mình như vậy:

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()])

Nhưng tất cả những gì cần liệt kê là tất cả các điểm tham chiếu, chúng không liên quan đến bất kỳ tay đua cụ thể nào. Có ý kiến ​​gì không? Cảm ơn.

Câu trả lời:


191

bạn có thể lọc các điểm mốc bằng cách chuyển người dùng đến biểu mẫu 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)]
        )

từ quan điểm của bạn trong khi bắt đầu biểu mẫu vượt qua người dùng

form = waypointForm(user)

trong trường hợp mẫu

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
Sử dụng ModelChoiceField cho dù đó có phải là ModelForm hay không - nó cũng hoạt động trên các dạng thông thường.
Daniel Roseman

9
Bạn làm gì khi bạn muốn lấy dữ liệu yêu cầu ra? waypointForm (request.POST) sẽ không xác thực trong lần đầu tiên, bởi vì dữ liệu để xác thực không còn nữa.
Nhân giống

1
@Ashok Làm thế nào tiện ích CheckboxSelectMult Môn có thể được sử dụng trong trường hợp này? Đối với các mô hình đặc biệt.
wasabigeek

2
Nếu bạn muốn sử dụng CheckboxSelectMultipletiện ích này, bạn sẽ muốn sử dụng MultipleChoiceFieldhoặc ModelMultipleChoiceField. Lúc đầu, nó có vẻ hoạt động ChoiceField, nhưng các phần bên trong sẽ bị hỏng khi bạn cố lưu biểu mẫu.
coredumperror

1
Cảm ơn bạn @CoreDumpError - chỉ cần chiến đấu trong gần 2 giờ trước khi đọc bình luận của bạn (doh!) Và điều này cuối cùng đã khiến mọi thứ hoạt động. Những người khác, hãy cẩn thận khi phá vỡ đệ trình biểu mẫu của bạn (các vấn đề về unicode) nếu bạn có kế hoạch sử dụng CheckboxSelectMultiplewidget với mã này. Hãy chắc chắn để thay đổi ChoiceFormthànhMultipleChoiceForm
nhẹ nhàng

11

Có giải pháp tích hợp cho vấn đề của bạn: ModelChoiceField .

Nói chung, nó luôn đáng để thử sử dụng ModelFormkhi bạn cần tạo / thay đổi các đối tượng cơ sở dữ liệu. Hoạt động trong 95% các trường hợp và nó sạch hơn nhiều so với việc tạo triển khai của riêng bạn.


8

vấn đề là khi bạn làm

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)])

trong một yêu cầu cập nhật, giá trị trước đó sẽ bị mất!


3

Làm thế nào về việc chuyển thể hiện của người lái vào biểu mẫu trong khi khởi tạo nó?

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

Bên dưới giải pháp làm việc với lĩnh vực lựa chọn bình thường. vấn đề của tôi là mỗi người dùng có các tùy chọn trường tùy chọn riêng dựa trên một số điều kiện.

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

Chính xác những gì tôi đang tìm kiếm! Cảm ơn!
Raptor

điều này làm cho cuộc sống của tôi dễ dàng hơn .. Cảm ơn rất nhiều .. :)
Aravind R Pillai

1

Như được chỉ ra bởi Breedly và Liang, giải pháp của Ashok sẽ ngăn bạn nhận được giá trị được chọn khi đăng mẫu đơn.

Một cách hơi khác, nhưng vẫn không hoàn hảo, cách giải quyết đó là:

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)

Điều này có thể gây ra một số vấn đề đồng thời, mặc dù.


1

Bạn có thể khai báo trường dưới dạng một thuộc tính hạng nhất của biểu mẫu của bạn và chỉ cần thiết lập các lựa chọn một cách linh hoạt:

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

Bạn cũng có thể sử dụng ModelChoiceField và đặt bộ truy vấn trên init theo cách tương tự.


0

Nếu bạn cần một trường lựa chọn động trong quản trị django; Điều này hoạt động cho 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

Hi vọng điêu nay co ich.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.