Django пользовательский виджет администратора, подклассифицирующий ForeignKeyRawIdWidget
Я пытаюсь создать пользовательский виджет администратора, который будет использоваться в нескольких различных моделях для отображения пользовательского ForeignKey в модели Image. Целью является отображение миниатюры рядом с полем ввода ForeignKey. Я следовал статье в блоге здесь, но столкнулся с ошибкой:
ValueError at /admin/events/event/2697/change/
Cannot assign "11": "Event.image" must be a "Image" instance.
Похоже, что метод save_form_data
в django.forms.models
ожидает экземпляр модели Image, а не id, но я не уверен, как передать это через поле моей пользовательской модели или поле формы. Вот код:
class ImageForeignKeyWidget(ForeignKeyRawIdWidget):
def render(self, name, value, attrs=None, renderer=None, image=''):
context = self.get_context(name, value, attrs)
html = self._render(self.template_name, context, renderer)
if value:
image = Image.objects.get(id=value)
thumb = image.version_url('thumb')
image = f'''
<div style="margin-top: 5px !important;">
<a href="{image.file.url}">
<img style='border: solid 1px #ccc;' src="{thumb}"/>
</a>
</div>'''
return mark_safe(html + image)
def _render(self, template_name, context, renderer=None):
if renderer is None:
renderer = get_default_renderer()
return mark_safe(renderer.render(template_name, context))
class ImageFormField(fields.IntegerField):
def __init__(self, model=None, *args, **kwargs):
super(ImageFormField, self).__init__(*args, **kwargs)
self.widget = ImageForeignKeyWidget(model._meta.get_field('image').remote_field, admin.site)
class ImageModelField(models.ForeignKey):
def formfield(self, **kwargs):
defaults = {
'form_class': ImageFormField,
'model': self.model
}
defaults.update(kwargs)
return models.Field.formfield(self, **defaults)
Есть ли где-то другой метод, который нужно переопределить, чтобы передать экземпляр?
Решением было использование поля ModelChoiceField и определение набора запросов:
class ImageFormField(forms.ModelChoiceField):
def init(self, model=None, *args, **kwargs):
super(ImageFormField, self).init(queryset=None, *args, **kwargs)
self.widget = ImageForeignKeyWidget(model._meta.get_field('image').remote_field, admin.site)
self.queryset = Image.objects.all()