【问题标题】:Add values to empty ModelForm将值添加到空 ModelForm
【发布时间】:2014-10-09 15:16:32
【问题描述】:

我有一个向默认用户模型添加额外属性的模型

class Perfil(models.Model):
    usuario = models.OneToOneField(User)
    telefono = models.CharField(max_length=140,null=True,blank=True)
    departamento = models.ForeignKey(Departamento,null=True,blank=True)
    menus = models.ManyToManyField(Menu,null=True,blank=True)
    def __unicode__(self):
        return self.usuario.username 

我有 ModelForms 来创建一个新用户

class UsuarioForm(ModelForm):
    class Meta:
        model = User
        fields = ("username","password","first_name","last_name","email","is_active",)

class PerfilForm(ModelForm):
    class Meta:
        model = Perfil
        exclude = ("usuario",)

我的视图看起来像这样。

def nuevo_usuario(request):
    if request.method == 'POST':
        form = UsuarioForm(request.POST, prefix='user')
        form2 = PerfilForm(request.POST, prefix='perfil')
        if form.is_valid() * form2.is_valid():
            menus = request.POST.getlist("perfil-menus")
            user = User.objects.create_user(username=request.POST.get("user-username",""),email=request.POST.get("user-email",""),password=request.POST.get("user-password",""))
            user.first_name = request.POST.get("user-first_name","")
            user.last_name = request.POST.get("user-last_name","")
            user.is_active = request.POST.get("user-is_active","True")
            user.save()
            perfil = Perfil()
            perfil.usuario = user
            perfil.telefono = request.POST.get("perfil-telefono","")
            perfil.departamento = Departamento.objects.get(pk=request.POST.get("perfil-departamento",""))           
            perfil.save()
            men = Menu.objects.filter(pk__in=menus)
            for m in men:
                perfil.menus.add(m)
            form = UsuarioForm(prefix='user')
            form2 = PerfilForm(prefix='perfil')
    else:
        form = UsuarioForm(prefix='user')
        form2 = PerfilForm(prefix='perfil')
    return render(request,'nuevousuario.html',locals())

在这个方法中,我只用一个简单的方式渲染表单

<form id="form" method="post" action=''>{% csrf_token %}
                <table>
                {{form}}
                {{form2}}
                </table>
                <p><input type="submit" value="Registrar"/></p>
            </form>

但是我想用一些数据填充输入值来编辑用户,但不仅是用户,我还需要编辑“Perfil”值。

注意:“菜单”字段在 HTML 中显示为

对不起,西班牙代码,我在一家拉丁公司工作。

【问题讨论】:

  • 你的问题是什么?您想使用用户信息创建表单以进行编辑?
  • 为什么直接从 POST 数据中设置对象的值,而不是从表单中清除数据? Django 还提供了一个 UserCreationForm。
  • 这是正确的@HasanRamezani,我想填写表格进行编辑。
  • 我不知道如何使用 UserCreationForm @Brandon,有什么区别?
  • 不同之处在于,通过直接从 POST 数据设置值,您绕过了表单类提供的所有验证。永远不要相信用户提交的数据。我的建议是看看contrib.auth.forms

标签: django django-models django-forms


【解决方案1】:

我仍然不确定你在问什么,但让我们稍微清理一下。

首先,您需要利用来自django.contrib.auth.forms 的内置UserCreationForm。其次,从不直接使用表单帖子中的数据来水合模型对象,因为这完全绕过了由形成类。第三,视图可以大大简化。我假设您使用的是 Django 1.7:

# forms.py

from django import forms

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User

from .models import Perfil

class UsarioForm(UserCreationForm):
    class Meta:
        model = User
        exclude = ()

class PerfilForm(forms.ModelForm):
    class Meta:
        model = Perfil
        exclude = ('usario',)


# views.py

from django.shortcuts import render

from .forms import UsarioForm, PerfilForm

def nuevo_usario(request):
    usario_form = UsarioForm(request.POST or None)
    perfil_form = PerfilForm(request.POST or None)

    if request.method == 'POST':
        if usario_form.is_valid() and perfil_form.is_valid():
            usario = usario_form.save()
            perfil = perfil_form.save(commit=False)
            perfil.usario = usario
            perfil.save()
            perfil.save_m2m()

    return render(request, 'nuevousario.html',
        {'usario_form': usario_form, 'perfil_form': perfil_form})

让 ModelForm 类完成它们的设计任务 - 从经过处理的数据创建对象。您不必在视图中手动完成所有这些工作。您的模板代码也需要一些帮助:

# nuevousario.html

<form action="." method="post" enctype="application/x-www-form-urlencoded">
    <table>
        <tfoot>
            <tr>
                <td>
                    {% csrf_token %}
                    <button type="submit">Registrar</button>
                </td>
            </tr>
        </tfoot>
        <tbody>
            {{ usario_form.as_table }}
            {{ perfil_form.as_table }}
        </tbody>
    </table>
</form>

您确定要为此表单使用表格吗?真的是表格数据吗?在语义上似乎不太正确。您可以考虑使用有序列表:&lt;ol&gt;

希望对你有所帮助。

【讨论】:

  • 哇...这是一个巨大的帮助,我真的很感谢你,我会做出改变,但是...实际上我的主要问题是我不知道如何编辑用户,我的意思是,如何用要修改和保存更新用户信息的实际数据填写表格。我是否需要制作与此类似的另一个视图?如何从我的数据库中获取数据并将其放入表单的值字段中?
  • 不客气。您可以在使用 initial 关键字参数实例化表单时将数据传递给表单:docs.djangoproject.com/en/1.7/ref/forms/api/…
  • 编辑现有用户实例与此类似,但您需要使用 instance 参数来传递数据。
  • 优秀...我找到了答案。我在views.py和我的模板中更改了一些东西......我会发布它。再次感谢哥们!
  • 这个视图有很多内容。我建议将其分成两个单独的视图:一个用于创建,一个用于编辑。更容易看到发生了什么。更容易测试。更好地分离关注点。
【解决方案2】:

使用@Brandon 的 cmets,我已经像这样更改了我的代码。

我添加了两个 URL,一个用于空表单,另一个用于获取用户数据

#urls.py

url(r'^usuarios/$','main.views.usuarios',name='usuarios'),
url(r'^usuarios/(\d+)$','main.views.usuarios',name='editar_usuario'),

在只能处理两个 URL 的一个视图中,我查找 user_id,如果没有,则显示空表单,否则我获取用户和配置文件数据,并使用 instance 放置数据进入输入字段

#views.py

def usuarios(request,id_usuario=None):
    usuarios = User.objects.all()
    #Pide información de un usuario - Ask for user Info
    if id_usuario is not None: 
        usr = User.objects.get(pk=id_usuario)
        prf = Perfil.objects.get(usuario=usr)
        usuario_form = UsuarioForm(instance=usr)
        perfil_form = PerfilForm(instance=prf)
    #El formulario está vacío para nuevo usuario -Empty User Form
    else:
        usuario_form = UsuarioForm(request.POST or None)
        perfil_form = PerfilForm(request.POST or None)
    #Botón Registrar - Register Button pressed
    if request.method == 'POST':
        #Si está editando se obtiene la instancia del que quiere guardar - If edit, then gets the instance to save
        if id_usuario is not None:
            usuario_form = UsuarioForm(request.POST, instance=usr)
            perfil_form = PerfilForm(request.POST, instance=prf)
        #Finalmente guarda - Finally Saves the form
        if usuario_form.is_valid() and perfil_form.is_valid():
            usuario = usuario_form.save()
            perfil = perfil_form.save(commit=False)
            perfil.usuario = usuario
            perfil.save()
            HttpResponseRedirect('/usuarios/')
    return render(request,'usuarios.html',locals())

最后我在表单中添加了一些 bootstrap/crispy 并使它看起来更好。

#Template usuarios.html
{% block content %}
<div class="row">
    <div class="col-md-4">
        <h3>Usuarios Registrados</h3>
        <ul>
        {% for usuario in usuarios %}
            <li><a class="usuario_link" href="/usuarios/{{usuario.pk}}">{{ usuario.username }} - {{ usuario.first_name }}</a></li>
        {% empty %}
            <li>No hay usuarios.</li>
        {% endfor %}
        </ul>
    </div>
    <div class="col-md-5">
        <fieldset>
            <form id="form" method="post" action=''>{% csrf_token %}
                {{usuario_form|crispy}}
                {{perfil_form|crispy}}
                <p><input class="btn btn-default" type="submit" value="Registrar"/></p>
            </form>
        </fieldset>
    </div>
    <div class="col-md-2 col-md-offset-1">
        <a href="/usuarionuevo/"><input class="btn btn-default" type="button" value="Nuevo Usuario" /></a>    
    </div>
</div>
{% endblock %}

我希望它对某人有所帮助,我是 python 和 django 的新手,所以再次感谢 @Brandon 的精彩咨询。

如果有人有更好的答案,请告诉我。

【讨论】:

    猜你喜欢
    • 2014-07-21
    • 2013-01-11
    • 2015-06-25
    • 2018-03-14
    • 2015-10-13
    • 1970-01-01
    • 2017-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多