- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我的博文模型有一个多对多标签字段:
tags = models.ManyToManyField(PostTag)
但是编辑它很不舒服,我这样修改了我的模型:
def _get_tagging(self): # Returns comma separated list of tags
tagging = []
for tag in self.tags.all():
tagging.append(tag.name)
return ", ".join(tagging)
def _set_tagging (self, tagging): # Saves tags from comma separated list
tagging = tagging.split(", ")
self.tags.clear()
for tag in tagging:
if len(tag) < 1:
continue
try:
self.tags.add(PostTag.objects.get(name=tag))
except ObjectDoesNotExist:
self.tags.create(name=tag)
tagging = property(_get_tagging, _set_tagging)
然后我修改了我的admin.py
:
class BlogAdminForm (forms.ModelForm):
tagging = forms.CharField(required=False, label="Tags", max_length=200,
widget=forms.TextInput(attrs={'class':'vTextField'}))
class Meta:
model = BlogPost
def __init__(self, *args, **kwargs):
super(BlogAdminForm, self).__init__(*args, **kwargs)
if kwargs.has_key('instance'):
instance = kwargs['instance']
self.initial['tagging'] = instance.tagging
def save(self, commit=True):
model = super(BlogAdminForm, self).save(commit=False)
model.tagging = self.cleaned_data["tagging"]
if commit:
model.save()
return model
这很好用,但只适用于编辑对象。尝试创建新对象时出现错误。为什么?因为多对多关系可以与尚未在数据库中且没有主键的对象一起使用(“BlogPost”实例需要有一个主键值才能建立多对多关系使用)。我试图通过以这种方式编辑保存方法来解决它:
def save(self, commit=True):
model = super(BlogAdminForm, self).save(commit=False)
try:
model.tagging = self.cleaned_data["tagging"]
except ValueError:
model.save()
model.tagging = self.cleaned_data["tagging"]
if commit:
model.save()
这解决了原来的问题。但是现在 model.save()
没有调用我的管理模型的 save_model
方法:
class BlogAdmin (admin.ModelAdmin):
# ...
form = BlogAdminForm
def save_model(self, request, obj, form, change):
obj.author = request.user
obj.save()
因此,我收到一个新错误:“author_id”列中的空值违反了非空约束。
我做错了什么?我可以手动调用这个方法吗?
最佳答案
您必须在保存实例后保存标签,这意味着在您的 save_model
中执行此操作功能。这与您的标签操作代码无关:如果您查看 documentation for the Form.save
method它说:
Another side effect of using
commit=False
is seen when your model has a many-to-many relation with another model. If your model has a many-to-many relation and you specifycommit=False
when you save a form, Django cannot immediately save the form data for the many-to-many relation. This is because it isn't possible to save many-to-many data for an instance until the instance exists in the database.To work around this problem, every time you save a form using
commit=False
, Django adds asave_m2m()
method to yourModelForm
subclass. After you've manually saved the instance produced by the form, you can invokesave_m2m()
to save the many-to-many form data.
有几种方法可以解决您的问题。你可以写一个 widget在标签 ID 列表和逗号分隔的标签名称列表之间来回转换,然后调用 form.save_m2m()
在你的save_model
方法。但这种方法的缺点是,即使表单未保存(可能是因为表单其他地方的验证错误),您也必须在解码小部件的值时创建新标签。
所以我认为在这种情况下更好的方法是添加您自己的 save_tags
形式的方法:
class BlogAdminForm(forms.ModelForm):
tagging = forms.CharField(required=False, label="Tags", max_length=200,
widget=forms.TextInput(attrs={'class':'vTextField'}))
class Meta:
model = Post
def __init__(self, *args, **kwargs):
super(BlogAdminForm, self).__init__(*args, **kwargs)
if 'instance' in kwargs:
tags = (t.name for t in kwargs['instance'].tags.all())
self.initial['tagging'] = ', '.join(tags)
def save_tags(self, obj):
obj.tags = (Tag.objects.get_or_create(name = tag.strip())[0]
for tag in self.cleaned_data['tagging'].split(','))
class BlogPostAdmin(admin.ModelAdmin):
form = BlogAdminForm
def save_model(self, request, obj, form, change):
obj.author = request.user
obj.save()
form.save_tags(obj)
请注意,我将标签操作代码移到了表单中:我认为它属于这里,而不属于模型,因为它完全是关于用户输入的。我还做了一些风格上的改进:
'instance' in kwargs
比 kwargs.has_key('instance')
简单.
生成器表达式 (t.name for t in kwargs['instance'].tags.all())
比在 for
中构建列表更简单循环。
get_or_create
method是一个方便的快捷方式,避免需要 try: ... except ObjectDoesNotExist: ...
你可以直接赋值给一个ManyToMany
字段而不是调用 clear
然后 add
(另外,当标签不变时效率更高)。
关于python - Django admin.py : save_model() is not called by model. ModelForm保存方法中的save(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9646085/
当我尝试更新用户数据时,出现此错误:数据库正在尝试使用 User 类型的值更新 CharField 类型的关系字段。确保设置正确的关系。 这是我的views.py: def settings(requ
我不明白我做错了什么。我希望用户只添加公告模型的标题和描述,其余的应该自动填写。这是我的模型: class Annoucement(models.Model): username = mode
我有一个模型 models.py : class MyModelClass(models.Model): name = models.CharField(max_length=255)
我最初的问题是我试图将当前用户附加到新条目,因此我重写了 admin.ModelAdmin 下的 save_model 方法来执行 def save_model(self, request, obj,
对于覆盖 save 方法所需的所有 Django 需求,我一直在模型中使用 save() 。突然,当我正在查找需要一些额外功能的东西时,有人建议在我的管理类中覆盖 save_model() 。 我找到
我最初的问题是我试图将当前用户附加到新条目,因此我重写了 admin.ModelAdmin 下的 save_model 方法来执行 def save_model(self, request, obj,
假设我处于通常的情况,在多对多关系中有额外的字段: class Person(models.Model): name = models.CharField(max_length=128) cl
我在尝试保存 Keras 模型时遇到了一些麻烦: 这是我的代码: import h5py from keras.models import load_model try: import h5p
我有两个相关的(通过外键关系)模型并使用内联为父级创建了管理模型。在几种情况下(通过 bool 字段在管理员中编辑),我需要删除所有以前的对象(内联)并创建新对象。我尝试使用 save_model 来
我正在尝试覆盖 save_model method on a Django admin object以防止用户更改某个字段。但是,我找不到一种方法来查明该字段是否已在此方法中更改。 到目前为止,这是我
def save_model(self, request, obj, form, change): basewidth = 650 img = PIL.Image.open(form.
我需要在 ModelAdmin 类中编写一个调用 ModelAdmin.save_model() 的方法,而无需用户实际单击“保存”。 (我想这样做的原因是我在 Django Admin 对象 Vie
这是我的 admin.py: class TransactionInfoAdmin(admin.ModelAdmin): search_fields=['transactionId','sub
对于我的应用程序,当通过表单保存模型时,我需要执行额外的操作。在实践中,如果表单中存在某些条件,我需要在另一个模型中添加一个值。 为此,我有两种选择,但我想了解两者的优缺点。 使用 post_save
所以我在 Django 管理中有一个函数允许我在数据库中创建一个重复的 MyModel: def save_model(self, request, obj, form, change): i
我有以下模型: class Guest(models.Model): first_name = models.CharField(max_length=128) last_name =
我使用 tf.keras 创建了一个Sequential 模型,如下所示: model = tf.keras.Sequential() model.add(tf.keras.layers.Dense(
我有一个模型,它有一个 user 字段,需要从当前登录的用户自动填充。我可以让它按规定工作 here如果 user 字段在标准 ModalAdmin 中,但如果我正在使用的模型在 InlineMode
我训练了一个神经网络,没有任何检查点,最后我写了 tf.keras.models.save_model(model, dirpath) 来保存整个模型,它创建了以下文件: savedmodel.pb
我有一个与我以前解决的问题类似的问题,除了这次解决方案似乎不起作用: How to auto insert the current user when creating an object in dj
我是一名优秀的程序员,十分优秀!