2010-11-03 27 views
5

Tôi cần đặt giá trị trường, không được truyền cho hàm tạo của Django Form.Đặt giá trị trường theo phương thức clean() Django Form, nếu trường này không được truyền trong hàm tạo

tôi có mô hình và hình thức như thế này:

class Message(models.Model): 
    created  = models.DateTimeField() 
    text  = models.CharField(max_length=200, blank=True, null=True) 
    active  = models.BooleanField(default=False) 

class MessageForm(forms.ModelForm): 
    class Meta: 
     model = Message 
     exclude = ('created', 'active') 

    def clean(self): 
     # check if user is blocked 
     if user.is_admin(): 
      self.cleaned_data['active'] = True 
     return self.cleaned_data 

Dự kiến ​​: nếu người dùng hiện nay là admin - Tôi không cần tự động thiết lập thông điệp như hoạt động. Người dùng không được chuyển thông số này theo biểu mẫu.

Thực tế: Tôi thấy thông báo đã lưu luôn có cờ "Sai" (Tôi có thể xóa điều kiện và trong trường hợp này tôi cũng thấy thông báo đó không hoạt động).

Hãy giúp tôi hiểu, làm cách nào tôi có thể đặt phương thức "hoạt động" này ở clean().

+1

Làm thế nào và nơi nào "người dùng" biến được thiết lập? –

+0

Tôi làm ví dụ này. Bạn có thể xóa tình trạng này hoặc thay thế mọi thứ khác. Tôi đã đặt self.cleaned_data ['active'] = True nhưng tôi cũng cần nói với Django Form rằng trường này được sử dụng và cần thiết lập giá trị này cho đối tượng trước khi lưu. Tôi có thể làm điều này với tham số "ban đầu" cho đối tượng Form, nhưng tôi không thể làm điều này im trường hợp của tôi. Tôi cần nói với Django Form rằng tôi đã sử dụng "hoạt động" lĩnh vực, nhưng tôi không biết làm thế nào để làm điều này vào một phương pháp hình thức sạch(). –

Trả lời

4

Câu trả lời trước sẽ hoạt động, nhưng tôi thích đóng gói tất cả các hoạt động nội bộ của biểu mẫu như những gì hiển thị và những gì không có trong biểu mẫu. Tôi biết bạn đã đề cập bạn không muốn gửi giá trị trường tới hàm tạo, nhưng nếu bạn không nhớ gửi người dùng, giải pháp của bạn sẽ hoạt động. ví dụ: nhà xây dựng của bạn:

def __init__(self, user): 
    self.user = user 
    super(BaseForm, self).__init__() 

sau đó trong sạch của bạn, bạn chỉ cần thay đổi user-self.user. Có một lợi ích bổ sung cho điều này. Giả sử ngày mai bạn muốn chỉ định nhiều trường hơn dựa trên người dùng của mình, bạn không cần thêm bất kỳ thứ gì vào chế độ xem, bạn có thể chỉ cần thêm trường vào biểu mẫu.

EDIT: Khi bạn thêm trường để loại trừ, trường này không có sẵn trong dữ liệu được làm sạch. Thay vào đó, hãy đặt tiện ích con của nó là ẩn.

active = forms.BooleanField(widget=forms.HiddenInput) 

EDIT 2: Nếu bạn thực sự không muốn các lĩnh vực theo hình thức Trong trường hợp này, thay vì trọng sạch sẽ, tại sao bạn không ghi đè tiết kiệm?

def save (self): 
    super(BaseForm, self).save() 
    if user.is_admin(): 
     self.instance.active=True 
    super(BaseForm, self).save() 
+0

Đối tượng người dùng - đây không phải là vấn đề. Sự cố không được giải quyết clean_data đối với đối tượng đã lưu. Nếu tôi đặt self.cleaned_data ['active'] = True in result, trường này không bị ảnh hưởng. Tôi cần nói với biểu mẫu rằng tôi đã sử dụng trường "hoạt động" trong xử lý biểu mẫu này, giống như dữ liệu ban đầu được truyền trong hàm tạo biểu mẫu. –

+0

Chỉ cần kiểm tra lại biểu mẫu của bạn. Vấn đề là, khi bạn loại trừ một trường trong một biểu mẫu, nó không có sẵn trong dữ liệu đã được làm sạch. Thay vào đó, hãy bao gồm thuộc tính và đặt tiện ích con của nó thành ẩn. kiểm tra chỉnh sửa của tôi – zsquare

+0

Tôi đã đặt dữ liệu thành self.cleaned_data - điều này là tốt. Nhưng tôi cần nói với Django Form để sử dụng trường này. làm như thế nào? –

3

Không làm điều này trong phương thức clean() của biểu mẫu, thực hiện việc này trong chế độ xem.

def your_view(request): 
    if request.method == 'POST': 
     form = MessageForm(data=request.POST) 
     if form.is_valid(): 
      new_message = form.save(commit=False) 
      if user.is_admin(): 
       new_message.active = True 

Tuy nhiên, nếu bạn cũng muốn để xử lý các trường hợp sử dụng của bạn là không quản trị sử dụng các hình thức tương tự, bạn có thể nhìn vào kết hợp logic tương tự trong init của hình thức() thay vì quan điểm, có lẽ bởi chuyển thông tin về người dùng từ chế độ xem đến biểu mẫu init()

+0

Tôi mô tả dưới đây rằng tôi cần làm điều này trong Logic mô hình hoặc trong logic biểu mẫu. Theo quan điểm - cách này không dễ dàng cho công việc của tôi. Nếu người dùng làm việc trong phần quản trị - tôi cần kích hoạt logic tùy chỉnh của mình. Nếu tôi làm logic này theo quan điểm - điều này không hoạt động ở tất cả các nơi khác - và điều này không tốt! –

0

Sử dụng này:

def message_form_factory(user): 
    class MessageForm(forms.ModelForm): 
     def clean(self): 
      # check if user is blocked 
      if user.is_admin(): 
       self.cleaned_data['active'] = True 
      return self.cleaned_data 
    return MessageForm 

Và theo quan điểm sử dụng của bạn:

form = message_form_factory(request.user)() 
form = message_form_factory(request.user)(request.POST) 
+0

Trong quản trị Django, tôi cần sử dụng chức năng với logic tùy chỉnh. Giải pháp của bạn có thể được sử dụng trong quản trị viên với biểu mẫu tùy chỉnh - nhưng mã bổ sung này xung quanh dự án. Tôi nghĩ rằng đây không phải là một giải pháp tốt trong trường hợp của tôi. Cảm ơn! –

+0

Theo như tôi có thể đọc, bạn đã không đề cập đến bất cứ điều gì về quản trị Django trong câu hỏi của bạn .. –

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