如何在 django 中使用 has many through 来获取数据?

How to data fetch by using has many through in django?

我正在学习 Django。我有一个名为客户的简单模型。这是我的模型:

class Year(models.Model):
    year = models.CharField(max_length=255)
    created_at = models.DateTimeField(auto_now=False, auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True, auto_now_add=False)

    def __unicode__(self):
        return self.year

    def __str__(self):
        return self.year


class Customer(models.Model):
    name = models.CharField(max_length=255)
    created_at = models.DateTimeField(auto_now=False, auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True, auto_now_add=False)

    def __unicode__(self):
        return self.name

    def __str__(self):
        return self.name


class Product(models.Model):
    customer_name = models.ForeignKey(Customer, on_delete=models.CASCADE)
    quantity = models.CharField(max_length=255)
    year = models.ForeignKey(Year, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now=False, auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True, auto_now_add=False)

    def __unicode__(self):
        return self.score

    def __str__(self):
        return self.score

这是我对客户的看法:

from django.shortcuts import render, get_object_or_404, redirect
from .models import Customer, Product, Year


# Create your views here.
def home(request):
    customer = Customer.objects.all
    product = Product.objects.all

    year = Year.objects.all().prefetch_related('product_set')

    context = {'customers': customer,
               'years': year,
               'products': product
               }
    return render(request, 'customer.html', context)

这是我的 customer.html

{% extends 'base.html' %}
{% block customer %}
<div class="container">
  <h2>Players Table</h2>
  <p>Customer with Product</p>
  <table class="table">
    <thead>
      <tr>
          <th>Year/Product</th>
          {% for customer in cutomers %}
              <th>{{ customer.name }}</th>
          {% endfor %}
      </tr>
    </thead>
      <tbody>


{#      <tr>#}
{#          <th>2011</th>#}
{#          <th>633</th>#}
{#          <th>424</th>#}
{#      </tr>#}
{#      <tr>#}
{#          <th>2012</th>#}
{#          <th>353</th>#}
{#          <th>746</th>#}
{#      </tr>#}
      </tbody>
  </table>
</div>

{% endblock customer %}

现在我必须生成 table 行,其中包含每年的年份、客户和产品。 因此,如何获取包含年份、基于年份的客户产品数据的每一行。

更简单, 一年有很多客户,客户有一个产品思想年。

如何生成这个。请帮助我。

在您的上下文中,您不需要产品或年份。您可以使用模型之间的关系来获取此信息:

views.py

from django.shortcuts import render, get_object_or_404, redirect
from .models import Customer, Product, Year

# Create your views here.
def home(request):
    customer = Customer.objects.all
    context = {'customers': customer}
    return render(request, 'customer.html', context)

现在在您的模板中您可以获得:

All product of a customer, with year by product

{% for customer in customers %}
   Customer : {{ customer }}<br>
   {% for product in customer.product_set.all %}
       Product : {{ product }} / Year :{{ product.year }}<br>
   {% endfor %}
{% endfor %}

但我不喜欢在模板中加入太多逻辑。 我建议您在您的视图中创建 table 的数据,在您的模型中甚至更好。然后用这些数据生成你的 html table。

您需要的功能摘要: 您可以用 filter()

替换 all()
products = customer.product_set.all() # give you all product of a customer

评论后更新:

Views.py

from django.shortcuts import render, get_object_or_404, redirect
from .models import Customer, Product, Year

# Create your views here.
def home(request):
    customers = Customer.objects.all()
    years = Year.objects.all().values_list('year', flat=True).asc() # List of year name 
    rows = []
    for year in years:
        row = [year] + [None] * len(customers) # Row with year in first column, and the rest init with same size of customers list
        for idx, customer in enumerate(customers):
            quantities = customer.product_set.filter(year__year=year).valu e_list('quantity', flat=True) # filter product by year. That can return multiple product !!! 
            row[idx + 1] = ' ,'.join(quantities) # create a string of quantities
        rows.append(row) # Add new row in our rows list
    context = {'customers': customer,
               'rows': rows}
    return render(request, 'customer.html', context)

模板:

{% extends 'base.html' %}
{% block customer %}
<div class="container">
  <h2>Players Table</h2>
  <p>Customer with Product</p>
  <table class="table">
    <thead>
      <tr>
          <th>Year/Product</th>
          {% for customer in customers %}
              <th>{{ customer.name }}</th>
          {% endfor %}
      </tr>
    </thead>
      <tbody>
        {% for row in rows %}
            <tr>
                {% for cell in row %}
                    <th>cell</th>
                {% endfor %}
            </tr>
        {% endfor %}
      </tbody>
  </table>
</div>

我认为这可以帮助您了解如何解决您的问题。我没有测试这段代码,所以可能有错误。这并不完美!