使用get_or_create的Django表单

时间:2010-02-19 16:23:11

标签: django django-forms

我正在使用Django ModelForms来创建表单。我已经设置了表单并且工作正常。

form = MyForm(data=request.POST)

if form.is_valid():
    form.save()

我现在想要的是首先检查表单以查看是否存在相同的记录。如果是的话,我希望它获取该对象的id,如果不是,我希望它将它插入数据库,然后给我该对象的id。这可能是使用类似的东西:

form.get_or_create(data=request.POST)

我知道我能做到

form = MyForm(instance=object)

在创建表单时但这不起作用,因为我仍然想要没有对象实例的情况

编辑:

说我的模特是

class Book(models.Model):
    name = models.CharField(max_length=50)
    author = models.CharField(max_length=50)
    price = models.CharField(max_length=50)

我想要一张可以填写书籍的表格。但是,如果数据库中已经有一本书具有相同的名称,作者和价格,我显然不希望再次添加此记录,所以只想找出它的ID而不是添加它。

我知道Django中有一个函数; get_or_create这样做但是表格有类似的东西吗?或者我必须做类似

的事情
if form.is_valid(): 
    f = form.save(commit=false)
    id = get_or_create(name=f.name, author=f.author, price=f.price)

由于

5 个答案:

答案 0 :(得分:30)

我喜欢这种方法:

if request.method == 'POST':
    form = MyForm(request.POST)
    if form.is_valid():
       book, created = Book.objects.get_or_create(**form.cleaned_data)

这样你就可以利用模型表单的所有功能(除了.save())和get_or_create快捷方式。

答案 1 :(得分:1)

在回发发生之前,您只需要两个案例,例如

if id:
    form = MyForm(instance=obj)
else
    form = MyForm()

然后你可以在回发中调用form.save(),Django会处理其余的事情。

答案 2 :(得分:1)

“如果存在相同的记录”是什么意思?如果这是一个简单的ID检查,那么您的视图代码将如下所示:

if request.method == 'POST':
    form = MyForm(request.POST)
    if form.is_valid():
        form.save()
else:
    if get_id:
        obj = MyModel.objects.get(id=get_id)
        form = MyForm(instance=obj)
    else:
        form = MyForm()

这里的概念是在GET请求上进行检查,这样在保存的POST上,Django已经确定这是新记录还是现有记录。

如果对相同记录的检查更复杂,则可能需要稍微改变逻辑。

答案 3 :(得分:0)

我会这样做 -

if request.method == 'POST':
    form = MyForm(request.POST)
    if form.is_valid():
        name   = form.cleaned_data['name']
        author = form.cleaned_data['author']
        price  = form.cleaned_data['prince']

        if name and author and price:
            book, created = Book.objects.get_or_create(name=name, \
              author=author, price=price)

            if created:
                # fresh entry in db.
            else:
                # already there, maybe update?

            book.save()

答案 4 :(得分:0)

根据答案和评论,我必须为我的案例创建一个不同的解决方案,其中包括在基础模型上使用unique_together。您可能会发现此代码也很有用,因为我实际上使它非常通用。

我在form.save()方法中使用自定义代码来创建新对象,因此我不想简单地不使用form.save()调用。我必须在form.save()方法中检查我的代码,我认为这是一个合理的位置。

我有一个实用功能来压缩迭代。

def flatten(l, a=list()):
    """ 
        Flattens a list.  Just do flatten(l).
        Disregard the a since it is used in recursive calls.
    """
        for i in l:
            if isinstance(i, Iterable):
                flatten_layout(i, a)
            else:
                a.append(i)
        return a

ModelForm中,我覆盖了validate_unique()方法:

def validate_unique(self):
    pass

这是关于我的保存方法的样子:

def save(self, commit=True):
    unique_fields = flatten(MyObject._meta.unique_together)
    unique_cleaned_data = {k: v for k, v in self.cleaned_data.items() if k in unique_fields}
    # check if the object exists in the database based on unique data
    try:
        my_object = MyObject.objects.get(**unique_cleaned_data)
    except MyObject.DoesNotExist:
        my_object = super(MyModelFormAjax, self).save(commit)
        # -- insert extra code for saving a new object here ---
    else:
        for data, value in self.cleaned_data.items():
            if data not in unique_fields:
                # only update the field if it has data; otherwise, retain
                #   the old value; you may want to comment or remove this
                #   next line
                if value:
                    setattr(my_object, data, value)

        if commit:
            my_object.save()
    return my_object