【问题标题】:How do I pass the primary key from one model to another model and display some fields of the first model in the template?如何将主键从一个模型传递到另一个模型并在模板中显示第一个模型的某些字段?
【发布时间】:2019-08-21 05:43:24
【问题描述】:

我有 2 个模型,'Candidate' 和 'Tracker' 。 如果我愿意,我想将候选人添加到跟踪器列表中。跟踪器有一些额外的字段。但是,在跟踪器模板中,我希望显示候选人的一些详细信息,例如姓名、电话等。 基本上,跟踪器页面包含添加的候选人以及一些关于他们的额外详细信息。

候选模型.py

class Candidate(models.Model):
    name = models.CharField(max_length=100)
    phone = models.CharField(max_length=100)
    email = models.EmailField()
    current_company = models.CharField(max_length=100)
    current_designation = models.CharField(max_length=100)

    def __str__(self):
        return self.candidate_name

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

跟踪模型.py

class Tracker(models.Model):
    candidate = models.ForeignKey(Candidate, on_delete=models.CASCADE)
    position_applied = models.CharField(max_length=100)
    current_CTC = models.CharField(max_length=100)
    expected_CTC = models.CharField(max_length=100)

    def __str__(self):
        return self.position_applied

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

views.py 文件..

class TrackerCreateView(LoginRequiredMixin, CreateView):
    model = Tracker
    fields = ['current_CTC', 'expected_CTC', 'position_applied', 'candidate']

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)
class CandidateCreateView(LoginRequiredMixin, CreateView):
    model = Candidate
    fields = ['name', 'phone', 'email','current_company', 
    'current_designation']

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

到目前为止,我只是将候选者作为外键包含在内。但这需要从下拉列表中选择候选人名称,这是不切实际的。 如何在跟踪器列表中显示姓名、电话、电子邮件等?

我在候选页面上有一个按钮'添加到跟踪器'针对每个名称,它会打开 Tracker CreateView 表单并让我填写和提交详细信息。有什么方法可以自动填充形成一些肠衣? 或者我可以采取什么其他方法?也许传递主键或什么?对 urls.py 文件进行哪些更改?

注意 - 我已将候选模型中的 candidate_name 更改为 name,并将跟踪器模型中的 candidate_name 更改为 candidate,因为命名不正确且令人困惑。 但是,下面的答案仅基于以前的命名约定。

【问题讨论】:

  • 注意与你的问题无关:在你的Tracker模型中,candidate字段的related_name是错误的,它应该是trackers。这用于反向关系 (candidate.trackers),将其称为 candidates 会很奇怪:您必须调用 candidate.candidates 才能获取该候选人的所有跟踪器。
  • 注 2:在 fk 的 Tracker 模型中命名字段 candidate_name 也令人困惑。 tracker.candidate_name 返回一个 Candidate 实例,而不是候选人的姓名。 Candidate 中的 candidate_name 也让事情变得复杂。要获得名称,您现在需要执行tracker.candidate_name.candidate_name,这很难阅读并且几乎没有语法意义。你想要tracker.candidate.name。将您的字段名称更改为 candidatename

标签: django django-models django-templates django-views


【解决方案1】:

问题一:如何自定义下拉选择Candidate的显示?

您需要覆盖用于candidate_name 的实际表单字段。默认情况下这是一个ModelChoiceField,它有一个方法label_from_instance(),您可以覆盖它来决定显示什么(而不仅仅是名称):

  1. 子类 ModelChoiceField 并仅覆盖 label_from_instance()
  2. 子类ModelForm 仅覆盖candidate_name 字段,如here 所述
  3. 将该类作为form_class 添加到您的CreateView

问题 2:如何预填充 TrackerCreateView

Here 是 Django 通用 CBV 的一个非常有用的参考。您将看到CreateView 有一个get_initial() 方法,您可以使用该方法用初始值填充表单(只需将值传递给它一个字典)。对CreateView 的第一个请求是 GET 请求,因此您只需传递 URL 查询参数即可为视图提供一些附加信息。所以在你的情况下:

  1. 将查询参数添加到调用TrackerCreateView 的URL,例如在您的按钮模板中:

    <a href="{% url 'tracker-create' %}?candidate_id={{ candidate.id }}">
    
  2. 覆盖TrackerCreateView 中的get_initial() 方法。 self.request.GET 将是一个包含您的 URL 查询参数的字典:

    def get_initial(self):
        initial = super().get_initial()
        candidate_id = self.request.GET.get('candidate_id')
        if candidate_id:
            try:
                candidate = Candidate.objects.get(id=candidate_id)
            except Candidate.DoesNotExist:
                pass
            else:
                initial.update({'candidate_name': candidate})
        return initial
    
  3. 现在您的表格将预先填写候选人。

【讨论】:

  • &lt;a href="{% url 'tracker-create' %}"&gt; 这是我现在的网址。这只是我的 html 表中每个候选人名称旁边提到的链接。 url 如何知道我指的是哪个候选人?或者我应该将此链接转移到我的候选人详细信息页面,其路径为-path('candidate/&lt;int:pk&gt;/', CandidateDetailView.as_view(), name='candidate-detail'),
  • 你说{% url 'tracker-create' %}以前工作过。这就是为什么我建议使用查询参数 (?param=value)。如果你改变了url模式,当然你还需要添加所需的参数。
  • 使用您当前的 url 模式,object.id 作为 pk kwarg 传递给您的视图,即您可以使用 self.kwargs['pk'](而不是 request.GET)检索它。
  • 预填充在哪里?您的跟踪器表单没有这些字段。
  • 忽略上述消息。我的互联网连接很慢,我认为消息没有送达。我把这些修改回来了。有效 !!哇,这样的解脱。我还必须预先填写电子邮件和电话号码。假设我也将它们添加为外键,我应该对 get_initial 方法进行哪些更改?
猜你喜欢
  • 2021-12-13
  • 1970-01-01
  • 1970-01-01
  • 2013-10-13
  • 2021-05-29
  • 2017-01-31
  • 1970-01-01
  • 1970-01-01
  • 2020-06-15
相关资源
最近更新 更多