2010-06-07 35 views
20

trong dự án Django (1.2) của tôi, tôi muốn điền trước một trường trong một dạng mẫu, nhưng giá trị mới của tôi bị bỏ qua. Đây là đoạn:Ghi đè giá trị ban đầu trong ModelForm

class ArtefactForm(ModelForm): 
    material = CharField(widget=AutoCompleteWidget('material', force_selection=False)) 

    def __init__(self, *args, **kwargs): 
     super(ArtefactForm, self).__init__(*args, **kwargs) 
     self.fields['material'].initial = 'Test' 

Tôi cũng đã cố gắng với self.base_fields, nhưng không có tác dụng: luôn luôn có cơ sở dữ liệu có giá trị hiển thị trong biểu mẫu. Bất kỳ ý tưởng?

Trả lời

39

Hãy thử điều này:

def __init__(self, *args, **kwargs): 
    initial = kwargs.get('initial', {}) 
    initial['material'] = 'Test' 
    kwargs['initial'] = initial 
    super(ArtefactForm, self).__init__(*args, **kwargs) 
+0

hoàn hảo, cảm ơn bạn. – schneck

10

Cũ câu hỏi nhưng thêm một câu trả lời mô tả như tôi tin rằng nó sẽ rất hữu ích đối với một số nhà phát triển mới.

Tôi cũng đã thử với self. base_fields, nhưng không có hiệu lực: luôn có giá trị cơ sở dữ liệu hiển thị trong biểu mẫu. Bất kỳ ý tưởng?

Nếu một hình thức được "khởi tạo" hình thức, hoặc là: -

  1. sử dụng initial luận (. Ví dụ YourModelFrom(initial={'filed1': variable}) — nói chung là các trường hợp, khi bạn muốn vượt qua giá trị ban đầu tự động tính toán cho một số lĩnh vực) . Tham khảo Setting Initial Values

    hoặc

  2. sử dụng instance luận (ví dụ. YourModelFrom(instance=model_object) — thường là trường hợp, khi bạn muốn cập nhật một đối tượng dụ mô hình hiện có). Tài liệu tham khảo đọc ModelFrom của save() method

    Lưu ý:
    lớp kế thừa `BaseModelFrom` lớp. Lớp `BaseModelFrom` kế thừa lớp `BaseForm`.
    2 Luận điểm instance được thêm vào trong `BaseModelFrom` constructor lớp, khi chúng ta gán một đối tượng mô hình lớp dụ để instance luận (do đó instance is not None) sau đó `BaseModelFrom` constructor gọi model_to_dict() và cập nhật initial tranh luận trước khi gọi siêu constructor lớp. Kiểm tra def __init__ trong lớp BaseModelFrom

Sau đó gán giá trị ban đầu cho một lĩnh vực một cách rõ ràng (như thể hiện trong mã OP trong câu hỏi) không thực tế, đây là do cách _clean_fields phương pháp được viết bằng BaseFrom lớp.

Mã Snip:

def _clean_fields(self): 
    for name, field in self.fields.items(): 
     value = field.widget.value_from_datadict(
       self.data, self.files, self.add_prefix(name)) 
     try: 
      if isinstance(field, FileField): 
       initial = self.initial.get(name, field.initial) # <- Check 
       value = field.clean(value, initial) 
      else: 

Theo dòng mã initial = self.initial.get(name, field.initial), nếu giá trị ban đầu cho lĩnh vực được đưa ra trong initial dict sau đó giá trị giao cho field.initialkhông sử dụng.

[ĐÁP]:

Mặc dù, @Daniel Câu trả lời là hoàn toàn chính xác nhưng người ta có thể cũng giống như một cách khác để đạt được cùng một hiệu ứng được sử dụng self.initial:

def __init__(self, *args, **kwargs): 
    super(ArtefactForm, self).__init__(*args, **kwargs) 
    self.initial['material'] = 'Test' 

Give it a try !!

self.initial là gì, nhưng nó là dict chúng tôi vượt qua trong đối số. Kiểm tra mã __init__ trong BaseForm:

class BaseForm(object): 
    def __init__(........ 
       ........): 
     : 
     self.prefix = prefix 
     self.initial = initial or {} # <-- Notice 
     self.error_class = error_class 
     : 

Lưu ý: Tôi không tìm thấy bất kỳ tài liệu liên quan đến sử dụng thuộc tính ban đầu, tôi chỉ khám phá các mã cơ bản và sử dụng nó.

Edit: hành vi báo cáo trong Câu hỏi này cũng được ghi chép lại trong Django Mẫu

Dynamic initial values

Form.initial

Lưu ý rằng nếu một Field định nghĩa initialbạn bao gồm initial khi khởi tạo Biểu mẫu, sau đó là initial sẽ được ưu tiên. Trong ví dụ này, initial được cung cấp cả ở cấp trường và tại mức hình thức ví dụ, và sau này sẽ được ưu tiên:

>>> from django import forms 
>>> class CommentForm(forms.Form): 
...  name = forms.CharField(initial='class') 
...  url = forms.URLField() 
...  comment = forms.CharField() 
>>> f = CommentForm(initial={'name': 'instance'}, auto_id=False) 
>>> print(f) 
<tr><th>Name:</th><td><input type="text" name="name" value="instance" /> 
<tr><th>Url:</th><td><input type="url" name="url" /></td></tr> 
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> 

PS: Btw, điểm 2 trong câu trả lời của tôi nói sự khác biệt giữa đối số initialinstance. Đối số của họ là một đối số khóa-giá trị hơn data - các giá trị trong trình kích hoạt đó tạo thành xác thực hợp lệ. đọc số này Difference between Django Form 'initial' and 'bound data'?.

+0

** Lưu ý: ** Ở dạng ràng buộc, 'dữ liệu' (truy vấn dict) sẽ được ưu tiên hơn giá trị của trường được khởi tạo. Kiểm tra mã: ['def value (self)'] (https://github.com/django/django/blob/master/django/forms/forms.py#L610) và phương thức ['def bound_data (tự, dữ liệu, ban đầu) '] (https://github.com/django/django/blob/master/django/forms/fields.py#L165) - điều này sẽ giúp bạn nếu bạn có một giá trị cho một trường os được tính toán động và đã nộp là ['disabled'] (http://stackoverflow.com/a/1424453/1673391). Hãy cho tôi biết nếu có ai cần giúp đỡ về điều này, tôi sẽ cập nhật câu trả lời này! –

+0

Câu trả lời hay, cảm ơn bạn! Về cài đặt giá trị ban đầu, tôi muốn thêm một giải pháp [Tôi tìm thấy] (https://stackoverflow.com/a/22390638/2996101): 'self.fields [field_name] .initial = field_value' – raratiru

Các vấn đề liên quan