【问题标题】:Many To Many Field Django throwing errors多对多字段 Django 抛出错误
【发布时间】:2021-11-21 22:58:27
【问题描述】:

我正在尝试将表单数据存储到模型中,当用户提交表单时,所有数据都已正确保存,但多对多字段 (catagory) 会引发错误。有人可以帮我编辑我的视图,以便我可以保存此信息吗?提前谢谢你。

我尝试保存字段'Catagory',但起初无法保存。然后我遇到了说在self.save(commit=False) 之前添加self.save_m2m() 的答案。但这会导致另一个错误:

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.

The screenshot of the error message

这是我使用的代码sn-ps:

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)

我不知道为什么会出现这个错误,这让我发疯了

【问题讨论】:

    标签: python python-3.x django django-models django-forms


    【解决方案1】:

    来自docs

    当您的模型与另一个模型具有多对多关系时,会看到使用 commit=False 的另一个副作用。如果您的模型具有多对多关系并且您在保存表单时指定 commit=False,则 Django 无法立即保存多对多关系的表单数据。这是因为在实例存在于数据库中之前,无法为实例保存多对多数据。

    错误是由这两行引起的:

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

    form.save(commit=False) 会给你一个未保存的对象,这意味着它还没有 id。所以在它之后调用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()
    

    【讨论】:

      猜你喜欢
      • 2014-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-27
      • 2015-06-15
      • 2021-04-05
      • 2011-02-05
      相关资源
      最近更新 更多