首页 > 解决方案 > 如何将活动用户传递给 Django ModelForms

问题描述

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

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

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

知道这是什么原因吗?

视图.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})

表格.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)
        ])

模型.py

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)

标签: pythondjango

解决方案


您需要在 GET 请求POST 请求的情况下传递用户,因此:

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

除非tenant您的Booking是 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]将视图限制为经过身份验证的用户的视图 。


推荐阅读