2010-02-09 36 views
21

Tôi đã làm một ModelForm thêm một số trường bổ sung mà không phải là trong mô hình. Tôi sử dụng các trường này cho một số phép tính khi lưu biểu mẫu.Django ModelForm với các trường bổ sung không có trong mô hình

Các trường bổ sung xuất hiện trên biểu mẫu và chúng được gửi trong yêu cầu POST khi tải lên biểu mẫu. Vấn đề là chúng không được thêm vào từ điển cleaned_data khi tôi xác thực biểu mẫu. Tôi có thể truy cập chúng bằng cách nào?

+0

Chúng phải được thêm vào dictionry clean_data. Vui lòng đăng mã mẫu của bạn để chúng tôi có thể xem xét. – gruszczy

+0

Tôi khuyên bạn không nên lưu trữ thông tin trong trường Biểu mẫu. Giải pháp sạch hơn là: lưu trữ nó trong phiên. – sergzach

+0

Nếu mã bạn đã đăng trong câu trả lời tiếp theo là bản sao và dán chính xác, thì có sự cố thụt dòng với dòng cuối cùng - nó phải là một cấp độ. –

Trả lời

1

Ok tôi đã giải quyết nó. Dường như việc truy cập vào các trường bổ sung với clean_data ['field_name'] tăng một KeyError nhưng sử dụng clean_data.get ('field_name') hoạt động. Điều đó thật lạ vì các trường thông thường cho mô hình có thể được truy cập thông qua clean_data ['field_name'].

Cập nhật: Không, nó không hoạt động. Với get() nó không tăng KeyError nhưng nó đặt giá trị None vì các trường bổ sung không có trong từ điển clean_data.

Đây là mã. Trong các mẫu có tự động hoàn thành, do đó, trong biểu mẫu có trường "nghệ sĩ" được hiển thị dưới dạng một CharField và một IntegerField ẩn sẽ được tự động điền với id nghệ sĩ đã cho. Trong phương thức clean_artist, tôi muốn chọn đối tượng nghệ sĩ và lưu nó trong trường nghệ sĩ của biểu mẫu.

models.py

class Music(models.Model): 
    artist = models.ForeignKey(Artist, related_name='music', blank=True, null=True) 
    # other fields... 

forms.py

class MusicForm(forms.ModelForm): 
    artist_id = forms.IntegerField(label="", widget=forms.HiddenInput(), required=False) 
    artist = forms.CharField(required=False) 
    # other fields ... 

    class Meta: 
     model = Music 

    def clean_artist(self): 
     if self.cleaned_data.get('artist') == '': 
      artist = None 
     else: 
      artist_id = self.cleaned_data.get('artist_id') # this returns always None because artist_id is not in cleaned_fields (this seemed to work with previous django versions but not with current SVN version) 
      if artist_id != None: 
       artist = Artist.objects.get(id=artist_id) 
      else: 
       artist = None 

    return artist 
+0

Điều này thật lạ, bởi vì không có khác với []. Đăng mã của bạn và việc tìm sự cố cơ bản sẽ dễ dàng hơn. – gruszczy

+4

nghệ sĩ trả lại cần thêm thụt lề. nó không có trong phương thức clean_artist. –

+1

thụt lề có khắc phục được sự cố không? – Anentropic

5

Thứ nhất, bạn không nên có artist_id và nghệ sĩ lĩnh vực. Chúng được xây dựng từ mô hình. Nếu bạn cần một số tên nghệ sĩ, hãy thêm trường artist_name, đó là CharField.

Hơn nữa, bạn đang cố truy xuất nội dung nào đó từ clean_data bên trong giá trị sạch. Có thể không có dữ liệu bạn cần - bạn nên sử dụng giá trị từ self.data, dữ liệu trực tiếp từ POST.

+0

thực sự là sử dụng clean_data trong các phương thức clean_X riêng lẻ: http://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-a-specific-field-attribute – Anentropic

+0

Cảm ơn bạn đã phiên bản, @Martin – Cartucho

11

Có thể mở rộng Django ModelForm bằng các trường bổ sung. Hãy tưởng tượng bạn có một mô hình tài khoản tùy chỉnh và ModelForm này:

class ProfileForm(forms.ModelForm): 

    class Meta: 
     model = User 
     fields = ['username', 'country', 'website', 'biography'] 

Bây giờ, hãy tưởng tượng bạn muốn bao gồm trường bổ sung (không có mặt trong mô hình tài khoản của bạn, cho phép nói một hình ảnh avatar). Mở rộng hình thức của bạn bằng cách làm này:

from django import forms 

class AvatarProfileForm(ProfileForm): 

    profile_avatar = forms.ImageField() 

    class Meta(ProfileForm.Meta): 
     fields = ProfileForm.Meta.fields + ('profile_avatar',) 

Cuối cùng (cho rằng các hình thức có ImageField), nhớ để bao gồm request.FILES khi instantiating hình thức theo quan điểm của bạn:

# (view.py) 

def edit_profile(request): 
    ... 
    form = AvatarProfileForm(
     request.POST or None, 
     request.FILES or None, 
     instance=request.user 
    ) 
    ... 

Hy vọng nó giúp. Chúc may mắn!

EDIT:

Tôi đã nhận được một "chỉ có thể nối tuple (không phải là "danh sách") để tuple" lỗi trong AvatarProfileForm.Meta.fields thuộc tính. Thay đổi nó thành một tuple và nó đã làm việc.

+2

Tôi nhận được 'django.core.exceptions.FieldError: (các) trường không xác định (my_new_field) được chỉ định cho MyModel' khi tôi thêm' my_new_field' vào danh sách 'fields'. Django 1,10 – CpILL

4

Câu trả lời này có thể đã quá muộn đối với áp phích gốc, nhưng tôi nghĩ nó có thể giúp người khác. Tôi đã có cùng một vấn đề và tôi đã thông báo rằng self.cleaned_data ('artist_id') có thể được truy cập trong phương thức clean(), nhưng không có trong clean_artist().

Khi tôi thêm các trường bổ sung vào khai báo 'trường' của Meta, sau đó nó hoạt động.

class Meta: 
     model = Music 
     fields=[..., 'artist_id'] 

Bạn sẽ có thể truy cập self.cleaned_data ('artist_id') trong clean_artist().

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