Warm tip: This article is reproduced from serverfault.com, please click

python-如何将活动用户传递给Django ModelForms

(python - How to pass active user to Django ModelForms)

发布于 2020-11-28 02:06:57

在我的表单中,我必须过滤“承租人”选择字段,以便它仅显示与活动用户的组织相关联的承租人。因此,我只是将一个额外的参数传递给表单构造函数。当我加载(GET)表单时,这可以按预期工作。

但是当我提交(POST)表单时,我不断收到以下错误:

AttributeError: 'NoneType' object has no attribute 'organization_profile'

你知道是什么在激怒这吗?

Views.py

def create_booking(request):
    if request.method == "POST":
        form = BookingCreateForm(data=request.POST)
        if form.is_valid():
            data = form.cleaned_data
            booking = Booking.objects.create(
                status=data['status'],
                tenant = data['tenant'],
                apartment = data['apartment'],
                check_in = data['check_in'],
                check_out = data['check_out'],
                rent = data['rent'],
            )
            booking.save()

            return redirect('dashboard:dashboard')

    else:
        form = BookingCreateForm(user=request.user)
    return render(request, 'accounts/booking_form.html', {'form': form})

Forms.py

class BookingCreateForm(forms.ModelForm):
    class Meta():
        model = Booking
        fields = '__all__'
    
    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user',None)
        super(BookingCreateForm, self).__init__(*args, **kwargs)
        organization = self.user.organization_profile
        self.fields['tenant'] = forms.ChoiceField(choices=[
            (tenant.id, tenant.name)) for tenant in TenantProfile.objects.filter(organization=organization)
        ])

型号

class Booking(models.Model):
    STATUS_OPTIONS = [
        (0, 'Pending'),
        (1, 'Accepted'),
        (2, 'In-tenancy'),
        (3, 'Moved-out'),
        (4, 'Cancelled'),
    ]
    status = models.PositiveSmallIntegerField(choices=STATUS_OPTIONS, default=0)
    tenant = models.ForeignKey('TenantProfile', on_delete=models.CASCADE)
    apartment = models.ForeignKey('Apartment', on_delete=models.CASCADE)
    check_in = models.DateField(blank=False)
    check_out = models.DateField(blank=False)
    rent = models.DecimalField(max_digits=6, decimal_places=2, blank=False)
Questioner
Maxim Vallee
Viewed
11
Willem Van Onsem 2020-11-28 18:58:17

无论是GET请求还是POST请求,都需要传递用户,因此:

def create_booking(request):
    if request.method == 'POST':
        form = BookingCreateForm(data=request.POST, user=self.request.user)
        # …

除非tenantBooking的a是多少,否则CharField这将无法工作,你需要使用ModelChoiceField[Django-doc]例如:

class BookingCreateForm(forms.ModelForm):
    class Meta:
        model = Booking
        fields = '__all__'
    
    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user',None)
        super().__init__(*args, **kwargs)
        organization = self.user.organization_profile
        self.fields['tenant'].queryset = TenantProfile.objects.filter(
            organization=organization
        )

注意:你可以使用@login_required装饰器[Django-doc]将视图限制为仅通过身份验证的用户使用