保存具有多对多自举字段的实体抛出异常

时间:2017-11-05 20:17:37

标签: python django django-models django-admin many-to-many

我正在尝试为类别树提供管理界面。 我的类别可以有几个父母。我使用多对多的自我字段来提供它。 我也有一些使用sql创建的类别。

models.py

class Category(models.Model):
    id = models.AutoField(primary_key=True)
    active = models.BooleanField()
    description = models.CharField(max_length=255, blank=True, null=True)
    title = models.CharField(max_length=255, blank=True, null=False)
    url = models.CharField(max_length=255, blank=True, null=True)
    parents = models.ManyToManyField('self', through='CategoryParents',
                                 symmetrical=False, blank=True)

    def save(self, *args, **kwargs):
        if self.id is None:
            self.id = Category.objects.latest('id').id + 1
        super(Category, self).save(*args, **kwargs)

    def __str__(self):
        if self.description is not None:
            return self.title + ": " + self.description
        else:
            return self.title

    class Meta:
        managed = False
        db_table = 'category'
        verbose_name = 'Category'
        verbose_name_plural = 'Categories'


class CategoryParents(models.Model):
    category = models.ForeignKey(Category, related_name='category_id')
    parent = models.ForeignKey(Category, related_name='parent_id')

    class Meta:
        auto_created = True
        managed = False
        db_table = 'category_parents'
        unique_together = (('category', 'parent'),)

    def __str__(self):
        if self.parent.id is 1:
            return self.category.title
        else:
            return self.parent.title + "->" + self.category.title

admin.py

class CategoryForm(forms.ModelForm):
    parents = forms.ModelMultipleChoiceField(
        queryset=Category.objects.all(),
        required=False,
        widget=FilteredSelectMultiple(
            verbose_name='Parents',
            is_stacked=False,
        )
    )

    class Meta:
        model = Category
        fields = ('title', 'id', 'description', 'url', 'active')

    def __init__(self, *args, **kwargs):
        super(CategoryForm, self).__init__(*args, **kwargs)

        # if self.instance:
        #     self.fields['parents'].initial = self.instance.parents.all()

    def save(self, commit=True):
        category = super(CategoryForm, self).save(commit=False)  
        # After this row field parents from category has value 
        # '"<Category: qwerty: test>" needs to have a value for
        # field "category" before this many-to-many relationship 
        # can be used.'
        category.parents = self.cleaned_data['parents']  # Here exception is thrown

        if commit:
            category.save()
            category.save_m2m()

        return category


class CategoryAdmin(admin.ModelAdmin):
    form = CategoryForm
    search_fields = ('title',)
    list_display = ('title', 'id', 'description', 'url', 'active')

这是根据CategoryForm生成的Django Admin表单的视图。 Here is Django admin form

填写表单并单击“保存”后,将抛出以下异常:

[05/Nov/2017 19:40:49] "GET /admin/kazanexpress/category/add/ HTTP/1.1" 200 10911
[05/Nov/2017 19:40:49] "GET /admin/jsi18n/ HTTP/1.1" 200 3189
Internal Server Error: /admin/kazanexpress/category/add/
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py", line 149, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py", line 147, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/admin/options.py", line 541, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/views/decorators/cache.py", line 57, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/admin/sites.py", line 244, in inner
    return view(request, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1437, in add_view
    return self.changeform_view(request, None, form_url, extra_context)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 67, in _wrapper
    return bound_func(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/decorators.py", line 63, in bound_func
    return func.__get__(self, type(self))(*args2, **kwargs2)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/contextlib.py", line 52, in inner
    return func(*args, **kwds)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1372, in changeform_view
    new_object = self.save_form(request, form, change=not add)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/contrib/admin/options.py", line 985, in save_form
    return form.save(commit=False)
  File "/Users/kevinkhanda/PycharmProjects/KazanexpressAdmin/kazanexpress/admin.py", line 82, in save
    category.parents = self.cleaned_data['parents']
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 480, in __set__
    manager = self.__get__(instance)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 468, in __get__
    return self.related_manager_cls(instance)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 751, in __init__
    (instance, self.source_field_name))
ValueError: "<Category: qwerty: hgfdsa>" needs to have a value for field "category" before this many-to-many relationship can be used.
[05/Nov/2017 19:42:12] "POST /admin/kazanexpress/category/add/ HTTP/1.1" 500 125267

如果有人告诉我我的错误,我会很高兴。

0 个答案:

没有答案