Many To Many Field Django бросает ошибки

Я пытаюсь сохранить данные формы в модели, когда пользователь отправляет форму, все данные сохраняются корректно, кроме поля many to many (catagory), которое выдает ошибки. Может ли кто-нибудь помочь мне отредактировать мое представление так, чтобы я мог сохранить эту информацию? Заранее благодарю.

Я попытался сохранить поле 'Catagory', но сначала не смог. Затем я наткнулся на ответы, в которых говорилось, что нужно добавить self.save_m2m() перед self.save(commit=False). Но это приводит к другой ошибке:

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/create/

Django Version: 3.2.5
Python Version: 3.9.6
Installed Applications:
['fontawesome_free',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'jquery',
 'portfolio',
 'blog',
 'import_export',
 'tinymce',
 'hitcount',
 'taggit',
 'accounts']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "C:\Users\Babli\AppData\Roaming\Python\Python39\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\Babli\AppData\Roaming\Python\Python39\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Babli\AppData\Roaming\Python\Python39\site-packages\django\contrib\auth\decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "C:\Users\Babli\Desktop\My-Projects\MySite\mysite\blog\views.py", line 35, in make_post
    form.save_m2m()
  File "C:\Users\Babli\AppData\Roaming\Python\Python39\site-packages\django\forms\models.py", line 451, in _save_m2m
    f.save_form_data(self.instance, cleaned_data[f.name])
  File "C:\Users\Babli\AppData\Roaming\Python\Python39\site-packages\django\db\models\fields\related.py", line 1668, in save_form_data
    getattr(instance, self.attname).set(data)
  File "C:\Users\Babli\AppData\Roaming\Python\Python39\site-packages\django\db\models\fields\related_descriptors.py", line 536, in __get__
    return self.related_manager_cls(instance)
  File "C:\Users\Babli\AppData\Roaming\Python\Python39\site-packages\django\db\models\fields\related_descriptors.py", line 851, in __init__
    raise ValueError('"%r" needs to have a value for field "%s" before '

Exception Type: ValueError at /create/
Exception Value: "<Post: sadfsadfasdfsadsdfasd>" needs to have a value for field "id" before this many-to-many relationship can be used.

Скриншот сообщения об ошибке

Вот фрагменты кода, которые я использовал:

models.py

class Catagory(models.Model):
    title = models.CharField(max_length=50)
    slug = models.SlugField(max_length=400, unique=True, blank=True)

    class Meta:
        verbose_name_plural = "Catagories"

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Catagory, self).save(*args, **kwargs)

    def __str__(self):
        return self.title
    @property
    def num_posts(self):
        return Post.objects.filter(catagory=self).count()

    @property
    def last_post(self):
        return Post.objects.filter(catagory=self).latest("date")
class Post(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField(max_length=100, unique=True, blank=True)
    user = models.ForeignKey(Author, on_delete=models.CASCADE)
    content = HTMLField(max_length=500)
    catagory = models.ManyToManyField(Catagory)
    date = models.DateTimeField(auto_now_add=True)
    approved = models.BooleanField(default=False)
    hit_count_generic = GenericRelation(HitCount, object_id_field='object_pk', 
    related_query_name='hit_count_generic_relation')
    points = models.IntegerField(default=0)
    tags = TaggableManager()
    comments = models.ManyToManyField(Comment, blank=True)

forms.py

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'content', 'catagory', 'tags']

views.py

@login_required
def make_post(req):
    context = {}
    form = PostForm(req.POST or None)
    if req.method == "POST":
        if form.is_valid():
            author = Author.objects.get(user=req.user)
            form.save(commit=False)
            form.save_m2m()
            new_post = form
            new_post.user = author
            new_post.save()
            return redirect('blog:blog-index')
    context.update({
        'form': form,
        'title': 'Create A Post'
    })

    return render(req, 'create.html', context)

Я не знаю, почему возникает эта ошибка, и она сводит меня с ума

От docs:

Еще один побочный эффект использования commit=False проявляется, когда ваша модель имеет отношение "многие-ко-многим" с другой моделью. Если ваша модель имеет отношение "многие-ко-многим" и вы указываете commit=False при сохранении формы, Django не может немедленно сохранить данные формы для отношения "многие-ко-многим". Это происходит потому, что невозможно сохранить данные отношения "многие-ко-многим" для экземпляра, пока этот экземпляр не существует в базе данных.

.

Ошибка вызвана этими двумя строками:

form.save(commit=False)
form.save_m2m()

form.save(commit=False) даст вам несохраненный объект, то есть у него еще нет идентификатора. Поэтому вызов form.save_m2m() сразу после него приведет к ошибке, которой вы поделились.

Это означает, что перед вызовом form.save_m2m():

необходимо сначала сохранить несохраненный объект.
my_obj = form.save(commit=False)
my_obj.save()
form.save_m2m()

Итак, похоже, что вы хотели сделать следующее:

    new_post = form.save(commit=False) # unsaved new post object
    new_post.user = author
    new_post.save()
    form.save_m2m()
Вернуться на верх