【问题标题】:Django - ManytoOne relations and list of data entered by userDjango - 多对一关系和用户输入的数据列表
【发布时间】:2021-03-11 06:39:45
【问题描述】:

我是 django 新手,但很想学习如何使用这个框架。

想做什么:

我有一个表单,例如,它允许用户创建一个新客户端。

所以在这个表单中我有 3 个字段:

  • 姓名
  • 说明
  • 技能

“技能”字段目前是一个文本区域,用户可以在其中复制和粘贴已存在于另一个文档 (excel) 中的列表。因此,每个元素都由分割线分隔。

我想做的是:

  • 在数据库中创建用户输入的客户端
  • 在数据库中,将用户输入的描述链接到客户端
  • 在数据库中,将用户输入的每项技能链接到名称,以便我可以在其他功能/应用程序中相互独立地处理它们。我不希望所有技能都与客户联系为一个大集团。

所以我阅读了文档并考虑使用 ForeignKey。问题是我在使用 ForeignKey 时无法获得输入文本区域。每次我使用它时,我都会得到一个像这样的空“选择列表”......

Empty list field

即使我能够做到这一点,我仍然不知道如何将每个元素与其他元素分开处理..

这是我现在的代码:

模型.py

class Post(models.Model):
    name = models.CharField(max_length=100, null=True)
    description = models.TextField(null=True)
    skills = models.TextField(null=True)
    date_posted = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE)

def __str__(self):
    return self.name

def get_absolute_url(self):
    return reverse('post-detail', kwargs={'pk': self.pk})

views.py

class PostCreateView(LoginRequiredMixin, CreateView):
    model = Post
    fields = ['name', 'description', 'skills']

def form_valid(self, form):
    form.instance.author = self.request.user
    return super().form_valid(form)

post_form.html

{% extends "taskflow/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
    <div class="content-section">
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Client</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Save</button>
            </div>
        </form>
    </div>
{% endblock content %}

作为我尝试使用外键实现的示例:

models.py

class Skills(models.Model):
    element = models.TextField(null=True)

class Post(models.Model):
    name = models.CharField(max_length=100, null=True)
    description = models.TextField(null=True)
    skills = models.ForeignKey(Skills, on_delete=models.CASCADE)
    date_posted = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    

def __str__(self):
    return self.name

def get_absolute_url(self):
    return reverse('post-detail', kwargs={'pk': self.pk})

views.py

class PostCreateView(LoginRequiredMixin, CreateView):
    model = Post
    fields = ['name', 'description', 'skills']

def form_valid(self, form):
    form.instance.author = self.request.user
    return super().form_valid(form)

如果在views.py 中,而不是调用'skills' 我调用'element',我得到一个错误,说'element' 是未定义的。 我认为使用 ForeignKey 会将技能中包含的“元素”字段包含在 Post 中包含的“技能”字段中。所以据我了解并非如此。

我做错了什么?

欢迎提供任何信息和提示。

非常感谢。

【问题讨论】:

    标签: python django forms foreign-keys many-to-one


    【解决方案1】:

    显示外键字段

    如果您想在视图中显示skills.element,则不必在字段中调用skills.element,只需在技能模型中定义__str__() 方法即可。

    class Skills(models.Model):
        element = models.TextField(null=True)
        
        def __str__(self):
            return self.element
    

    附言关于帖子和技能之间的关系,我认为可能是多对多,因为一个Post 可以拥有许多 Skills,而一个Skill 可以属于to 许多 Posts,但您当前的模型不允许这样做(任何Post 只能有一个 Skill 而一个Skill 属于to强> 很多 Post)。

    您可以通过https://docs.djangoproject.com/en/3.1/topics/db/examples/many_to_many/了解更多关于如何在 Django 中实现多对多关系的信息

    【讨论】:

    • 我测试了你的建议并将 def str 行。但是,当在 view.py 中调用字段“技能”时,我仍然会得到这个空的“选择字段”,而不是来自“元素”的文本字段。如果我直接在 views.py 中调用“元素”,我会收到一条错误消息,说它是未定义的。虽然感谢您的帮助
    • 尝试在 django 管理页面中创建 1 个技能,您会看到列表不为空。 i.stack.imgur.com/F7o5f.png.
    • 我认为你应该试试这个dev.to/zxenia/…。这篇文章可能是您尝试实现的解决方案(在帖子表单中显示技能的内联形式)
    • 这不是我想要的,因为我不希望用户每次想要添加数据时都点击“添加”按钮。我宁愿有一个大的 TextField,用户可以在其中输入一个列表。并且对于列表的每个元素,在数据库中创建一个实例。我会仔细看看你的链接。如果我找不到解决方案,我可能会使用它。
    【解决方案2】:

    ** 我改变了技能来解决 **

    我想过这个:

    • 获取 TextField 而不是 ForeignKey
    • 用户输入他的列表,例如:

    TextField

    • 然后在 Views.py 中,我尝试通过创建一个新字段并像这样使用 splitlines() 来解析它:

        class PostCreateView(LoginRequiredMixin, CreateView):
            model = Post
            fields = ['name', 'description', 'address']
      
        def form_valid(self, form):
            self.object = form.save(commit=False)
            self.object.address_list = self.object.address.splitlines()
            form.instance.author = self.request.user
            self.object.save()
            return super().form_valid(form)
      

    在这里我想我需要做一些类似的事情

    for element in self.object.address_list:
        #create object here
    

    但我真的不知道该怎么做,而且大部分时间我都得到了

    Post 对象没有属性对象

    另外,如果我在我的模板中使用:

    <p class="article-content">{{ post.address_list }}</p>
    

    我得到 ['123456', '123457', '123458']

    如果我使用:

    {{ post.address_list.1 }}

    我会得到第一个 str 字符 '

    所以一般的想法是从这个表单中获取数据库中的这个输出:

    db

    因为我想在数据库中创建每个地址的实例,链接到客户端。

    非常感谢您的帮助!

    【讨论】:

      猜你喜欢
      • 2012-04-11
      • 1970-01-01
      • 2020-10-28
      • 2021-11-10
      • 1970-01-01
      • 2015-07-05
      • 2015-11-05
      • 1970-01-01
      • 2016-02-22
      相关资源
      最近更新 更多