我正在尝试为类别树提供管理界面。 我的类别可以有几个父母。我使用多对多的自我字段来提供它。 我也有一些使用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表单的视图。
填写表单并单击“保存”后,将抛出以下异常:
[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
如果有人告诉我我的错误,我会很高兴。