1

警告: 私は深い知識を持っていないので、間違ったツリーを吠えている場合はお知らせください。

とにかく、タグ付けアプリの作成に取り組んでいます。ユーザーがタグの巨大なリストをブラウズするのではなく、スペースで区切られた単語のリストを入力できるようにしたい.

2 つのモデルがあります。1 つはタグの名前を保持し、もう 1 つはタグの割り当てを保持します。

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()

モデルフォームは、ユーザーからの入力が必要な唯一のタグ フィールドを表示するだけです。

class TaggedForm(forms.ModelForm):
    class Meta:
        model = Tagged
        fields = ('tag',)
        widgets = {
            'tag': TextInput(),
        }

私が抱えている問題は、スペースで区切られた選択肢のリストを入力することはできますが、入力が無効として拒否されることです。

有効な選択肢を選択してください。その選択は、利用可能な選択肢の 1 つではありません。

私がやりたいことは、データを取得し、それを自分で有効な選択に強制し、そのきれいなデータを選択フィールドとして返すことです(つまり、予期しないものとユーザーフレンドリーなものを取り、それを期待されたジャンゴフレンドリーにする)。

私の質問は、どうすればこれを行うことができますか?

ありがとう。

編集:

解決策は 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',''))
4

1 に答える 1

1

ここでタグのリストが必要なだけである限り、. は必要ありませんforms.ModelForm。ModelForm は Model(Tags) インスタンスを作成しようとするため、すべてのフィールドが必要になります - 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).

あなたの本当の目標が何であるかはわかりませんが、ここから 2 番目のフォームを表示できます。

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))) 

これが必要なものに近いかどうかはわかりません。ここにいくつかの例を追加するだけです..

于 2012-08-01T15:22:19.970 に答える