【问题标题】:How to edit/update a model via Django form with manytomany field?如何通过具有多字段的 Django 表单编辑/更新模型?
【发布时间】:2015-11-30 13:03:33
【问题描述】:

我在编辑/更新具有多态字段的表单时遇到问题。我不知道如何实现使用多字段保存表单的逻辑。模型 Sam 是一个用户,他管理不同的帐户,并且在一段时间内他管理的帐户会发生变化。因此,应该可以灵活地添加或删除他通过 Samprofileupdateform 管理的帐户,其中包括 Account 的多对多字段。你能帮我实现这个吗?

models.py

class Account(models.Model):
   accnt_nagp = models.CharField(max_length=30, unique=True, primary_key=True)
   #sam_name = models.ManyToManyField(Sam)
   def __unicode__(self):
     return  self.accnt_nagp

class Sam(models.Model):
    SUNNYVALE = 'SVL'
    NORTHCAROLINA = 'RTP'
    EUROPE = 'EMEA'
    INDIA = 'NB'
    AUSTRALIA = 'AUS'
    suppaccntmgr = 'SAM'
    MANAGER = 'SAM_MGR'
    REGION_CHOICES = (
       (SUNNYVALE, 'Sunnyvale'),
       (NORTHCAROLINA, 'RTP'),
       (EUROPE,'EMEA'),
       (INDIA,'NB'),
       (AUSTRALIA,'AUS'),
      )
    DESIGNATION_CHOICES = (
       (suppaccntmgr, 'SAM'),
       (MANAGER, 'SAM_MGR'),
      )
    user = models.OneToOneField(User)
    designation = models.CharField(max_length=8, choices=DESIGNATION_CHOICES, 
                        default=suppaccntmgr)
    mgr = models.ForeignKey(SamMgr)
    accnt = models.ManyToManyField(Account)

    def __unicode__(self):
        return u'%s' % self.user.username

Views.py:

class SamProfileUpdateView(views.LoginRequiredMixin, UpdateView):
    model = Sam
    form_class = SamProfileUpdateForm
    success_url = reverse_lazy('risklist')
    template_name = 'samrunbook/samaccntassociate.html'

forms.py

class SamProfileUpdateForm(forms.ModelForm):
    class Meta:
       model = Sam
       fields = ('accnt','mgr')
    def __init__(self, *args, **kwargs):
       super(SamProfileUpdateForm, self).__init__(*args, **kwargs)
       self.helper = FormHelper(self)
       self.helper.form_method = 'POST'
       self.helper.form_class = 'form-horizontal'
       self.helper.label_class = 'col-md-3'
       self.helper.field_class = 'col-md-6'
       self.helper.layout = Layout(
            'accnt',
            'mgr',
          FormActions(
                Submit('map', 'Map Your Account', css_class="btn-primary col-md-offset-3 col-md-6")
                )
        )

模板.py

{% extends 'samrunbook/base_risk.html' %}
{% load crispy_forms_tags %}

{% block content %}
<h3 class="col-md-offset-5">Login | Risk Register</h3>
{% csrf_token %}
{% crispy form %}
{% endblock %}

【问题讨论】:

    标签: python django forms django-crispy-forms manytomanyfield


    【解决方案1】:

    如果我正确理解您的问题:您想显示具有 ManyToMany 字段的模型形式。问题是如果 Sam 有 3 个帐户,您想显示 3 个字段,但可能更少或更多。

    我最近做了类似的事情。在表单的初始化中,查询此模型拥有的帐户并循环遍历结果以将每个对象添加到 self.fields 数组中

    query = ... # query Sam's accounts
    for account in query:
        self.fields[account.accnt_nagp] = forms.IntegerField(...)
    

    【讨论】:

      【解决方案2】:

      您应该使用模型表单集来添加/删除相关帐户。

      https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/#model-formsets

      【讨论】:

        【解决方案3】:

        我创建了这个自定义视图功能来创建/更新/编辑管理多个帐户/客户的用户配置文件。我通过中间模型来创建 Sam 和 Account 两个模型之间的多对多关系。中间模型是 SamAccount。请在下面找到模型、视图功能和表单的代码。现在问题已经解决了。

        形成 AccountMapForm :

        class AccountMapForm(forms.Form):
            account_nagp = forms.CharField()
        
            def __init__(self, *args, **kwargs):
               super(AccountMapForm, self).__init__(*args, **kwargs)
               self.helper = FormHelper()
               self.helper.form_class = 'form-horizontal'
               self.helper.label_class = 'col-md-4'
               self.helper.field_class = 'col-md-6'
               self.helper.layout = Layout(
                   Field('account_nagp', css_class='input-xlarge'),
                   FormActions(
                      Submit('save_changes', 'Map', css_class='btn-primary col-md-offset-1 col-md-4'),
                      Submit('un_map', 'UnMap', css_class='btn-primary col-md-offset-1 col-md-4'),
                    )
                )
        

        查看功能:

        def account_map(request, slug):
           user_id = slug
           sam = Sam.objects.get(user_id=user_id)
           sam_check = SamAccount.objects.filter(sam=sam)
           message_account_map = "Please enter the Account Nagp you want to Map to your Profile"
           message_account_unmap = "Account is succesfully UnMapped"
           message_account_map_success = 1
           message_account_unmap_success = 1
           if 'save_changes' in request.POST:
               print "yes save_changes is there"
           if 'un_map' in request.POST:
               print "Yes Unmap is there"
           if request.method == 'POST':
               form = AccountMapForm(request.POST)
               if form.is_valid():
                  user_id = slug
                  account_from_form = form.cleaned_data['account_nagp']
                  try:
                    account = Account.objects.get(accnt_nagp=account_from_form)
                    try:
                        if 'save_changes' in request.POST:
                            account = SamAccount.objects.get(sam=sam, account=account_from_form)
                            message_account_map = "Account is already Mapped"
                            message_account_map_success = 0 # To get the color change for the Warning
                        else:
                            SamAccount.objects.get(sam=sam, account=account_from_form).delete()
                            message_account_unmap_success = 0
                    except ObjectDoesNotExist:
                        if 'save_changes' in request.POST:
                            SamAccount.objects.create(sam=sam, account=account)
                            message_account_map = "Account is succesfully Mapped to your profile"
                        else:
                            message_account_unmap = "The requested Account was not mapped to your profile"
                            message_account_unmap_success = 1
                  except ObjectDoesNotExist:
                    account = Account.objects.create(accnt_nagp=account_from_form)
                    SamAccount.objects.create(sam=sam, account=account)
                    message_account_map = "Created the Account and succesfully Mapped to your profile"
           else:
              form = AccountMapForm()
              template = loader.get_template('book/account_map.html')
              context = RequestContext(request, {
                    'form' : form,
                    'message_account_map' : message_account_map,
                    'message_account_unmap' : message_account_unmap,
                    'message_account_map_success' : message_account_map_success,
                    'message_account_unmap_success' : message_account_unmap_success,
            })
           return HttpResponse(template.render(context))
        

        模型帐户:

        class Account(models.Model):
           """Each Account Can have multiple SAMs"""
           accnt_nagp = models.CharField(max_length=30, unique=True, primary_key=True)
           sam_name = models.ManyToManyField('Sam', related_name='managed_by', through='SamAccount')
           def __unicode__(self):
        

        模特山姆:

        class Sam(models.Model):
           """Sam can have Multiple Accounts"""
           SUNNYVALE = 'SVL'
           NORTHCAROLINA = 'RTP'
           EUROPE = 'EMEA'
           INDIA = 'NB'
           AUSTRALIA = 'AUS'
           ROLE = 'SAM'
           MANAGER = 'SAM_MGR'
           REGION_CHOICES = (
            (SUNNYVALE, 'Sunnyvale'),
            (NORTHCAROLINA, 'RTP'),
            (EUROPE,'EMEA'),
            (INDIA,'NB'),
            (AUSTRALIA,'AUS'),
            )
          DESIGNATION_CHOICES = (
            (ROLE1, 'SAM'),
            (MANAGER, 'SAM_MGR'),
            )
          user = models.OneToOneField(User)
          designation = models.CharField(max_length=8, choices=DESIGNATION_CHOICES,     default=ROLE)
          mgr = models.ForeignKey(SamMgr)
          slug = models.SlugField(max_length=255)
          accnt = models.ManyToManyField(Account, related_name='accounts_managed', through='SamAccount')
        
          def __unicode__(self):
              return u'%s' % self.user.username
        

        中间模型来处理两个模型之间的多对多关系。如果必须在两个模型之间创建关系,我所要做的就是在中间模型中为相应的外键字段创建一个对象。

        中间模型 SamAccount:

        class SamAccount(models.Model):
           account = models.ForeignKey('Account', on_delete=models.CASCADE)
           sam = models.ForeignKey('Sam', on_delete=models.CASCADE)
        
           def __unicode__(self):
               return u'%s' % self.account  
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-04
          • 2013-07-28
          • 2015-06-03
          • 1970-01-01
          • 2023-03-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多