2016-10-08 2 views
0

노래의 아티스트, 제목 및 믹스를 묻는 양식이 있습니다. 아티스트 및 제목은 필수 입력란이지만 믹스는 아닙니다. 아티스트, 타이틀 및 믹스가없는 경우에만 양식을 저장해야합니다. 양식에 빈 아티스트 또는 제목 필드가 있으면 제출시 "이 필드가 필요합니다"라고 표시되어야합니다. 제목 필드가 비어 있지만 아티스트가 채워지면 여전히 get_or_create (### forms.py 참조)와 함께 아티스트 개체가 생성됩니다. 양식이 유효한 경우 아티스트 객체 만 어떻게 만듭니 까?폼 제약 조건이 충족되는 경우에만 장고 get_or_create

###########models.py 
class Artist (models.Model): 
    name = models.CharField(max_length=100) 

class Track (models.Model):  
    artist = models.ForeignKey(Artist, blank=True, null=True, on_delete=models.SET_NULL, verbose_name="Artist") 
    user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL, verbose_name="Submitted by", default=1) 
    title = models.CharField(max_length=100, verbose_name="Title") 
    mix = models.CharField(max_length=100, blank=True, verbose_name="Mix") 

###########views.py 
class TrackCreateView(SuccessMessageMixin, AjaxCreateView): 
    form_class = ProfileForm 
    success_message = "Thank you for submitting track: %(artist)s - %(title)s - %(mix)s" 

    def get_initial(self): 
     self.initial.update({ 'user': self.request.user }) 
     return self.initial 

    def get_success_message(self, cleaned_data): 
     return self.success_message % dict(cleaned_data, 
      artist=self.object.artist, 
      title=self.object.title, 
     ) 

###########forms.py 
class ProfileForm(forms.ModelForm): 

    class Meta: 
     model = Track 
     fields = [ 
      "artist", 
      "title", 
      "mix", 
      ]   
    artist = forms.CharField(widget=forms.TextInput(attrs={'maxlength': '100',}))   

    def __init__(self, *args, **kwargs): 
     self.user = kwargs['initial']['user'] 
     super(ProfileForm, self).__init__(*args, **kwargs) 
     # Set layout for fields. 
     my_field_text= [ 
      ('artist', 'Artist', ''), 
      ('title', 'Title', ''), 
      ('mix', 'Mix', ''), 
     ] 
     for x in my_field_text: 
      self.fields[x[0]].label=x[1] 
      self.fields[x[0]].help_text=x[2] 

     self.helper = FormHelper() 
     self.helper.layout = Layout(
      Div(
       Div('artist', css_class="col-sm-4"), 
       Div('title', css_class="col-sm-4"), 
       Div('mix', css_class="col-sm-4"),    
       css_class = 'row' 
      ), 
     ) 


    def save(self, commit=True): 
     obj = super(ProfileForm, self).save(False) 
     obj.user = self.user 
     commit and obj.save() 
     return obj 

    def clean(self): 
     cleaned_data = super(ProfileForm, self).clean() 

     artist = self.cleaned_data.get('artist') 
     title = self.cleaned_data.get('title') 
     mix = self.cleaned_data.get('mix') 

     if artist and title: 
      title = ' '.join([w.title() if w.islower() else w for w in title.split()]) 
      if mix: 
       mix = ' '.join([w.title() if w.islower() else w for w in mix.split()]) 

      if Track.objects.filter(artist=artist, title=title, mix=mix).exists(): 
       msg = "Record with Artist and Title already exists." 
       if mix: 
        msg = "Record with Artist, Title & Mix already exists." 
        self.add_error('mix', msg) 
       self.add_error('artist', msg) 
       self.add_error('title', msg) 

     if not artist: 
      raise forms.ValidationError("Artist is a required field.") 
     else: 
      artist, created = Artist.objects.get_or_create(name=artist) 
      self.cleaned_data['artist'] = artist 


     self.cleaned_data['title'] = title 
     self.cleaned_data['mix'] = mix 
     return self.cleaned_data 
+0

왜 당신은'clean_artist'에'get_or_create (name = artist)'을 가지고 있고 일반'clean'에는 들어 있지 않습니다; 후자의 경우에만 (당신이하는 것처럼)'예술가와 타이틀인지 '를 확인할 수 있습니다. – Evert

+0

clean_artist를 제거한 후 일반 청소했습니다. 어쨌든 양식이 유효한 경우에만 get_or_create 할 수 있습니까? – bayman

답변

1

어떻게 먼저 양식을 clean()에 유효한지 확인하여, 당신의 비교를 변경하는 방법에 대한? 사용자가 아티스트와 빈 제목을 모두 떠나면, 그들은 아티스트 통지를받을 ONY 이후

def clean(self): 
    ... 
    if not artist: 
     raise ValidationError("artist is a required field") 
    if not title: 
     raise ValidationError("title is a required field") 
    ... 

위는, 사용자를 위해 그것을 두 단계의 과정을 수 있습니다. 문 및 결합 ValidationError 경우 당신은 더 나은 (하위)를 만들 수있는, 아니면 그냥 (현장에서 청소 방법을 사용하지 get_or_create)를 ValidationError을 높이는를 들어, clean_artistclean_title를 사용하여 해당 해결 :

def clean_artist(self): 
    # no get_or_create here 
    ... 
    if not artist: 
     raise ValidationError("artist is a required field") 

def clean_title(self): 
    # no get_or_create here 
    ... 
    if not title: 
     raise ValidationError("title is a required field") 

def clean(self): 
    ... 
    if title and artist: 
     # get_or_create stuff here 
    ... 

이 방법 , 당신은 독립적으로 두 가지 오류를 모두 가져야한다. 그러나 get_or_create는 제목과 아티스트가 유효 할 때만 메인 클린에서 여전히 수행된다.

관련 문제