Nurzhan Nogerbek Nurzhan Nogerbek - 9 months ago 60
Python Question

Django add new object

I have

project_detail
page. Inside that page I have link which will redirect user to another page where user can add new members to current project. As you see from the code below I created form with 2 fields user and role. How to associate new members with current project? I tried next code but I have error when try to save new member. Here below you can see full trackback also. It seems to me system dont know in what project must be new member. I tested with 2 databases the sqlite and MS SQL SERVER. The result was same in both of them. How to fix this error.

models.py:

class Project(models.Model):
***FIELDS***
members = models.ManyToManyField(User, through='Membership',)

class Membership (models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE,)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
role = models.CharField(max_length=20, choices=ROLE_CHOICES,)


forms.py:

class ProjectMembersForm(forms.ModelForm):
class Meta:
model = Membership
exclude = ('project',)


views.py:

def project_detail(request, project_id):
project = get_object_or_404(Project, pk=project_id, status='public')
return render(request, 'project/project_detail.html', {'project': project})


def add_project_member(request, project_id):
project = get_object_or_404(Project, pk=project_id)
if request.method == 'POST':
form = ProjectMembersForm(request.POST)
if form.is_valid():
new_member = form.save()
new_member.save()
return render(request, 'project/project_detail.html', {'project': project, 'new_member': new_member})
else:
form = ProjectMembersForm()
return render(request, 'project/project_members.html', {'project': project, 'form': form})


urls.py:

url(r'^projects/(?P<project_id>\d+)/$', project_detail, name='project_detail'),

url(r'^projects/(?P<project_id>\d+)/members/add/$', add_project_member, name='add_project_member'),


link in 'project_detail' page looks like this:

<a href="{% url 'project:add_project_member' project_id=project.id %}">OPEN</a>


Trackback:

Traceback (most recent call last):
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
response = get_response(request)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Nurzhan\PycharmProjects\RMS\project\views.py", line 70, in add_project_member
new_member = form.save()
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\forms\models.py", line 453, in save
self.instance.save()
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\base.py", line 796, in save
force_update=force_update, update_fields=update_fields)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\base.py", line 824, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\base.py", line 908, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\base.py", line 947, in _do_insert
using=using, raw=raw)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\query.py", line 1045, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\sql\compiler.py", line 1054, in execute_sql
cursor.execute(sql, params)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\backends\utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\backends\utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\utils\six.py", line 685, in reraise
raise value.with_traceback(tb)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\backends\utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\sql_server\pyodbc\base.py", line 539, in execute
return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: ('23000', '[23000] [Microsoft][ODBC SQL Server Driver][SQL Server]�� ������� �������� �������� NULL � ������� "project_id", ������� "RMS.dbo.project_membership"; � ������� ��������� �������� NULL. ������ � INSERT. (515) (SQLExecDirectW)')

Answer Source

The error you get is ought due to project field which is a required one inside the Membership model but is excluded inside ProjectMembersForm (thus, it fails when new_member = form.save() is executed).

You should change your add_project_member view to this:

def add_project_member(request, project_id):
    # get project
    project = get_object_or_404(Project, pk=project_id)
    if request.method == 'POST':
        # bound form with POST data (without the 'project' one)
        form = ProjectMembersForm(request.POST)
        if form.is_valid():
            # form does not contain the "project" field. Its excluded!
            new_member = form.save(commit=False)
            # add project to member, manually
            new_member.project = project
            # save member to db
            new_member.save()
            ...