如何通过带有 manytomany 字段的 Django 表单 edit/update 模型?
How to edit/update a model via Django form with manytomany field?
我在 editing/updating 具有 manytomany 字段的表单时遇到问题。我不知道如何实现保存具有多对多字段的表单的逻辑。模型 Sam 是一个用户,他管理不同的帐户,并且在一段时间内他管理的帐户会发生变化。因此,应该可以灵活地通过 Samprofileupdateform 添加或删除他管理的帐户,其中包括帐户的 manytomany 字段。你能帮我实现一下吗?
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")
)
)
templates.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 %}
如果我对您的问题的理解正确:您想要显示具有 ManyToMany 字段的模型形式。问题是,如果 Sam 有 3 个帐户,你想显示 3 个字段,但它可能更少或更多。
我最近做了类似的事情。在您的表单初始化中,查询此模型拥有的帐户并遍历结果以将每个对象添加到 self.fields
数组
query = ... # query Sam's accounts
for account in query:
self.fields[account.accnt_nagp] = forms.IntegerField(...)
您应该为 adding/removing 相关帐户使用模型表单集。
https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/#model-formsets
我已经为 create/update/edit 一个管理多个 accounts/customers 的用户配置文件创建了这个自定义视图函数。我通过中间模型来创建 Sam 和 Account 这两个模型之间的 ManytoMany 关系。中间模型是 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
我在 editing/updating 具有 manytomany 字段的表单时遇到问题。我不知道如何实现保存具有多对多字段的表单的逻辑。模型 Sam 是一个用户,他管理不同的帐户,并且在一段时间内他管理的帐户会发生变化。因此,应该可以灵活地通过 Samprofileupdateform 添加或删除他管理的帐户,其中包括帐户的 manytomany 字段。你能帮我实现一下吗?
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")
)
)
templates.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 %}
如果我对您的问题的理解正确:您想要显示具有 ManyToMany 字段的模型形式。问题是,如果 Sam 有 3 个帐户,你想显示 3 个字段,但它可能更少或更多。
我最近做了类似的事情。在您的表单初始化中,查询此模型拥有的帐户并遍历结果以将每个对象添加到 self.fields
数组
query = ... # query Sam's accounts
for account in query:
self.fields[account.accnt_nagp] = forms.IntegerField(...)
您应该为 adding/removing 相关帐户使用模型表单集。
https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/#model-formsets
我已经为 create/update/edit 一个管理多个 accounts/customers 的用户配置文件创建了这个自定义视图函数。我通过中间模型来创建 Sam 和 Account 这两个模型之间的 ManytoMany 关系。中间模型是 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