【问题标题】:form instance is not shown表单实例未显示
【发布时间】:2013-07-07 05:46:01
【问题描述】:

views.py

@login_required
@user_passes_test(lambda u: u.is_superuser)
def date_format(request):
    save_msg = ''
    user = request.user
    try:
        settings = Settings.objects.get(user=user.id)
        settingsForm = SettingsForm(instance=settings)
    except:
        settings = None
        settingsForm = SettingsForm(initial={'date_format':0, 'time_format':0})
    if request.method == 'POST':
        settingsForm = SettingsForm(request.POST, instance=settings)
        if settingsForm.is_valid():
            settings = settingsForm.save(commit=False)
            settings.user = user
            settings.save()
            save_msg = 'Date format has been updated.'
    return render(request,'setting/date_format.html',
                           {
                            'about_menu': True,
                            'date_tab':True,
                            'SettingsForm':settingsForm,
                            'save_msg': save_msg,
                           })

models.py

class Settings(models.Model):  
    user = models.ForeignKey(User, null=True)
    date_format = models.BooleanField('Date format', default=False)
    time_format = models.BooleanField('Time format', default=False)
    is_contactlist_active = models.BooleanField('Contacts', default=True)

对于初始值,显示默认格式。但是,如果我将该值保存到数据库,则值正在保存,但未显示所选格式(表单实例)。

【问题讨论】:

  • 你确定这个视图代码有效吗?
  • 是的,它正在保存值问题是,表单没有保存值,总是显示空表单
  • 你还在使用旧的 render_to_response 吗?渲染快捷方式看起来更干净了。
  • @christophe31,替换为“render”问题仍然是他们的。
  • 我的猜测是,您的代码正在触及except 块,然后settingsForm = SettingsForm(request.POST, instance=settings) 评估为settingsForm = SettingsForm(request.POST, instance=None),因此出现了问题。另外,看起来你的视图需要一个 login_required 装饰器

标签: django django-models django-forms django-templates django-views


【解决方案1】:

说实话,您的代码很难遵循 - 并且很难测试。首先用空函数拆分它:

def date_format(request):
    settings = _retrieve_user_settings() # see below
    form = _prepare_settings_form(settings) # see below

    if request.method == 'POST':
        form = _prepare_settings_form(settings, request.POST)
        if form.is_valid():
            _save_settings(form) # see below
            save_msg = 'Date format has been updated.'

     return render(request,'setting/date_format.html',
                           {
                            ...
                           }
      )


def _retrieve_user_settings()
    """
    get the logged-in user settings or None if the user is logged off or doesn't have any settings
    """
    pass

def _prepare_settings_form(settingsInstance=None, data=None)
    """
    prepare the form with the settings provided
    use default values if the settings are empty (to pre-fill the form)
    """
    pass

def _save_settings(form) # this one is even better out of the view
    # throw exception if the form wasn't validated
    # retrieve the user for the new settings
    # save the settings (attached to the user)
    pass

在开始实现这 3 个新的小函数的代码之前,编写它们的单元测试,你一定会得到一个很好的工作代码。如果您认为这太费力了,请查看此 StackOverflow 线程的大小以及您一直在执行的手动测试的数量;)

这只是一个示例,您可以以不同的方式拆分代码 - 但您确实应该避免在 try 语句中使用长视图和长代码...

【讨论】:

    【解决方案2】:

    我不知道“当前答案”是什么样的,因为它已被删除,但我可以尝试向您建议几件事:

    ...
    user = request.user
    try:
        settings_inst = Settings.objects.get(user=user.id)
        settings_init = None
        settingsForm = SettingsForm(instance=settings_inst)
    except:
        settings_init = {'date_format':0, 'time_format':0}
        settings_inst = None
        settingsForm = SettingsForm(initial=settings_init)
    
    if request.method == 'POST':
    
        ## if settings_inst is None, you should fallback using the initial settings dict ##
        if settings_inst:
            settingsForm = SettingsForm(request.POST, instance=settings_inst)
        else:
            settingsForm = SettingsForm(request.POST, initial=settings_init)
    
        if settingsForm.is_valid():
            ...
    

    在您的情况下,如果您使用 settings = None,它将在您检查是否发生 POST 请求之前覆盖您使用 initial 传递的数据,从而使您每次使用 {'date_format' ...} 初始字典时都会松动。

    注意:我将设置重命名为 settings_instsettings_init 只是为了更容易向您解释(并从您的角度了解发生了什么)。当然重新排列代码,因为它最适合您的需求(又名:我不知道这是否会破坏您代码中的其他内容。)

    【讨论】:

    • 好吧,不要从 SO 中复制和粘贴代码并期望它能够正常工作,这是第一条规则。顺便说一句,我正在编辑,也许会更好。
    • No Samuele,问题没有解决。form 实例化没有发生。
    【解决方案3】:

    我怀疑您收到了MultipleObjectsReturnedSettings.objects.get(user=user.id) 的其他异常。

    因为您在用户上有ForeignKey,所以一个用户可以有多个Settings

    您可以将视图更改为

    @login_required
    @user_passes_test(lambda u: u.is_superuser)
    def date_format(request):
        save_msg = ''
        user = request.user
        try:
            #to update latest settings for an user
            settings = Settings.objects.filter(user=user.id).latest('id')
            settingsForm = SettingsForm(instance=settings)
        except:
            settings = None
            settingsForm = SettingsForm(initial={'date_format':0, 'time_format':0})
        if request.method == 'POST':
        #your existing code
        ...
    

    或者,如果您只想为每个用户设置一个设置,请使用 OneToOne 关系作为

    class Settings(models.Model):  
        user = models.OneToOneField(User, null=True)
        ....
    

    然后你可以直接在视图中引用它为request.user.settings。并将视图更新为

    @login_required
    @user_passes_test(lambda u: u.is_superuser)
    def date_format(request):
        save_msg = ''
        user = request.user
        if request.user.settings:
            settingsForm = SettingsForm(instance=request.user.settings)
        else:
            settings = None
            settingsForm = SettingsForm(initial={'date_format':0, 'time_format':0})
        if request.method == 'POST':
        ...
    

    【讨论】:

    • 我尝试了这种方法,如果我使用最新('id'),为每个表单发布一个新的数据行,所以表单是空的,它在表单中显示初始值.Form 实例化没有发生
    【解决方案4】:

    我正在结合其他人的几种解决方案,请尝试:

    @login_required
    @user_passes_test(lambda u: u.is_superuser)
    def date_format(request):
        save_msg = ''
        user = request.user
        try:
            settings_instance = Settings.objects.filter(user=user.id).latest('id')
            settings_initial = None
            settingsForm = SettingsForm(instance=settings_instance)
        except Settings.DoesNotExist:
            settings_instance = None
            settings_initial = {'date_format':0, 'time_format':0}
            settingsForm = SettingsForm(initial=settings_initial)
    
        print settings_instance  # DEBUG here
    
        if request.method == 'POST':
            if settings_instance:   
                settingsForm = SettingsForm(request.POST, instance=settings_instance)
            else:
                settingsForm = SettingsForm(request.POST, initial=settings_initial)
    
            if settingsForm.is_valid():
                settings = settingsForm.save(commit=False)
                settings.user = user
                settings.save()
                save_msg = 'Date format has been updated.'
    
        return render(request, 'setting/date_format.html', {
            'about_menu': True,
            'date_tab':True,
            'SettingsForm':settingsForm,
            'save_msg': save_msg,
        })
    

    如果不行,请在我指定的点继续调试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-29
      • 2021-04-15
      • 1970-01-01
      相关资源
      最近更新 更多