【问题标题】:Django: correct values in request.POST but cannot save formDjango:request.POST 中的值正确但无法保存表单
【发布时间】:2019-01-25 21:36:46
【问题描述】:

在我的注册页面中,我有 2 个表单用户表单和个人资料表单。

Profile Form 依赖于 Profile 模型,该模型具有一个 OneToOneField 到 User 模型 - 来自 Django 的默认 User 模型。

这个想法是,当创建用户时,也会创建该用户的个人资料:

@receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
    instance.profile.save()

轮廓模型:

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # birth_date = models.DateField(null=True, blank=True)
    dni = models.CharField(max_length=30, blank=True)
    #phone_number = models.CharField(max_length=15, blank=True)
    shipping_address1 = models.CharField(max_length=100, blank=False)
    shipping_address2 = models.CharField(max_length=100, blank=False)
    shipping_department = models.CharField(max_length=100, blank=False)
    shipping_province = models.CharField(max_length=100, blank=False)
    shipping_district = models.CharField(max_length=100, blank=False)

    def __str__(self):
        return str(self.user.first_name) + "'s profile" 

问题: UserForm.is_valid() 是 True,但 Profile_Form.is_valid() 是 False

但在我的请求中,我得到了 ProfileForm 的所有正确值:

<QueryDict: {'csrfmiddlewaretoken': ['91sJC01vyty3Z9ECjrSop1bouUOF2ZeC9m6XZUgk0nTEH7p6W0DmtuQaB4EBhV22'], 'first_name': ['Juana'], 'last_name': ['Juana'], 'username': ['juana
juana'], 'dni': ['454545'], 'email': ['juana@gmail.com'], 'password1': ['caballo123'], 'password2': ['caballo123'], 'shipping_address1': ['Urb. La Merced Mz.G Lot.32'], 'ship
ping_address2': ['Villa FAP - San Roque'], 'shipping_department': ['Cajamarca'], 'shipping_province': ['Cajamarca'], 'shipping_district': ['Cajamarca']}>

如何正确保存 ProfileForm?

显示 UserForm 和 ProfileForm 的视图:

@transaction.atomic
def signupView(request):
    peru = Peru.objects.all()
    department_list = set()
    province_list = set()
    district_list = set()
    for p in peru:
        department_list.add(p.departamento)
    department_list = list(department_list)
    print("Department List: ", department_list)
    if len(department_list):
        province_list = set(Peru.objects.filter(departamento=department_list[0]).values_list("provincia", flat=True))
        print("Provice List: ", province_list)
        province_list = list(province_list)
        # print("dfsfs", province_list)
    else:
        province_list = set()
    if len(province_list):
        district_list = set(
            Peru.objects.filter(departamento=department_list[0], provincia=province_list[0]).values_list("distrito",
                                                                                                         flat=True))
        print("district List: ", district_list)
    else:
        district_list = set()

    if request.method == 'POST':
        user_form = SignUpForm(request.POST)
        profile_form = ProfileForm(district_list, province_list, department_list, request.POST)
        print("This is Profile Form: ", profile_form)
        print("Is Profile_Form valid: ", profile_form.is_valid())
        if user_form.is_valid() and profile_form.is_valid():
            user = user_form.save()
            username = user_form.cleaned_data.get('username')
            signup_user = User.objects.get(username=username)
            customer_group = Group.objects.get(name='Clientes')
            customer_group.user_set.add(signup_user)
            raw_password = user_form.cleaned_data.get('password1')
            user.refresh_from_db()  # This will load the Profile created by the Signal
            # print(user_form.cleaned_data)
            print("Form is valid: district_list, province_list, department_list")
            print(district_list, province_list, department_list)
            profile_form = ProfileForm(district_list, province_list, department_list, request.POST,
                                       instance=user.profile)  # Reload the profile form with the profile instance
            profile_form.full_clean()  # Manually clean the form this time. It is implicitly called by "is_valid()" method
            # print(profile_form.cleaned_data)
            profile_form.save()  # Gracefully save the form

            user = authenticate(username=username, password=raw_password)
            login(request, user)

            return redirect('cart:cart_detail')
    else:
        print("INVALID FORM")
        user_form = SignUpForm()

        profile_form = ProfileForm(district_list, province_list, department_list)
        print('end of profile postdata print')
        print(profile_form)
        print("Profile Data:")

    return render(request, 'accounts/signup.html', {
        'user_form': user_form,
        'profile_form': profile_form
    })

此行返回 false:

print("Is Profile_Form valid: ", profile_form.is_valid())

个人资料表格

class ProfileForm(ModelForm):

    def __init__(self, district_list, province_list, department_list, *args, **kwargs):
        super(ProfileForm, self).__init__(*args, **kwargs)
        self.fields['shipping_district'] = forms.ChoiceField(choices=tuple([(name, name) for name in district_list]))
        self.fields['shipping_province'] = forms.ChoiceField(choices=tuple([(name, name) for name in province_list]))
        self.fields['shipping_department'] = forms.ChoiceField(choices=tuple([(name, name) for name in department_list]))

    dni = forms.CharField(label='DNI', max_length=100, required=True)
    shipping_address1 = forms.CharField(label='Dirección de envío', max_length=100, required=True)
    shipping_address2 = forms.CharField(label='Dirección de envío 2 (opcional)', max_length=100, required=False)

    class Meta:
        model = Profile
        fields = ('dni', 'shipping_address1',
                  'shipping_address2', 'shipping_department', 'shipping_province', 'shipping_district')

更新 1:

    else:
        print("INVALID User_FORM")
        print(user_form.errors)
        print("INVALID Profile_FORM")
        print(profile_form.errors)


INVALID User_Form

INVALID Profile_Form
<ul class="errorlist"><li>shipping_province<ul class="errorlist"><li>Select a valid choice. Tarata is not one of the available choices.</li></ul></li><li>shipping_district<ul
 class="errorlist"><li>Select a valid choice. Estique is not one of the available choices.</li></ul></li></ul>
[25/Jan/2019 18:18:38] "POST /account/create/ HTTP/1.1" 200 16522
[25/Jan/2019 18:18:38] "GET /static/css/footer.css HTTP/1.1" 404 1767

【问题讨论】:

    标签: python django


    【解决方案1】:

    表单中的选择字段不需要值列表。您将有多个选项,但该字段将只有一个值。

    那么,试试这个:

     profile_form = ProfileForm(request.POST)
    

    并计算shipping_districtshipping_provinceshipping_department 的值作为表单中__init__ 的一部分。

    更新:

    如果为了查看错误更改您的代码:

    user_form_valid =  user_form.is_valid()
    profile_form_valid = profile_form.is_valid()
    
    if user_form_valid and profile_form_valid:
        # ...
    else:
        # print(user_form.errors)
        # print(profile_form.errors)
        # ...
    

    更新 #2

    您呈现给用户的表单中的选项与您在视图中绑定的选项不同,尝试初始化尝试找到一种方法来初始化这些选项,为每个 ProfileForm 设置相同的值你实例化。

    另一方面,我鼓励您在这种情况下使用FormSet

    【讨论】:

    • 使用:profile_form = ProfileForm(request.POST) 返回__init__() missing 2 required positional arguments: 'province_list' and 'department_list'
    • 我的意思是在您的构造函数中,您正在设置这些字段的选项,而不是值。
    • 是的,我明白了。但我如何通过shipping_districtshipping_provinceshipping_department 作为 POST 的一部分?我需要输入ProfileForm(shipping_deparment = request.POST.get('shipping_deparment'), shipping_province = request.POST.get('shipping_province'), shipping_district = request.POST.get('shipping_district'), request.POST)??
    • form.errorsform.is_valid 之后的值是多少?
    • 无法访问该部分,因为:if user_form.is_valid() and profile_form.is_valid(): 因为profile_form 无效,我无法通过该条件。请在我的代码中查看更多详细信息,并告诉我应该在哪里打电话给form.errors
    猜你喜欢
    • 2018-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多