2016-10-08 2 views
0

私は、曲のアーティスト、タイトル、およびミックスを要求するフォームを持っています。アーティストとタイトルは必須フィールドですが、ミックスは必須ではありません。フォームはアーティスト、タイトル、ミックスが存在しない場合にのみ保存する必要があります。フォームに空のアーティストまたはタイトルフィールドがある場合は、送信時に「このフィールドは必須です」と表示されます。 Titleフィールドが空でもArtistに値が設定されていても、get_or_createを使ってArtistオブジェクトを作成します(下記の### forms.pyを参照)。フォームが有効な場合、アーティストオブジェクトのみを作成するにはどうすればよいですか?フォーム制約が満たされている場合にのみDjango 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") 
    ... 

上記は、そのユーザーのための2段階のプロセスになります。声明と組み合わせ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はまだメインクリーンで実行されます。

関連する問題