Python Django表单,包含来自数据库的链接(URL)选项,并能够输入新URL(自由文本)
我希望能够有一个下拉列表的选择,从数据库中的链接(网址),也有一个文本输入框来创建一个新的网址 我已经看到了问题的答案 这个问题的作者给出的答案似乎最接近我的需要,但我有一些不同之处:Python Django表单,包含来自数据库的链接(URL)选项,并能够输入新URL(自由文本),python,django,django-forms,Python,Django,Django Forms,我希望能够有一个下拉列表的选择,从数据库中的链接(网址),也有一个文本输入框来创建一个新的网址 我已经看到了问题的答案 这个问题的作者给出的答案似乎最接近我的需要,但我有一些不同之处: 这些选项来自数据库 这些选项应该能够链接到URL 这对Django可行吗 我想有一个链接只有下拉。文本框将显示所选链接——此链接也将位于下拉列表中。如果在文本框中输入新链接,该链接将添加到数据库和下拉列表中 我还想从下拉列表中删除条目——这将从数据库中删除它们。可能在下拉列表中的每个链接旁边都有一个“x”,以便在
class Form(ModelForm):
detail_urls = common_fields.UrlChoiceField(
label='Detail URLs', required=False,
queryset=common_models.DetailUrl.objects.none(),
help_text='List of Detail URLs from which to pick. Can be null.')
def __init__(self, *args, **kwargs):
super(Form, self).__init__(*args, **kwargs)
if self.instance.pk:
if 'detail_urls' in self.fields:
queryset = self.instance.detail_urls.all()
self.initial.update({
'detail_urls': common_fields.UrlChoiceField(queryset=queryset)})
fields.py:
class OptionalChoiceWidget(forms.MultiWidget):
def __init__(self, *args, **kwargs):
queryset = kwargs.pop('queryset')
widgets = (
forms.Select(choices=queryset),
forms.TextInput())
super(OptionalChoiceWidget, self).__init__(*args, **kwargs)
def decompress(self, value):
if value:
if value in [x[0] for x in self.widgets[0].choices]:
return [value, '']
return ['', value]
return ['', '']
class UrlChoiceField(forms.MultiValueField):
def __init__(self, queryset, *args, **kwargs):
fields = (
forms.ModelChoiceField(queryset=queryset, required=False),
forms.CharField(required=False))
self.widget = OptionalChoiceWidget(
queryset=queryset, widgets=[f.widget for f in fields])
super(UrlChoiceField, self).__init__(fields, *args, **kwargs)
def compress(self, data_list):
if not data_list:
raise exceptions.ValidationError(
'Need to select choice or enter text for this field')
return data_list[0] or data_list[1]
class URLWidget(forms.TextInput):
"""Widget for displaying an URLField input with clickable link."""
def render(self, name, value, attrs=None):
"""Defines HTML representation for this widget."""
cls = ''
attrs = attrs or {}
if 'class' in attrs:
cls = ' ' + attrs['class']
attrs['class'] = 'autolink' + cls
html = super(URLWidget, self).render(name, value, attrs)
return safestring.mark_safe(html)
class URLField(models.CharField):
"""A CharField with milder validation of URLs than Django's URLField."""
default_validators = [validators.ValidateUrl]
def __init__(self, *args, **kwargs):
if 'max_length' not in kwargs:
kwargs['max_length'] = 512
super(URLField, self).__init__(*args, **kwargs)
def formfield(self, **kwargs):
kwargs['widget'] = URLWidget
return super(URLField, self).formfield(**kwargs)
class DetailUrlField(URLField):
"""A URLField that becomes auto-linked in list view."""
def ListDisplay(self, value=None, unused_instance=None):
if not value:
value = ''
else:
value = html_utils.escape(value)
value = filters.AutoLink(value)
return value
ListDisplay.allow_tags = True
models.py:
class MyModel(Model):
detail_urls = ct_fields.GenericRelation(
'common.DetailUrl', object_id_field='object_pk')
class DetailUrl(models.Model):
content_type = models.ForeignKey(ct_models.ContentType)
object_pk = models.PositiveIntegerField(db_index=True)
content_object = ct_fields.GenericForeignKey(fk_field='object_pk')
detail_url = common_fields.DetailUrlField(
'Detail URL', blank=True, help_text='URL to relevant information.',
max_length=255)
class Meta(object):
ordering = ('detail_url',)
unique_together = ('content_type', 'object_pk', 'detail_url')
def __unicode__(self):
return u'%s: %s' % (self.content_object, self.detail_url)
def ListDisplay(self, unused_value=None, unused_instance=None):
"""Provides formatting of detail_url in list view."""
content = self.detail_url
content = filters.AutoLink(content)
return content
ListDisplay.allow_tags = True
def ExportDisplay(self):
return self.detail_url
是的,它是可以做到的。您可以在表单中使用ModelChoiceField并指定“queryset”将值从数据库拉到下拉列表中,但我无法在表单下拉列表中显示可单击的链接。下拉菜单是一个带有选项的菜单,其中选项有一个值(通常是主键)和文本(不是链接)。你的下拉列表是什么样子的?你有这样的例子吗?或者你想用文本字段显示UL内部的链接以输入新值吗?我添加了一些文本和代码片段来回答你的问题。非常感谢。