首页 > 解决方案 > 访问 Django 模板的 ManyToManyField 内容

问题描述

我正在制作一个低规格的 e-bay 克隆,我正在尝试实现一个监视列表功能,但问题是我无法访问监视列表模型中的 ManyToManyField,因此我可以使用模板中字段的内容我正在使用。为了向他们显示每个用户的关注列表,到目前为止我只得到这个结果: 在此处输入图像描述但我需要得到这样的结果: 在此处输入图像描述

我正在使用的代码:

监视列表.html

{% extends "auctions/layout.html" %}

{% load static %}

{% block title %} {{name}}'s Watchlist {% endblock %}

{% block body %}
<h2>{{name}}'s Watchlist</h2>

{% for listing in watchlist %}
<div class='listing'>
    <h3>{{ listing.list_title}}</h3>
    {% if listing.img_url == "" %}
        <a href='#'><img src="{% static 'auctions/img404.png' %}" class='img-fluid'></a>
    {% else %}
        <a href='#'><img src="{{ listing.img_url }}" class="img-fluid" alt='image of {{ listing.list_title }}'></a>
    {% endif %}
    <p>
        {{ listing.desc }}
    </p>
    <p>
        Current Bid: ${{ listing.start_bid }}
    </p>
    {% if listing.category == "" %}
        <p>Category: No Category Listed</p>
    {% else %}
        <p>Category: {{ listing.category }}</p>
    {% endif %}
    <a href='#' class='btn btn-primary' id='go'>Go To Listing</a>
</div>
{% endfor %}
{% endblock %}

视图.py

def render_listing(request, title):
    if request.method == "POST":
        form = BidForm(request.POST)
        bid = int(request.POST['new_bid'])
        listing = Auction_Listing.objects.get(list_title=title)
        comments = Auction_Comments.objects.all().filter(auction_id=listing)
        if bid < listing.start_bid:
            error = True
        else:
            error = False
            listing.start_bid = bid
            listing.save()
        return render(request, 'auctions/listing.html', {
            "listing": listing,
            "form": form,
            "comments": comments,
            "error": error
        })
    else:
        form = BidForm()
        listing = Auction_Listing.objects.get(list_title=title)
        comments = Auction_Comments.objects.all().filter(auction_id=listing)
        return render(request, 'auctions/listing.html', {
            "listing": listing,
            "form": form,
            "comments": comments,
            "error": False
        })

@login_required
def watchlist_render(request):
    user = request.user.id
    username = request.user.username
    watched = Watchlist.objects.filter(user_id=user)
    return render(request, 'auctions/watchlist.html', {
        "watchlist": watched,
        "name": username
    })

模型.py

from django.contrib.auth.models import AbstractUser
from django.db import models
from django.db.models.deletion import CASCADE

CATEGORIES = [
        ('Appliances', 'Appliances'),
         ('Tech', 'Tech'), 
         ('Gaming', 'Gaming'), 
         ('Fashion', 'Fashion'), 
         ('Sports and Fitness','Sports and Fitness'), 
         ('Other','Other'),
         ("Hygiene and Medicine","Hygiene and Medicine"), 
         ("Stationery","Stationery"),
        ('Decor', 'Decor'), 
        ('Furniture','Furniture'), 
        ('Cars and Mechanical Things','Cars and Mechanical Things'), 
        ("Tools","Tools")
    ]

# Create models here
class User(AbstractUser):
    pass

class Auction_Listing(models.Model):
    user_id = models.IntegerField(default=1)
    list_title = models.CharField(max_length=64)
    desc = models.TextField(max_length=324)
    img_url = models.URLField(max_length=200, null=True, blank=True)
    start_bid = models.IntegerField()
    category = models.CharField(choices=CATEGORIES, max_length=35, null=True, blank=True)

    def __str__(self):
        return f"ID:{self.id}, {self.list_title}: {self.desc}, {self.start_bid} posted by user:{self.user_id} in Category:{self.category}, url:{self.img_url}"

class Bids(models.Model):
    bid = models.IntegerField(default=0)
    user_id = models.IntegerField(default=1)
    auction_id = models.ManyToManyField(Auction_Listing)

    def __str__(self):
        return f"ID:{self.id}, Bid {self.bid} posted by user:{self.user_id} on auction {self.auction_id}"

class Auction_Comments(models.Model):
    user_id = models.IntegerField(default=1)
    comment = models.TextField(max_length=324, default='N/A')
    auction_id = models.ManyToManyField(Auction_Listing)

    def __str__(self):
        return f"ID:{self.id}, Comment: {self.comment} posted by user:{self.user_id} on auction {self.auction_id}"

class Watchlist(models.Model):
    user_id = models.ForeignKey(User, on_delete=CASCADE,default=1)
    auction_id = models.ManyToManyField(Auction_Listing, related_name='auction_listing')

    def __str__(self):
        return f"ID:{self.user_id} on auction {self.auction_id}"

在此先感谢您的帮助!

亲切的问候
PrimeBeat

编辑:@nigel222 要求的链接结果 在此处输入图像描述

标签: pythonhtmldjangodjango-modelsdjango-templates

解决方案


啊CS50W。我喜欢这门课程。不管怎样,我知道你卡在哪里了。您所做的是在上下文中传递 Watchlist 对象,而不是传递列表列表。

这就是你{% for listing in watchlist %}失败的原因,因为watchlist它是一个单一的对象。

相反,您可以做的是,在您的 views.py 中,获取已观看项目的完整列表,并将该列表作为上下文传入。所以:

@login_required
def watchlist_render(request):
    user = request.user.id
    username = request.user.username

    # This will give you the Watchlist instance
    watchlist = Watchlist.objects.filter(user_id=user)


    # I would recommend renaming auction_id (in your models.py file) to `auctionItems` or 'listings'
    # because it returns an object of type Auction_Listing, rather than just the id.
    # for eg. watchlist.listings.all() allows you to instinctively understand what you're trying to do.
    # Now you can extract the listings from the watchlist
    listings = watchlist.auction_id.all()
    return render(request, 'auctions/watchlist.html', {
        "watchlist": listings,
        "name": username
    })

现在在您的模板中,您可以访问列表中的每个列表:{% for listing in listings %}


推荐阅读