Django ModelForm中的一个字段(ManyToMany)未保存到数据库

时间:2017-07-24 01:29:29

标签: python django

我的应用是项目管理工具,用户可以在其中添加,编辑和查看项目。项目包括标题,摘要和作者(用户)。用户与Projects具有ManyToMany关系。

添加新项目工作正常,直到我添加了编辑项目视图。我仍然可以创建一个新项目或编辑现有项目,新标题和摘要将保存到数据库中,但所选作者不会被保存。请注意,我仍然可以进入shell并手动将作者添加到项目中。

以下是项目用户模型

class MyUser(AbstractBaseUser):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    bank_id = models.CharField("researcher's four-letter bank id", null=True, max_length=4, unique=True)
    #division = models.CharField(max_length=30, blank = True)
    department = models.CharField(max_length=3, choices=DEPARTMENTS)
    job_title = models.CharField("job title",  max_length=30, choices=JOB_TITLES)
    citations = models.IntegerField(null=True, blank=True)
    institution = models.CharField(max_length=30, choices=DEPARTMENTS, blank=True)
    created_on = models.DateTimeField(auto_now_add=True)
    updated_on = models.DateTimeField(auto_now=True)
    #history = HistoricalRecords()
    REQUIRED_FIELDS = ['email']
    USERNAME_FIELD = 'username'

class Project(models.Model):
    title = models.TextField('Title')
    summary = models.TextField('Summary', default=DEFAULT_TEXT)
    authors = models.ManyToManyField(MyUser)
    internal_status = models.CharField('Internal Status', max_length = 20, choices = INTERNAL_STATUS,
                                       default='wip')
    external_status = models.CharField('External Status', max_length = 20, choices = EXTERNAL_STATUS,
                                       blank=True)
    mtp_goal = models.CharField(max_length = 50, choices = MTP_GOALS,
                                blank=True)
    topics = ArrayField(models.CharField('Topics', max_length=30), size=4, null=True)
    created_on = models.DateTimeField(auto_now_add=True, null=True)
    updated_on = models.DateTimeField(auto_now=True, null=True)
    history = HistoricalRecords()

views.py

def add_new(request):
    if request.method == 'POST':
        form = ProjectForm(request.POST)
        if form.is_valid():
            project = form.save(commit=False)
            project.created_on = timezone.now()
            project.save()
            return redirect('project_profile', pk=project.pk)
    else:
        form = ProjectForm()
    return render(request, 'add_new.html', {'form': form})

def edit_project(request, pk):
    project = get_object_or_404(Project, pk=pk)
    if request.method == 'POST':
        form = ProjectForm(request.POST, instance=project)
        if form.is_valid():
            project = form.save(commit=False)
            project.updated_on = timezone.now()
            project.save()
            return redirect('project_profile', pk=project.pk)
    else:
        form = ProjectForm(instance=project)
    return render(request, 'edit_project.html', {'form': form})

forms.py:

from django import forms
from .models import Project, MyUser

class ProjectForm(forms.ModelForm):

    class Meta:
        model = Project
        fields = ('title', 'authors', 'summary')

最后, add_project.html 页面(请原谅可疑的HTML):

<html>
<head>
    <title>ResearchTracker</title>
</head>
<body>
  <div>
    <nav>
      <a href="/about">About us</a>
      <a href="/login">Login</a>
      <a href="/admin">Admin</a>
    </nav>
  </div>
      <h1>New project</h1><br>
    <form method="POST" class="post-form">{% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="save btn btn-default">Save</button>
    </form>
    <a href="/">Go home</a>
  </body>
</html>

1 个答案:

答案 0 :(得分:3)

由于您在commit=False中使用save,因此您需要明确调用save_m2m以保存多个字段。

来自the documentation

  

仅在使用save(commit = False)时才需要调用save_m2m()。   当您在表单上使用简单的save()时,所有数据 - 包括   多对多数据 - 无需任何额外数据即可保存   方法调用。例如:

你会做

project.save()
project.save_m2m()