【问题标题】:Django-taggit tag value retrieval and formatting failingDjango-taggit 标记值检索和格式化失败
【发布时间】:2020-07-04 09:02:29
【问题描述】:

我正在尝试为个人资料实施标记过程,以便您可以添加您的爱好。 我选择了 django-taggit,因为它看起来很简单,可以做我需要的事情,而且我真的不知道如何从头开始自己做。 我已经设法让它在某种程度上发挥作用,但我遇到了 3 件事:

  1. 我不太确定控制这些标签的表单字段的最佳方法是什么,因为我使用表单元功能中的小部件调整自动生成表单,但在解决以下两个问题后它可能会正常工作。
  2. 当没有字段爱好(标签)的数据时,该字段将填充一个值“[]”的标签,如下图所示。

  1. 当我添加“音乐”标签并在重新加载页面后提交表单时,我会根据图像得到这个“[]”。我以为图书馆会处理这件事,但我在网上看不到另一个类似的情况。

当我尝试添加另一个“游戏”标签并保存并重新加载时,会发生以下情况。初始值再次被包装。

我的模型是:

class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
hobbies = TaggableManager()

我的表格是:

class UserProfileForm(forms.ModelForm):

    class Meta:
        model = UserProfile
        fields = ['hobbies',]

    def __init__(self, *args, **kwargs):
      super(UserProfileForm, self).__init__(*args,**kwargs)
      self.fields['hobbies'].widget = forms.TextInput()
      self.fields['hobbies'].widget.attrs['data-role'] = "tagsinput"
      self.fields['hobbies'].widget.attrs['class'] = "form-control"
      self.fields['hobbies'].required = False

我的视图函数是:

if request.method == 'POST':
        user_profile = UserProfile.objects.get(user=request.user)
        form = UserProfileForm(request.POST, instance=user_profile)
        print(form)
        if form.is_valid():
            obj = form.save(commit=False)
            obj.user = request.user
            obj.save()
            print("Form valid")
            form.save_m2m()

使用:

<script src="/static/js/tagsinput.js"></script>
<link rel="stylesheet" href="{% static 'css/tagsinput.css' %}" />

【问题讨论】:

  • 您不能将TextInput 用作小部件,因为这将在值上使用str(..),因此列表确实会格式化为[..]
  • 您可能想查看自动完成小部件:django-autocomplete-light.readthedocs.io/en/master/taggit.html
  • @WillemVanOnsem 我使用 self.fields['hobbies'].widget = forms.TextInput() 作为标签字段。我还没有转向系统中已使用标签的自动完成功能。我正在努力正确显示数据并正确保存。因为我第二次添加新标签时,前一个标签被包装在另一个包装器中。将在问题中添加图片。

标签: python django django-forms tagging django-taggit


【解决方案1】:

所以经过相当多(数百次)的测试,我终于缩小了问题所在,并试图以成功的结果解决它。 似乎数据通过我正在使用的 tagsinput 库修改为标签对象。仅当在 forms.py 中将“数据角色”指定为“tagsinput”时,数据才会作为这些对象到达 html 端并且显示不正确。因此,我想保持数据干净,最后只应用 data-role='tagsinput' 用于视觉方面,我使用的是:

var hobbiesTags = document.getElementById("id_hobbies");
  if(hobbiesTags){
  var att = document.createAttribute("data-role");
  att.value = "tagsinput";
  hobbiesTags.setAttributeNode(att);
  };

结果如下。也许有更好的方法可以做到这一点,我不确定,但这是一个非常干净的解决方案。分享您的替代方案。

【讨论】:

    【解决方案2】:

    我也遇到了同样的问题。

    一种解决方案是应用data-role="tagsinput" AFTER,您将标签列表转换为表单的逗号分隔字符串。

    解决方案如下:

    class MyModelForm(forms.ModelForm):
    
        class Meta:
            model = MyModel
    
        def __init__(self, **kwargs):
            self.fields['tags'].widget.attrs['value'] = ", ".join(list(self.instance.tags.names()))
            self.fields['tags'].widget.attrs['data-role'] = "tagsinput"
    

    输出:

    如您所见,在多词标签周围出现引号存在问题。它还会将带有引号的新标签保存到数据库中。

    如果多词短语周围没有出现双引号,这将是最优雅的解决方案。如果将来有人解决了这个问题,请留言!

    我的模板是这样的:

      <div class="m-3 p-3 border">
        <form method="POST" enctype="multipart/form-data">
          {% csrf_token %}
          {{ form|crispy }}
          <button class="btn btn-primary" type="submit">Save Form</button>
        </form>
      </div>
    

    我知道我可以使用模板标签从标签字段本身中去除多余的引号,但是我必须手动创建所有表单字段才能设置标签模板标签。

    目前,我的解决方案是简单地使用 Javascript 并只修改表单的 Meta 小部件部分。

    最终答案(暂时):

    forms.py

    class MyModelForm(forms.ModelForm):
    
        class Meta:
            model = MyModel
    
            widgets = {
                'tags': forms.TextInput(attrs={
                    "data-role": "tagsinput",
                })
            }
    

    custom.js - 将此脚本放在加载表单的页面上。

    document.addEventListener("DOMContentLoaded", function(event) {
        let tags_input = document.querySelector('#id_tags');
        let tags_input_value = tags_input.value;
        let new_value = [...tags_input_value.matchAll(/<Tag:\s*([\w\s]+)>/g)].map(([, m]) => m).join(', ')
        tags_input.setAttribute('value', new_value);
    }
    

    所以我们所做的只是修改前端的表现形式,而保持所有后端内部表单功能不变。

    【讨论】:

      猜你喜欢
      • 2017-10-14
      • 1970-01-01
      • 2015-05-02
      • 1970-01-01
      • 1970-01-01
      • 2019-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多