ModelForm

时间:2016-01-17 21:37:53

标签: django django-forms modelform

我为我的应用程序设置页面创建了一个ModelForm(Django 1.9.1)。它应该以下列方式工作:

  1. 设置页面应包含多个文本字段,其中包含数据库中的值。
  2. 如果我更改任何字段,然后按"保存"按钮 - 它应该更新数据库中的相同字段,而不是添加新字段。
  3. 型号:

    class Settings(models.Model):
        pkey_path = models.CharField(max_length=255)
    
        class Meta:
            db_table = "t_settings"
    
        def __str__(self):
            return self.id
    

    形式:

    class SettingsForm(ModelForm):
        class Meta:
            model = Settings
            fields = ['pkey_path']
    

    查看:

    def settings_update(request):
        if request.method == "POST":
            form = SettingsForm(request.POST)
            if form.is_valid():
                form.save()
                return render(request, 't_settings/index.html', {'form': form})
        else:
            form = SettingsForm()
        return render(request, 't_settings/index.html', {'form': form})
    

    urls.py:

    app_name = 't_settings'
    urlpatterns = [
        url(r'^$', views.index, name='index'),
        url(r'^update/', views.settings_update, name='settings-update'),
    ]
    

    html表格:

    <form action="{% url 't_settings:settings-update' %}" method="post" class="form-horizontal">
                {% csrf_token %}
              <div class="box-body">
                <div class="form-group">
                  <label for="{{ form.pkey_path.id_for_label }}" class="col-sm-3 control-label">test</label>
                  <div class="col-sm-8">{{ form.pkey_path.errors }}
                    <input type="text" class="form-control"
                           name="{{ form.pkey_path.name }}"
                           id="{{ form.pkey_path.id_for_label }}"
                           placeholder="Path"
                           value="{{ form.pkey_path.value }}">
    

    我尝试了使用Django文档的不同方法,但无论如何我得到了:

    1. {{ form.pkey_path.value }}未在模板
    2. 中显示数据库中的值
    3. 表单本身有效,但在数据库中添加新行,而不是更新现有行

2 个答案:

答案 0 :(得分:0)

您可以覆盖模型的保存方法以检查pkey_path是否已存在并覆盖现有记录(如果存在)。

from django.core.exceptions import ObjectDoesNotExist

class Settings(models.Model):
    pkey_path = models.CharField(max_length=255)

    class Meta:
        db_table = "t_settings"

    def __str__(self):
        return self.id

    def save(self, *args, **kwargs):
        try:
            # will update existing record
            self.pk = Settings.objects.get(pkey_path=self.pkey_path).pk 
        except ObjectDoesNotExist:
            # if not existing record, will write a new one
            self.pk = None  
        # call the original save method
        super(Settings, self).save(*args,**kwargs)

请注意,如果现在成功保存为您的视图列表,则只有与该表单关联的实例。

如果此视图仅用于更新现有记录,则可以执行以下操作,以便始终存在一个实例:

查看:

from django.shortcuts import get_object_or_404
from my_app.models import Settings
def settings_update(request, pkey_path=None):
    instance = get_object_or_404(Settings,pkey_path=pkey_path)

    if request.method == "POST":
        form = SettingsForm(request.POST, instance=instance)
        if form.is_valid():
            form.save()
            return render(request, 't_settings/index.html', {'form': form})
    else:
        form = SettingsForm(instance=instance)
    return render(request, 't_settings/index.html', {'form': form})

您必须为urls.py添加一个条目,其中包含(?P<pkey_path>.+)此视图的条目,以便它获取现有的设置记录。要添加新记录,您可以编写settings_add视图,或者如果没有pkey_path提供给视图,则使instance=Settings()实例化设置模型的空实例。

编辑#2 :处理新记录与现有记录所需的内容比视图中的内容要多。这是实现这一目标的一种方法。

在urls.py中:

urlpatterns = patterns('',
    url(r'^settings/$',views.settings_update, name='add-settings'),
    url(r'^settings/(?P<pkey_path>.+)/$',views.settings_update, name='update-settings'),
    # ...
)

在views.py中:

from django.shortcuts import get_object_or_404
from my_app.models import Settings


def settings_update(request, pkey_path=None):
    if pkey_path: # if supplied via url, find record w/ pkey_path. If pkey_path supplied matches no records, return 404. 
        instance = get_object_or_404(Settings,pkey_path=pkey_path)
    else: # if pkey_path not supplied in url, create empty instance
        instance = Settings() # instantiate new Settings object

    if request.method == "POST": # if post submitted, save if valid
        form = SettingsForm(request.POST, instance=instance)
        if form.is_valid():
            form.save()
            return render(request, 't_settings/index.html', {'form': form})
    else: # no post submitted
        form = SettingsForm(instance=instance)
    return render(request, 't_settings/index.html', {'form': form})

答案 1 :(得分:0)

您在视图中没有做任何事情要么将现有的设置条目传递给表单,要么告诉表单在保存时更新哪一个。你需要有一些方法来识别你想要的对象,一开始,这通常意味着接受URL中的id或slug;然后你需要在初始实例化和保存之前查询该对象并将其传递给带有instance参数的表单。