我有以下具有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.
。我该怎么做?
答案 0 :(得分:11)
您需要在视图中明确保存MeetingArrival
对象,以便在ManyToManyField
带through
参数的情况下保存中间模型。
如果ManyToManyField
有中间模型,则您无法使用普通多对多字段中可用的add
,create
或assignment
与普通的多对多字段不同,您无法使用添加,创建或 分配以建立关系。
创建此类关系的唯一方法是创建 中间模型的实例。
因此,您必须在视图中明确创建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
答案 1 :(得分:3)
使用到表时,需要手动保存。
MeetingArrival.objects.create( ... )
答案 2 :(得分:1)
对于Django 1.x,就像Rahul所说的,您不能使用add
,create
等
对于django 2.x,实际上您可以在django 2.x
中查看每个文档您还可以使用add(),create()或set()创建关系,只要您为任何必填字段指定through_defaults即可:
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)})
答案 3 :(得分:0)
不要将逻辑放在视图中处理ManyToManyField的位置,而是将其放在表单中,这样如果在多个位置使用表单,就不必重复自己。
为此,您需要覆盖save
的{{1}}方法。
请参阅我对其他问题的更全面的回答:https://stackoverflow.com/a/40822731/2863603
答案 4 :(得分:0)
我是这样做的,仍然试图从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)
答案 5 :(得分:0)
user_profiles = UserProfile.objects.all()
NotificationUser.objects.bulk_create([[user_profiles中的user_profile的NotificationUser(user = user_profile,notification = notification)])