如何保存具有直通关系的 ManyToMany 字段
How to save a ManyToMany field with a through relationship
我有以下具有 ManyToMany
和 through
关系的模型:
class Meeting(models.Model):
site = models.ForeignKey(Site)
meeting_title = models.CharField(default='', max_length=128, blank=True, null=True)
meeting_visitors = models.ManyToManyField(Visitor, through="MeetingArrival", blank=False, null=False)
class Visitor(models.Model):
visitor_company = models.ForeignKey(Company)
visitor_name = models.CharField(default='', max_length=128, blank=False, null=False)
class MeetingArrival(models.Model):
visitor = models.ForeignKey(Visitor)
meeting = models.ForeignKey(Meeting)
arrival_status = models.BooleanField(default=False)
我有创建会议的表格:
class AddMeetingForm(forms.ModelForm):
class Meta:
model = Meeting
exclude = ['site',]
以及保存表格的简单视图:
def add_meeting(request):
add_meeting_form = AddMeetingForm(request.POST or None)
site = Site.objects.get(user=request.user.id)
if request.method == "POST":
if add_meeting_form.is_valid():
obj = add_meeting_form.save(commit=False)
obj.site = site
obj.save()
这会保存表单,但不会保存 meeting_visitors
字段,即使该字段在视图中完美呈现。如何挽救这段感情?
编辑
如果我将 add_meeting_form.save_m2m()
添加到视图,我将得到 Cannot set values on a ManyToManyField which specifies an intermediary model. Use meetings.MeetingArrival's Manager instead.
。我该怎么做?
当您使用到 table时,您需要手动保存。
MeetingArrival.objects.create( ... )
如果 ManyToManyField
带有 through
参数,您必须在视图中显式保存 MeetingArrival
对象以保存中间模型。
对于 Django 2.1 及以下版本,如果 ManyToManyField
具有中间模型,则不能使用 add
、create
或 assignment
,它们是适用于普通的多对多字段。
Unlike normal many-to-many fields, you can’t use add, create, or
assignment to create relationships.
The only way to create this type of relationship is to create
instances of the intermediate model.
因此,您必须在视图中显式创建一个 MeetingArrival
对象。
您可以通过以下方式完成:
def add_meeting(request):
add_meeting_form = AddMeetingForm(request.POST or None)
site = Site.objects.get(user=request.user.id)
if request.method == "POST":
if add_meeting_form.is_valid():
obj = add_meeting_form.save(commit=False)
obj.site = site
obj.save()
# create an instance of 'MeetingArrival' object
meeting_arrival_obj = MeetingArrival(meeting=obj, visitor=<your_visitor_object_here>, arrival_status=True)
meeting_arrival_obj.save() # save the object in the db
不要将处理 ManyToManyField 的逻辑放在视图中,而是将其放在表单中,这样如果您在多个地方使用表单,就不必重复自己。
为此,您需要重写ModelForm
的save
方法。
查看我对另一个问题的更详尽的回答:
我这样做了,仍然试图从 select 中获取多个 id 值,我认为我的 javascript
有问题
但这里是 python 代码:
class ArticuloCreateView(View):
def __init__(self):
self.template_name = 'articulo/formulario.html'
def get(self, request):
formulario = ArticuloForm()
contexto = {
'form': formulario,
'operation': "Nuevo"
}
return render(request, self.template_name, contexto)
@transaction.atomic
def post(self, request):
punto_transaccion = transaction.savepoint()
formulario = ArticuloForm(request.POST)
almacenes = request.POST.get('almacenes', 0)
almacenes = Almacen.objects.filter(id=almacenes)
if formulario.is_valid():
datos_formulario = formulario.cleaned_data
articulo = Articulo()
articulo.clave = datos_formulario.get('clave')
articulo.descripcion = datos_formulario.get('descripcion')
articulo.tipo = datos_formulario.get('tipo')
articulo.udm = datos_formulario.get('udm')
articulo.clave_jde = datos_formulario.get('clave_jde')
articulo.save()
for almacen in almacenes:
Stock.objects.create(articulo=articulo, almacen=almacen)
if punto_transaccion:
transaction.savepoint_commit(punto_transaccion)
return redirect(
reverse('inventarios.articulos_lista')
)
contexto = {
'form': formulario,
}
return render(request, self.template_name, contexto)
对于 django 1.x,正如 Rahul 所说,您不能使用 add
、create
等
对于 django 2.x,您实际上可以根据此处的文档 django 2.x
You can also use add(), create(), or set() to create relationships, as long as you specify through_defaults for any required fields:
beatles.members.add(john, through_defaults={'date_joined': date(1960, 8, 1)})
beatles.members.create(name="George Harrison", through_defaults={'date_joined': date(1960, 8, 1)})
beatles.members.set([john, paul, ringo, george], through_defaults={'date_joined': date(1960, 8, 1)})
user_profiles = UserProfile.objects.all()
NotificationUser.objects.bulk_create([NotificationUser(user=user_profile, notification=notification) for user_profile in user_profiles])
我有以下具有 ManyToMany
和 through
关系的模型:
class Meeting(models.Model):
site = models.ForeignKey(Site)
meeting_title = models.CharField(default='', max_length=128, blank=True, null=True)
meeting_visitors = models.ManyToManyField(Visitor, through="MeetingArrival", blank=False, null=False)
class Visitor(models.Model):
visitor_company = models.ForeignKey(Company)
visitor_name = models.CharField(default='', max_length=128, blank=False, null=False)
class MeetingArrival(models.Model):
visitor = models.ForeignKey(Visitor)
meeting = models.ForeignKey(Meeting)
arrival_status = models.BooleanField(default=False)
我有创建会议的表格:
class AddMeetingForm(forms.ModelForm):
class Meta:
model = Meeting
exclude = ['site',]
以及保存表格的简单视图:
def add_meeting(request):
add_meeting_form = AddMeetingForm(request.POST or None)
site = Site.objects.get(user=request.user.id)
if request.method == "POST":
if add_meeting_form.is_valid():
obj = add_meeting_form.save(commit=False)
obj.site = site
obj.save()
这会保存表单,但不会保存 meeting_visitors
字段,即使该字段在视图中完美呈现。如何挽救这段感情?
编辑
如果我将 add_meeting_form.save_m2m()
添加到视图,我将得到 Cannot set values on a ManyToManyField which specifies an intermediary model. Use meetings.MeetingArrival's Manager instead.
。我该怎么做?
当您使用到 table时,您需要手动保存。
MeetingArrival.objects.create( ... )
如果 ManyToManyField
带有 through
参数,您必须在视图中显式保存 MeetingArrival
对象以保存中间模型。
对于 Django 2.1 及以下版本,如果 ManyToManyField
具有中间模型,则不能使用 add
、create
或 assignment
,它们是适用于普通的多对多字段。
Unlike normal many-to-many fields, you can’t use add, create, or assignment to create relationships.
The only way to create this type of relationship is to create instances of the intermediate model.
因此,您必须在视图中显式创建一个 MeetingArrival
对象。
您可以通过以下方式完成:
def add_meeting(request):
add_meeting_form = AddMeetingForm(request.POST or None)
site = Site.objects.get(user=request.user.id)
if request.method == "POST":
if add_meeting_form.is_valid():
obj = add_meeting_form.save(commit=False)
obj.site = site
obj.save()
# create an instance of 'MeetingArrival' object
meeting_arrival_obj = MeetingArrival(meeting=obj, visitor=<your_visitor_object_here>, arrival_status=True)
meeting_arrival_obj.save() # save the object in the db
不要将处理 ManyToManyField 的逻辑放在视图中,而是将其放在表单中,这样如果您在多个地方使用表单,就不必重复自己。
为此,您需要重写ModelForm
的save
方法。
查看我对另一个问题的更详尽的回答:
我这样做了,仍然试图从 select 中获取多个 id 值,我认为我的 javascript
有问题但这里是 python 代码:
class ArticuloCreateView(View):
def __init__(self):
self.template_name = 'articulo/formulario.html'
def get(self, request):
formulario = ArticuloForm()
contexto = {
'form': formulario,
'operation': "Nuevo"
}
return render(request, self.template_name, contexto)
@transaction.atomic
def post(self, request):
punto_transaccion = transaction.savepoint()
formulario = ArticuloForm(request.POST)
almacenes = request.POST.get('almacenes', 0)
almacenes = Almacen.objects.filter(id=almacenes)
if formulario.is_valid():
datos_formulario = formulario.cleaned_data
articulo = Articulo()
articulo.clave = datos_formulario.get('clave')
articulo.descripcion = datos_formulario.get('descripcion')
articulo.tipo = datos_formulario.get('tipo')
articulo.udm = datos_formulario.get('udm')
articulo.clave_jde = datos_formulario.get('clave_jde')
articulo.save()
for almacen in almacenes:
Stock.objects.create(articulo=articulo, almacen=almacen)
if punto_transaccion:
transaction.savepoint_commit(punto_transaccion)
return redirect(
reverse('inventarios.articulos_lista')
)
contexto = {
'form': formulario,
}
return render(request, self.template_name, contexto)
对于 django 1.x,正如 Rahul 所说,您不能使用 add
、create
等
对于 django 2.x,您实际上可以根据此处的文档 django 2.x
You can also use add(), create(), or set() to create relationships, as long as you specify through_defaults for any required fields:
beatles.members.add(john, through_defaults={'date_joined': date(1960, 8, 1)}) beatles.members.create(name="George Harrison", through_defaults={'date_joined': date(1960, 8, 1)}) beatles.members.set([john, paul, ringo, george], through_defaults={'date_joined': date(1960, 8, 1)})
user_profiles = UserProfile.objects.all()
NotificationUser.objects.bulk_create([NotificationUser(user=user_profile, notification=notification) for user_profile in user_profiles])