无论如何,我正在编写一个标记应用程序。我希望用户能够输入空格分隔的单词列表,而不必浏览巨大的标签列表。
有两种型号。一个包含标签的名称,另一个包含标签分配。
class Tags(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class Tagged(models.Model):
tag = models.ForeignKey(Tags)
app = models.CharField(max_length=256)
app_item = models.IntegerField()
modelform只显示标记字段,因为这是用户需要的唯一输入。
class TaggedForm(forms.ModelForm):
class Meta:
model = Tagged
fields = ('tag',)
widgets = {
'tag': TextInput(),
}
我遇到的问题是,当我能够输入空格分隔选项列表时,输入被拒绝为无效。
选择有效的选择。这个选择不是可用的选择之一。
我想要做的是获取数据,将其强制转换为有效的选择,并将清理后的数据作为选择字段返回(即:采取意外和用户友好的方式并使其符合预期并且django友好)。
我的问题是,我怎样才能尽可能地做到这一点?
感谢。
修改
解决方案遵循Tisho的建议。
数据在表单中清理,自定义保存功能处理保存,因此应用程序只需要传递一些变量。它的边缘仍然有点粗糙(例如没有权限),但它有效。
class TaggedForm(forms.Form):
tags = forms.CharField(max_length=50)
def save(self, app, app_item, tags):
# Convert tag string into tag list (whitespace and duplicates are removed here)
split_tags = list(set(tags.strip().split(' ')))
tag_list = []
for tag in split_tags:
if tag != '' and tag != u'':
tag_list.append(tag)
# Get list of current tags
current_tags = Tagged.objects.filter(app=app, app_item=app_item)
# Separate new, stable, and old tags
# (stable tags are deleted from tag_list leaving it populated by only new tags)
old_tags = []
if current_tags:
for tag in current_tags:
# Stable tags
if str(tag.tag) in tag_list:
# Delete tag from tag_list (this removes pre-existing tags leaving just new tags)
del tag_list[tag_list.index(str(tag.tag))]
# Old tags
elif not str(tag.tag) in tag_list:
old_tags.append(tag.tag)
# Remove old tags
try:
Tagged.objects.filter(tag__in=old_tags).delete()
except Tagged.DoesNotExist:
pass
# Add new tags
for tag in tag_list:
# Get tag object
try:
tag=Tags.objects.get(name=tag)
tag.save()
# Create new tag
except Tags.DoesNotExist:
tag = Tags(name=tag)
tag.save()
# Add new tagging relationship
try:
new_tag = Tagged(tag=tag, app=app, app_item=app_item)
new_tag.save()
except Tags.DoesNotExist:
pass
def clean(self):
# Get tags
try:
tags = self.cleaned_data['tags'].strip().split(' ')
except KeyError:
tags = False
# Process tags
if tags:
# Variables
tag_list = ''
# Build tag list
for tag in tags:
if tag != '' or tag != u'':
tag_list += tag + ' '
# Assign and return data
self.cleaned_data['tags'] = tag_list
return self.cleaned_data
# Just return cleaned data if no tags were submitted
else:
return self.cleaned_data
用法:标记逻辑不在应用程序逻辑中
tagged_form = TaggedForm(request.POST)
if tagged_form.is_valid():
tagged_form.save('articles', 1, request.POST.get('tags',''))
答案 0 :(得分:1)
只要您在此处只需要一个标记列表 - 您就不需要forms.ModelForm
。 ModelForm将尝试创建模型(标签)实例,因此它将需要所有字段 - app
,app_item
。一个简单的表格可以正常工作:
class TagsForm(forms.Form):
tags = forms.CharField(max_length=200)
并在视图中处理表单:
if request.POST:
form = TagsForm(request.POST)
if form.is_valid():
tags = form.cleaned_data['tags'].split(' ')
# here you'll have a list of tags, that you can check/map to existing tags in the database(or to add if doesn't exist.. some kind of pre-processing).
我不知道你的真正目标是什么,但从这里你可以显示第二种形式:
class TaggedForm2(forms.ModelForm):
class Meta:
model = Tagged
从用户输入获得标签后,创建新表单:
form = TaggedForm()
form.fields['tag'].widget = forms.widgets.SelectMultiple(choices=((t.id, t.name)
for t in Tags.objects.filter(name__in=tags)))
我不确定这是否与你需要的相近,只是在这里添加一些例子..