【问题标题】:How to save object field from other Model Django如何从其他模型 Django 中保存对象字段
【发布时间】:2020-08-01 15:34:41
【问题描述】:

首先,我像这样扩展 AbstractUser:

class MyProfile(AbstractUser):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    full_name = models.CharField(max_length=255)
    id_number = models.CharField(max_length=14)

    def __str__(self):
        return self.full_name

    def save(self, *args, **kwargs):
        self.full_name = '{0} {1}'.format(self.first_name, self.last_name)
        super().save(*args, **kwargs)

然后像这样引用其他模型:

class MyModel(models.Model):
    member = models.OneToOneField(MyProfile, on_delete=models.CASCADE)
    description = models.CharField(max_length=255)

    def __str__(self):
        return self.member

这个形式:

class MyModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    class Meta:
        model = MyModel
        fields = ('description')

    full_name = forms.CharField(required=False, label="", widget=forms.TextInput(attrs={'class': "form-control"}))
    id_number = forms.CharField(required=False, label="", widget=forms.TextInput(attrs={'class': "form-control"}))
    description = forms.CharField(required=False, label="", widget=forms.TextInput(attrs={'class': "form-control"}))

这是视图:

def applicationdata(request):
   if request.method == 'POST':
      form = MyModelForm(request.POST or None) 
      if form.is_valid():
         form.save()
      return HttpResponseRedirect('/index/')
      else:
         print(form.errors)
   else:
      form = MyModelForm()

   context = {
      'form': form,
   }
   return render(request, 'index.html', context)

我的问题是:

  • 如何在 MyModelForm 上显示 full_name 的字段和 id_number 的字段而不是 member 的字段?

  • 以及如何通过 applicationdata 的视图将这些字段保存到 MyModel 模型中的 member 字段中?

更新

  1. 我更新了 AbstractUser 模型,因为我忘记添加 first_name 和 last_name 并且忘记提及是否使用 allauth
  2. 我用 init 更新了表单

【问题讨论】:

    标签: django


    【解决方案1】:

    这里最好使用Form,而不是使用ModelForm,因为我们肯定不会特别使用模型领域。 你的 forms.py 应该是这样的

    class MyModelForm(forms.Form):
    
        full_name = forms.CharField(required=False, label="", widget=forms.TextInput(attrs={'class': "form-control"}))
        id_number = forms.CharField(required=False, label="", widget=forms.TextInput(attrs={'class': "form-control"}))
        description = forms.CharField(required=False, label="", widget=forms.TextInput(attrs={'class': "form-control"}))
    
    

    而我们的视图方法应该需要完全根据需要存储的字段和数据进行定制。 将您的 views.py 方法更改为此

    def applicationdata(request):
       if request.method == 'POST':
          form = MyModelForm(request.POST or None) 
          if form.is_valid():
              profile = MyProfile.object.create(full_name=request.POST['full_name'], id_number=request.POST['id_number'])
              if profile is not None:
                  MyModel.object.create(description=request.POST['description'], member=profile.pk)
                  return HttpResponseRedirect('/index/')
              else:
                  form.add_error('profile_out_of_bound', "please try to fill correct details!")
    
          print(form.errors)
       else:
          form = MyModelForm()
    
       context = {
          'form': form,
       }
       return render(request, 'index.html', context)
    

    如果这不起作用,请纠正我。

    【讨论】:

    • 感谢您的回答。我更新我的问题。实际上我使用 ModelForm 是因为我需要获取现有用户并填写一个附加字段(描述),然后将其保存到用户中(OneToOne)。我尝试了您的答案,但出现错误:django.db.utils.IntegrityError:重复键值违反唯一约束“myprofile_member_username_key”详细信息:键(用户名)=()已存在。
    【解决方案2】:

    首先您可以删除 first_namelast_name 字段,因为您可以从 full_name 获取它

    class MyProfile(AbstractUser):
        full_name = models.CharField(max_length=255)
        id_number = models.CharField(max_length=14)
    
        def __str__(self) -> str:
            return self.full_name
    
        @property
        def first_name(self) -> str:
            return self.full_name.split(' ')[0]
    
        @property
        def last_name(self) -> str:
            if self.full_name.split(' ') > 1:
                return self.full_name.split(' ')[1]
            return ''
    
    
    class MyModelForm(forms.ModelForm):
    
        full_name = forms.CharField(required=False, label="", widget=forms.TextInput(attrs={'class': "form-control"}))
        id_number = forms.CharField(required=False, label="", widget=forms.TextInput(attrs={'class': "form-control"}))
    
        class Meta:
            model = MyModel
            fields = ('description')
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.fields['description'].widget = forms.TextInput(attrs={'class': "form-control"})
    
        def save(self, *args, **kwargs):
            kwargs['commit'] = False
            my_model = super().save(*args, **kwargs)
            MyProfile.objects.update_or_create(
                full_name=self.cleaned_data['full_name'],
                id_number=self.cleaned_data['id_number'],
                mymodel=my_model
            )
    
    
    

    如果MyProfile对象已经存在,你可以使用它来自动填写__init__的表单域

        def __init__(self, my_profile: MyProfile, *args, **kwargs):
            kwargs.update(initial={
                # 'field': 'value'
                'full_name': my_profile.full_name,
                'id_number': my_profile.id_number
            })
            super().__init__(*args, **kwargs)
            self.fields['description'].widget = forms.TextInput(attrs={'class': "form-control"})
    

    【讨论】:

      【解决方案3】:

      如何在 MyModelForm 上显示 full_name 的字段和 id_number 的字段而不是 member 的字段?

      如果您打算显示它以在之后更改它,则必须覆盖 __init__ 方法以在两个字段上设置初始数据:maybe this answer 可以提供帮助

      以及如何通过 applicationdata 的视图将这些字段保存到 MyModel 模型中的成员字段中?

      entity = form.save() # this gives you the updated MyModel instance
      

      然后将表单中的数据保存到相关模型中,例如:

       entity.member.full_name = form.cleaned_data['full_name']
      

      应根据:this answer

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-04-15
        • 2011-09-10
        • 2017-07-13
        • 2021-03-24
        • 2014-07-20
        • 2011-06-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多