Django e-commerce part63 Crafting the Order Part 3
Order内容の修正
現状では、ゲストユーザーが買い物を続けようとすると、anonymous userは認証できないという画面が出てきてしまう。それを修正する。
errorの原因は、AddressSelectFormView
の、get_form()の箇所だと思われる。
orders/views.py に追記する。
try をなくして、変数関連を少し整える。
class AddressSelectFormView(FormView): ... def get_form(self, *args, **kwargs): form = super(AddressSelectFormView, self).get_form(*args, **kwargs) user_check_id = self.request.session.get("user_checkout_id") #carts/views.py から持ってくる。 user_checkout = UserCheckout.objects.get(id=user_check_id) ...
- user_check_idを、sessionからゲットする。
- ゲットした、user_check_idでフィルターをかけて、usercheckoutのinstanceをゲットする。
orders/views.py にさらに追記する。
class AddressSelectFormView(FormView): form_class = AddressForm template_name = "orders/address_select.html" def get_form(self, *args, **kwargs): form = super(AddressSelectFormView, self).get_form(*args, **kwargs) user_check_id = self.request.session.get("user_checkout_id") user_checkout = UserCheckout.objects.get(id=user_check_id) b_address = UserAddress.objects.filter( user=user_checkout, type='billing', ) s_address = UserAddress.objects.filter( user=user_checkout, type='shipping', ) form.fields["billing_address"].queryset = b_address form.fields["shipping_address"].queryset = s_address if b_address.count() == 0 or s_address.count() == 0: return print ("error") return form
orders/forms.py に UserAddressFormを作成する。
ModelFormで作成する。
class UserAddressForm(forms.ModelForm): class Meta: model = UserAddress fields = [ 'street', 'city', 'state', 'zipcode', 'type', ]
orders/views.py に、UserAddressCreateView を作成する。
CreateViewは、class based viewにあるため、それを利用する。
Generic editing views | Django documentation | Django
from django.views.generic.edit import CreateView, FormView from .forms import AddressForm, UserAddressForm ... class UserAddressCreateView(CreateView): form_class = UserAddressForm template_name = "forms.html" success_url = "/checkout/address/" ...
ポイント
- CreateViewをimportして、form_classには、UserAddressFormを設定している。
- success_urlも指定する。
urls.pyを設定
url(r'^checkout/address/add/$', UserAddressCreateView.as_view(), name='user_address_create'),
orders/views.py の修正
if b_address.count() == 0 or s_address.count() == 0: return redirect("user_address_create")
- アドレス登録のどちらかが、0である場合は、user_address_createにredirectする。ただこのままだと、shippingaddressが必須項目になってしまって、errorが出てしまうので、ちょっと上記の箇所はコメントアウトしておく。
orders/vews.pyの編集
class AddressSelectFormView(FormView): form_class = AddressForm template_name = "orders/address_select.html" def get_addresses(self, *args, **kwargs): user_check_id = self.request.session.get("user_checkout_id") user_checkout = UserCheckout.objects.get(id=user_check_id) b_address = UserAddress.objects.filter( user=user_checkout, type='billing', ) s_address = UserAddress.objects.filter( user=user_checkout, type='shipping', ) return b_address, s_address def get_form(self, *args, **kwargs): form = super(AddressSelectFormView, self).get_form(*args, **kwargs) b_address, s_address = self.get_addresses() # # if b_address.count() == 0 or s_address.count() == 0: # return redirect("user_address_create") form.fields["billing_address"].queryset = b_address form.fields["shipping_address"].queryset = s_address return form
ポイント
- b_addressと、s_addressをgetするfunctionを新たに作成する。
- get_formでは、self.get_addresses()で、それぞれの値を代入する。(これは、2つの値を返すため、変数も2つ必要)
orders/vews.py AddressSelectFormViewのdispatch メソッドを更新する。
def dispatch(self, *args, **kwargs): b_address, s_address = self.get_addresses() if b_address.count() == 0 or s_address.count() == 0: return redirect("user_address_create") return super(AddressSelectFormView, self).dispatch(*args, **kwargs)
billing shippingのどちらかが0の場合は、user_address_createにredirectする。
さらに上記にmessagesを加えると以下のようになる。
def dispatch(self, *args, **kwargs): b_address, s_address = self.get_addresses() if b_address.count() == 0: messages.success(self.request,"請求先の住所を登録してください。") return redirect("user_address_create") elif s_address.count() == 0: messages.success(self.request,"送付先の住所を登録してください。") return redirect("user_address_create") else: return super(AddressSelectFormView, self).dispatch(*args, **kwargs)
UserAddressForm に必須のuser fieldの情報を登録する。
UserAddress は、user情報が必須なので、その情報をデータベースに渡す必要がある。現状のフォームでは、userは選択できないため、バックヤードで渡す必要あり。ちなみに、ここのuserは、UserCheckout のuserのため、UserCheckoutのインスタンスが必要。
class UserAddressCreateView(CreateView): ... def get_checkout_user(self): user_check_id = self.request.session.get("user_checkout_id") user_checkout = UserCheckout.objects.get(id=user_check_id) return user_checkout def form_valid(self, form, *args, **kwargs): form.user = self.get_checkout_user() return super(UserAddressCreateView, self).form_valid(form, *args, **kwargs) ...
ポイント
- get_checkout メソッドで、sessionからcheckout_idをゲット->絞り込み->user_checkoutにUserCheckoutのインスタンスを渡す。
- form_validのタイミングで、form.user (ここでいうformは、UserAddressFormを想定)に、user_checkoutを代入する(ように、form_validを上書きする)
error を修正する。
以下のように、orders/useraddressには、user_idが必須と出てしまうので、それを修正する。つまり、user_checkoutがうまく渡せていないということだと思われる。
NOT NULL constraint failed: orders_useraddress.user_id
form_validを以下のように修正する。
def form_valid(self, form, *args, **kwargs): form.instance.user = self.get_checkout_user() return super(UserAddressCreateView, self).form_valid(form, *args, **kwargs)
ポイント
- UserAddressForm(forms.ModelForm)のように、ModelFormは、form.instance.フィールド名で、formのインスタンスをゲットできる。form.フィールド名では、ゲットできない。これはハマりそうなポイントのため注意。