【问题标题】:Pass related object's field in Django ModelForm在 Django ModelForm 中传递相关对象的字段
【发布时间】:2018-07-03 19:31:35
【问题描述】:

我有一个扩展 django.contrib.auth.models.User 的 Django 模型类:

class MyModel(models.Model):
  user = models.OneToOneField(User, models.CASCADE, unique=True)
  bio = models.TextField()
  date_of_birth = models.DateField()

我正在使用这个模型制作一个 ModelForm:

class MyModelForm(forms.ModelForm):

  class Meta:
    model = MyModel
    fields = ['bio', 'date_of_birth']

如何告诉 MyModelForm 接受用户的字段,例如 usernamefirst_namelast_name

类 Meta 字段中的示例我可以添加 ['bio', 'date_of_birth', 'user'] 但这只会为我提供下拉列表以选择 MyModelForm 中的 MyModel 应与谁相关。

执行['bio', 'date_of_birth', 'user.first_name'] 会引发异常django.core.exceptions.FieldError: Unknown field(s) (user.first_name) specified for MyModel

编辑:这是回溯 https://pastebin.com/0T42VKEP

【问题讨论】:

  • 嘿,您可以添加相关字段,如user__username 等,通过附加双下划线和相关模型字段名称。
  • 仍然抛出 FieldError,未知字段异常
  • 能否请您发布错误?还是追溯?
  • 用回溯编辑它
  • 添加了一个代码示例作为我使用的答案,这让我没有想到 Django 没有在表单中提供任何默认方式。

标签: python django


【解决方案1】:

通过覆盖 ModelForm 的 __init__ 方法,我找到了自己的解决方案:

class MyModelForm(forms.ModelForm):

  first_name = forms.CharField()

  class Meta:
    model = MyModel
    fields = ['bio', 'date_of_birth']

  def __init__(self, *args, **kwargs):
    super(MyModelForm, self).__init__(*args, **kwargs)
    my_user = kwargs.get('instance')
    first_name = my_user.user.first_name
    self.fields['first_name'].initial = first_name #this will show the first name in the html page when i request the instance

当我实例化我的表单时,我只是将 MyModel 的一个实例作为 夸格:form = MyModelForm(instance=my_model_instance)

【讨论】:

  • 很高兴您找到解决问题的方法 :)
  • super().__init__self.instance 被设置之后,所以你可以只使用my_user = self.instance,这比从kwargs 读取要容易一些。
  • @dirkgroten 哦,非常感谢 :) 我对 django/python 还是很陌生,所以很多细节都在逃避我
【解决方案2】:

您可以使用InlinFormset。在这里,我发布了一个我使用的代码示例,可能会对您有所帮助。我已根据您的需要进行了一些修改,所以如果有任何问题,请告诉我。

#forms.py
class UserForm(forms.ModelForm):
    class Meta:
        model = User

class MyModelForm(forms.ModelForm):

  class Meta:
    model = MyModel

那么在你看来你应该这样做

def profileEdit(request,username):
    # querying the User object with pk from url
    user = User.objects.get(username=username)

    # prepopulate MyModelForm with retrieved user values from above.
    user_form = UserForm(instance=user)

    MyModelInlineFormset = inlineformset_factory(User, MyModel,can_delete=False, fields="__all__")
    formset = MyModelInlineFormset(instance=user)

    if request.user.is_authenticated() and request.user.id == user.id:
        if request.method == "POST":
            user_form = UserForm(request.POST, request.FILES, instance=user)
            formset = MyModelInlineFormset(request.POST, request.FILES, instance=user)

            if user_form.is_valid():
                created_user = user_form.save(commit=False)
                formset = MyModelInlineFormset(request.POST, request.FILES, instance=created_user)

                if formset.is_valid():
                    created_user.save()
                    formset.save()
                    return HttpResponseRedirect('/')

        return render(request, "profile_edit.html", {
            'title':'Edit -'+ user.get_full_name(),
            "user_form": user_form,
            "formset": formset,
        })
    else:
        raise PermissionDenied

在您的 profile_edit.html 中

{% extends "layout.html" %}
{% block content %}
    {% if messages %}
    <div>
    {% for message in messages %}
            <div class="alert alert-{{ message.tags }}">  <!-- singular -->
                <a class="close" data-dismiss="alert">×</a>
                {{ message|safe }}
            </div>
        {% endfor %}
    </div>
    {% endif %}
<div class="col-xs-8 col-xs-offset-2">
      <div class="card">
        <div class="card-content">
        <h2 class="flow-text">Update your information</h2>
          <form action="." method="POST" class="padding" enctype="multipart/form-data">
            {% csrf_token %}
    {% for field in user_form %}
    <div class="form-group">
        {{ field.errors }}
       <label for="{{ field.label }}" >{{ field.label }}</label>
        {{ field }}
     {% if field.help_text %}
      <small class="form-text text-muted">{{ field.help_text|safe }}</small>
      {% endif %}
    </div>
{% endfor %}

    {{ formset.management_form }}
    {% for form in formset %}

        {% for hidden in form.hidden_fields %}
        {{ hidden }}
        {% endfor %}
        {% for field in form.visible_fields %}
        <div class="form-group">
            {{ field.errors }}
       <label for="{{ field.label }}" >{{ field.label }}</label>
       {{ field }}
      {% if field.help_text %}
      <small class="form-text text-muted">{{ field.help_text|safe }}</small>
      {% endif %}
        </div>
        {% endfor %}
    {% endfor %}
            <input type="submit" class="btn btn-primary" value="Save"></input>
        </form>
        </div>
    </div>
</div>
{% endblock content %}

【讨论】:

    猜你喜欢
    • 2016-06-10
    • 1970-01-01
    • 2014-09-02
    • 1970-01-01
    • 2018-03-29
    • 2011-01-14
    • 2018-08-10
    • 1970-01-01
    • 2020-07-28
    相关资源
    最近更新 更多