Django模型表单在特定数据库中是_valid()

2024-05-19 00:02:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我在settings.py('default'和'banco1')中定义了两个不同的数据库连接。在

然后在某个视图中,我收到一个帖子,其中包含一些我想根据我创建的ModelForm进行验证的数据:

 product_form = ProductForm(request.POST)
 if product_form.is_valid():

产品型号:

^{pr2}$

表格:

class ProductForm(ModelForm):
    class Meta:
        model = Product
        fields = ['name', 'description', 'abbreviation', 'category', 'metric']

观点:

 def create(request):
        if request.method != 'POST':
            return JsonResponse('Operação inválida', safe=False)

        product_form = ProductForm(request.POST)
        if product_form.is_valid():
            f = product_form.save(commit = False)
            f.save(using=request.session['database'])
            return HttpResponse("Novo product salvo com sucesso")
        else:
            return HttpResponse("Impossível salvar product. Verifique os campos")

产品模型被假定总是保存在“banco1”数据库中,因此FK验证应该从“banco1”数据库中查询,但是每当我试图用product_form.is_valid()进行验证时,Django就试图查询“default”数据库并抛出验证错误,因为FK约束在“default”数据库中无法满足。在

我如何设置一个模型表单来对手动选择的数据库进行验证?在

编辑

建议我利用一个数据库路由器模式来选择合适的数据库配置,这很好。我的问题是,这个选择应该基于一些标准,而不仅仅是模型。如何将一些变量从视图传递到db router类中的db_for_read方法?在

编辑2

新建ProductForm类

class ProductForm(ModelForm):
    class Meta:
        model = Product
        fields = ['name', 'description', 'abbreviation', 'category', 'metric']

    def __init__(self,database):
        category = forms.ModelChoiceField(queryset=Category.objects.using(database).all())

尝试在我的视图中实例化表单,如下所示:

product_form = ProductForm(request.POST, request.session['database'])

这给了我一个错误:

init() takes 2 positional arguments but 3 were given

我知道我重写__init__方法的方式是不正确的,但我要用python来实现这一点。在

编辑3

上次错误:

Traceback:

File "C:\Users\Pavarine\Documents\Visual Studio 2015\Projects\gims\gims\env\lib\site-packages\django\core\handlers\base.py" in get_response 149. response = self.process_exception_by_middleware(e, request)

File "C:\Users\Pavarine\Documents\Visual Studio 2015\Projects\gims\gims\env\lib\site-packages\django\core\handlers\base.py" in get_response 147. response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\Pavarine\Documents\Visual Studio 2015\Projects\gims\gims\gims\apps\inventory\views.py" in create 247. if product_form.is_valid():

File "C:\Users\Pavarine\Documents\Visual Studio 2015\Projects\gims\gims\env\lib\site-packages\django\forms\forms.py" in is_valid 161. return self.is_bound and not self.errors

File "C:\Users\Pavarine\Documents\Visual Studio 2015\Projects\gims\gims\env\lib\site-packages\django\forms\forms.py" in errors 153. self.full_clean()

File "C:\Users\Pavarine\Documents\Visual Studio 2015\Projects\gims\gims\env\lib\site-packages\django\forms\forms.py" in full_clean 362. self._clean_fields()

File "C:\Users\Pavarine\Documents\Visual Studio 2015\Projects\gims\gims\env\lib\site-packages\django\forms\forms.py" in _clean_fields 374. value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))

File "C:\Users\Pavarine\Documents\Visual Studio 2015\Projects\gims\gims\env\lib\site-packages\django\forms\widgets.py" in value_from_datadict 231. return data.get(name)

Exception Type: AttributeError at /inventory/product/create Exception Value: 'tuple' object has no attribute 'get'


Tags: pyselfform数据库requestformsproductusers
1条回答
网友
1楼 · 发布于 2024-05-19 00:02:16

要启用路由器,只需将其添加到setting.py中的DATABASE_ROUTERS,请参阅此处的详细信息:https://docs.djangoproject.com/en/1.9/topics/db/multi-db/#using-routers

每个router方法都得到hints字典,它应该包含代表所使用的模型实例的instance键。根据您希望从视图中获取的信息,您可能会很好地使用实例属性中的信息。请看这里:https://docs.djangoproject.com/en/1.9/topics/db/multi-db/#topics-db-multi-db-hints。在

即:

def db_for_read(self, model, **hints):
    model_instance = hints.get('instance')   
    if model_instance is not None:
        pass
        #perform actions with model_instance attributes
    return None

除此之外,我不认为有其他直接的方式将信息从活动视图传递到路由器,因为路由器应该与模型一起工作,并根据所使用的模型做出决策。在

数据库路由器用于模型层的自动数据库选择,但模型方法允许手动选择数据库。请参阅示例:https://docs.djangoproject.com/en/1.9/topics/db/multi-db/#manually-selecting-a-database

所以另一种解决方案是重新定义form类的方法,即save()(参见https://docs.djangoproject.com/en/1.9/topics/forms/modelforms/#the-save-method),并手动保存表单数据,指定要与using参数一起使用的DB。一、 电子邮箱:

^{pr2}$

在评论中,我建议将需要针对其他数据库验证的字段进行子类化,但可能还有更简单的方法。。。因为它是FK字段,它可能是ModelChoiceField的实例,它接受构造函数中的queryset参数,因此您可以提供它,即:

class ProductForm(ModelForm):
   category_field = forms.ModelMultipleChoiceField(queryset=Category.objects.using('banco1'))
    ...

{见^

对EDIT2的回答

你重新定义构造函数的方式,database参数得到request.POST和{}没有映射到任何东西,这就是为什么会出现错误。在

您应该考虑其他参数,同时调用超类构造函数,否则会破坏MRO,因此,应该使用以下方法:

class ProductForm(ModelForm):
    ...

    def __init__(self, *args, db_to_use='default', **kwargs):
        super(ProductForm, self).__init__(*args, **kwargs)
        #category = forms.ModelChoiceField(queryset=Category.objects.using(db_to_use).all())
        #the below line suggested as improvement by Alasdair and confirmed as working by Pavarine, so I updated the answer here
        self.fields['category'].queryset = Category.objects.using(database).all()

然后像往常一样,使用命名参数:

product_form = ProductForm(request.POST, db_to_use=request.session['database'])

相关问题 更多 >

    热门问题