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()