我想创建一个模型Changelog并使其可从管理页面进行编辑。以下是它的定义方式models.py:
class Changelog(models.Model):
id = models.AutoField(primary_key=True, auto_created=True)
title = models.TextField()
description = models.TextField()
link = models.TextField(null=True, blank=True)
picture = models.BinaryField(null=True, blank=True)
Run Code Online (Sandbox Code Playgroud)
title和description是必需的,link并且picture是可选的。我想让这个模型尽可能简单,所以我选择BinaryField了FileField. 在这种情况下,我不需要担心需要备份的单独文件夹,因为 DB 将是独立的(我不需要存储文件名或任何其他属性,只需存储图像内容)。
我很快意识到,Django Admin 没有用于 的小部件BinaryField,因此我尝试将小部件用于FileField. 这是我为实现这一目标所做的(admin.py):
class ChangelogForm(forms.ModelForm):
picture = forms.FileField(required=False)
def save(self, commit=True):
if self.cleaned_data.get('picture') is not None:
data = self.cleaned_data['picture'].file.read()
self.instance.picture = data
return self.instance
def save_m2m(self):
# FIXME: this function is required by ModelAdmin, otherwise save process will fail
pass
class Meta:
model = Changelog
fields = ['title', 'description', 'link', 'picture']
class ChangelogAdmin(admin.ModelAdmin):
form = ChangelogForm
admin.site.register(Changelog, ChangelogAdmin)
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,它有点 hacky。您也可以创建自己的表单字段作为子类forms.FileField,但代码几乎相同。它对我来说很好用,但现在我在想是否有更好/标准的方法来完成同样的任务?
更好、更标准的方法是Widget为这种类型的字段创建一个。
class BinaryFileInput(forms.ClearableFileInput):
def is_initial(self, value):
"""
Return whether value is considered to be initial value.
"""
return bool(value)
def format_value(self, value):
"""Format the size of the value in the db.
We can't render it's name or url, but we'd like to give some information
as to wether this file is not empty/corrupt.
"""
if self.is_initial(value):
return f'{len(value)} bytes'
def value_from_datadict(self, data, files, name):
"""Return the file contents so they can be put in the db."""
upload = super().value_from_datadict(data, files, name)
if upload:
return upload.read()
Run Code Online (Sandbox Code Playgroud)
因此,您只需在需要的地方使用小部件,而不是对整个表单进行子类化,例如以下列方式:
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.BinaryField: {'widget': BinaryFileInput()},
}
Run Code Online (Sandbox Code Playgroud)
正如您已经注意到的,代码大致相同,但这是放置以特定方式处理的字段的正确位置。实际上,您希望在表单中更改一个字段的外观和处理方式,而您不需要更改整个表单。
| 归档时间: |
|
| 查看次数: |
1957 次 |
| 最近记录: |