さて、CreateView
はmodel
とfields
の属性をに暗黙的に指定することができます。フォームを作成します。あなたのケースでは、Campaign
オブジェクトをデータベースに保存する前に(現在のユーザをログインさせて、ユーザをログインさせる)、いくつかのカスタマイズを行う必要があります。
その結果、あなたが最初に独自のフォームを作成する必要があります(あなたのviews.py
の隣にすることができforms.py
という名前のファイルを作成する)と、このコードを入力します:
class CampaignForm(ModelForm): # Import ModelForm too.
def __init__(self, *args, **kwargs):
# We need to get access the currently logged in user so set it as an instance variable of CampaignForm.
self.user = kwargs.pop('user', None)
super(CampaignForm, self).__init__(*args, **kwargs)
class Meta:
model = models.Campaign # you need to import this from your models.py class
fields = ['title','media','description']
def save(self, commit=True):
# This is where we need to insert the currently logged in user into the Campaign instance.
instance = super(CampaignForm, self).save(commit=False)
# Once the all the other attributes are inserted, we just need to insert the current logged in user
# into the instance.
instance.user = self.user
if commit:
instance.save()
return instance
今、私たちは私たちのforms.py
すべてを持っていること行く準備ができて、私たちは自分のviews.py
を変更する必要があります
class NewCampagin(LoginRequiredMixin, CreateView):
template_name = 'campagin/new_campagin.html'
form_class = forms.CampaignForm # Again, you'll need to import this carefully from our newly created forms.py
model = models.Campaign # Import this.
queryset = models.Campaign.objects.all()
def get_absolute_url(self):
return reverse('campagin:active_campagin') # Sending user object to the form, to verify which fields to display/remove (depending on group)
def get_form_kwargs(self):
# In order for us to access the current user in CampaignForm, we need to actually pass it accross.
# As such, we do this as shown below.
kwargs = super(NewCampaign, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
実際にボンネットの下に私のPOSTリクエストで何が起こっています?
注:これは、学習のためだけの追加情報です。 あなたのクラス ベースビューが実際にあなたの投稿要求をどのように処理しているか気にしない場合、この部分を読む必要はありません。
基本的に
CreateView
は次のようになります。
class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView):
"""
View for creating a new object instance,
with a response rendered by template.
"""
template_name_suffix = '_form'
はその面白そうに見えるしませんが、我々はBaseCreateView
分析する場合:
class BaseCreateView(ModelFormMixin, ProcessFormView):
"""
Base view for creating an new object instance.
Using this base class requires subclassing to provide a response mixin.
"""
def post(self, request, *args, **kwargs):
self.object = None
return super(BaseCreateView, self).post(request, *args, **kwargs)
を我々は2つの非常に重要なクラスから継承されて見ることができますModelFormMixin
およびProcessFormView
。さてライン、return super(BaseCreateView, self).post(request, *args, **kwargs)
は、基本的に次のようになりますProcessFormView
でpost
関数を呼び出します:あなたが見ることができるように
def post(self, request, *args, **kwargs):
"""
Handles POST requests, instantiating a form instance with the passed
POST variables and then checked for validity.
"""
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
を、あなたのCreateView
は本当にただ単に指定されたフォームとを検証+を取得し、この小さなpost
関数に帰着しますそれを保存します。この時点で2つの質問があります。
1)私も自分のフォームを指定していないので、form = self.get_form()
は何をしますか?
2)self.form_valid(form)
、実際には何をしているのですか?
self.get_form()
は基本的に別の関数form_class = self.get_form_class()
を呼び出し、この関数は実際にModelFormMixin(から継承された1!)で発見され、最初の質問に答えるために:
def get_form_class(self):
"""
Returns the form class to use in this view.
"""
if self.fields is not None and self.form_class:
raise ImproperlyConfigured(
"Specifying both 'fields' and 'form_class' is not permitted."
)
if self.form_class:
return self.form_class
else:
if self.model is not None:
# If a model has been explicitly provided, use it
model = self.model
elif hasattr(self, 'object') and self.object is not None:
# If this view is operating on a single object, use
# the class of that object
model = self.object.__class__
else:
# Try to get a queryset and extract the model class
# from that
model = self.get_queryset().model
if self.fields is None:
raise ImproperlyConfigured(
"Using ModelFormMixin (base class of %s) without "
"the 'fields' attribute is prohibited." % self.__class__.__name__
)
# THIS IS WHERE YOUR FORM WAS BEING IMPLICITLY CREATED.
return model_forms.modelform_factory(model, fields=self.fields)
あなたが見ることができるように、この関数がありますあなたのフォームは暗黙のうちにが作成されました(最後の行を参照)。お客様のケースに機能を追加する必要がありましたので、forms.py
を作成し、views.py
にform_classと指定しました。だからここ
def form_valid(self, form):
"""
If the form is valid, save the associated model.
"""
# THIS IS A CRUCIAL LINE.
# This is where your actual Campaign object is created. We OVERRIDE the save() function call in our forms.py so that you could link up your logged in user to the campaign object before saving.
self.object = form.save()
return super(ModelFormMixin, self).form_valid(form)
我々は単にオブジェクトを保存されています
は、2番目の質問に答えるために、我々は、関数で(
self.form_valid(form)
)コールのソースコードを見てする必要があります。
私はこれがあなたを助けてくれることを願っています!
詳細情報https://docs.djangoproject.com/en/1.10/ref/class-based-views/generic-editing/#createview
問題: – thebjorn
問題は、 'user_id'は常にデフォルト値' 1'を持っているようです。あなたはキャンペーンのインスタンスを作成するコードを投稿できますか? – dahrens
フォームクラスを投稿できますか? –