Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django 在ModelForm中将模型字段与非模型字段映射_Django - Fatal编程技术网

Django 在ModelForm中将模型字段与非模型字段映射

Django 在ModelForm中将模型字段与非模型字段映射,django,Django,我几乎花了一整天的时间阅读有关forms和ModelForms的文档。我设法使用了基本的东西,但现在我遇到了真正的麻烦,因为我在文档中没有找到任何关于将模型字段映射到非模型字段的提示。这就是我的意思: >>> from monitor.forms import ProcessForm >>> from remusdb.models import Process >>> >>> p = Process(name="test1

我几乎花了一整天的时间阅读有关
forms
ModelForms
的文档。我设法使用了基本的东西,但现在我遇到了真正的麻烦,因为我在文档中没有找到任何关于将模型字段映射到非模型字段的提示。这就是我的意思:

>>> from monitor.forms import ProcessForm
>>> from remusdb.models import Process
>>> 
>>> p = Process(name="test1", path="/tmp/config/a.cnf", author="pablo")
>>> f = ProcessForm(instance=p)
>>> print f["filename"].value()
---> here I want to get "a.cnf"
我有这个模型:

class Process(models.Model):
    key         = models.CharField(max_length=32, default="")
    name        = models.CharField(max_length=30)
    path        = models.CharField(max_length=215)
    author      = models.CharField(max_length=100)
    canparse    = models.NullBooleanField(default=False)
    last_exec   = models.DateTimeField(null = True)
    last_stop   = models.DateTimeField(null = True)
    last_change = models.DateTimeField(null = True, auto_now=True)
用户要修改的唯一字段是
name
author
<代码>路径是我的进程的配置文件的绝对真实路径。目录是固定的,用户不关心目录是
/home/measure/conf
还是
/var/which
),他们只关心文件名。这就是为什么我希望在我的
ModelForm
中有一个
filename
字段

我的表单如下所示:

class ProcessForm(MonitorForm):
    filename = forms.CharField(max_length=250)
    class Meta:
        model  = Process
        fields = ('name', 'filename', 'author')
现在,我想要的是
filename
包含存储在
Process.path
中的文件名,而不是整个路径,这就是我的意思:

>>> from monitor.forms import ProcessForm
>>> from remusdb.models import Process
>>> 
>>> p = Process(name="test1", path="/tmp/config/a.cnf", author="pablo")
>>> f = ProcessForm(instance=p)
>>> print f["filename"].value()
---> here I want to get "a.cnf"
问题是调用
ProcessForm(instance=p)
后,我不知道如何将
a.cnf
写入
filename
字段。我曾想过在
clean
函数中执行此操作,但我不确定这是否是一个好地方。我认为现在已经太晚了,因为这些字段或多或少都是只读的,一旦初始化,就不能更改它们的值。那我该怎么做呢?我是否应该创建一个自定义字段并覆盖
\uuuu init\uuu

我是从阅读中得到这个想法的,我想先测试一下。我不想先重写init,我想先使用
to_python
方法,就像文档中那样。因此,我创建了类
RemusFilenameField

class RemusFilenameField(forms.CharField):
    def to_python(self, value):
        print "to_python's value is %s" % value
        return value.upper()

    def clean(self, value):
        print "clean's value is %s" % value
        return value.upper()
并将
ProcessForm
上的
filename
行更改为

filename = RemusFilenameField(max_length=250)
我添加了打印以查看在何处/何时调用此方法。但根本不调用这些方法。我怀疑是因为表单没有边界。因此,我改为:

>>> p = {"name": "test1", "filename": "a.cnf", "author": "pablo"}
>>> f = ProcessForm(p)
>>> f.is_valid()
clean's value is a.cnf
True
>>> print f["filename"].value()
a.cnf
to_python
方法也没有被调用,我希望看到
A.CNF
,因为
clean
返回不同的东西

我不知道如何解决这个问题,甚至不知道这是否是一个好主意。我的下一个问题是当执行
f.save()
时,必须从
filename
生成正确的
路径
,并存储在
实例中。我会用
clean
方法来做,或者有更好的选择吗

编辑:我想我有一个创建表单的解决方案(我必须阅读整个源代码,以便在
python2.6/site packages/django/forms/models.py
中识别
model_to_dict
用法:

from django.forms.models import model_to_dict
import os

class ProcessForm(MonitorForm):
   filename = RemusFilenameField(max_length=250)
   def __init__(self, *args, **kwargs):
       super(ProcessForm, self).__init__(*args, **kwargs)
       try:
           proc = kwargs["instance"]
           filename = os.path.basename(proc.path)
           self.initial.update({'filename': unicode(filename)})
       except:
           pass
   class Meta:
       model  = Process
       fields = ('name', 'filename', 'author')
它知道如何工作:)现在我必须找出如何修复
save()
方法save()方法是在表单中放置任何附加保存逻辑的合适位置

def save(self, commit=True):
    proc = super(ProcessForm, self).save(commit=False)
    filename = cleaned_data['filename']
    # additional logic to alter filename
    proc.path = filename
    if commit:
        proc.save()
    return proc

在表单中对字段调用
到_python()
方法时,您的代码是正确的,但您必须从以下方面获取值:

如果您需要模型保存的一些逻辑,您可以覆盖模型中的
save()
。在中也有描述


<>你也应该考虑重写<代码> SAVER()>代码>如DrWWMAN所说的,它不会影响你在代码中从代码中的其他地方调用模型实例上的<代码> SAVER()/Cult>方法的代码。这是有道理的,而且比“加载”部分更容易。在阅读了django.forms.models的源代码之后,这很有意义。是的,谢谢。我一点也没有想到清理过的数据。问题是may view仍然没有显示
A.CNF
,而是
A.CNF
。但是我找到了一个从一开始就有效的解决方案,尽管我对它不是很满意。如果
ModelForm
的内部部分发生更改,则必须再次更改我的代码。