django模板中的外部方法访问

时间:2015-10-15 11:08:44

标签: django django-models django-templates

我是初学者。 我尝试访问Product模板层中模型ProductDetailView的相关项。如何检索ImageField s'的ProductBrand' BrandImages?我必须遍历一个前进和一个后退ForeignKey

已修改为包含 get_logo_url

get_logo_url函数有什么问题?

产品/ models.py

class Product(models.Model):

    brand = TreeForeignKey('Brand', verbose_name='parent category', related_name='products', default='')
    title = models.CharField(max_length=120)
    description = models.TextField(max_length=500, blank=True, null=True)
    price = models.DecimalField(decimal_places=2, max_digits=20)
    active = models.BooleanField(default=True)
    category = TreeForeignKey('Category', verbose_name='parent category', related_name='products', default='')
    slug = models.SlugField(default='')

    objects = ProductManager()

    class Meta:
            unique_together = ('slug', 'category')

    def get_absolute_url(self):
        return reverse("product_detail", kwargs={"pk":self.pk})

    def __unicode__(self):
        return self.title

    def get_image_url(self):
        img = self.productimage_set.first()
        if img:
            return img.image.url
        return img

品牌/ models.py

def image_upload_to(instance, filename):
    title = instance.brand.title
    slug = slugify(title)
    file_extension = filename.split(".")[1]
    new_filename = "%s.%s" % (instance.id, file_extension)
    return "products/%s/%s" % (slug, new_filename)

class BrandImage(models.Model):

    brand = models.ForeignKey('Brand', related_name='brandimages') 
    is_slider = models.BooleanField(default=False)
    is_featured = models.BooleanField(default=False)
    is_logo = models.BooleanField(default=False)
    image = models.ImageField(upload_to=image_upload_to)

    def __unicode__(self):
        return self.brand.title

   def get_logo_url(self):
      if is_logo:
         img = self.brandimage_set.first()
         if img:
            return img.image.url
         return img

    def thumb(self):
        if self.image:
            return u'<img src="%s" width=120 height=120 />' % (self.image.url)
        else:
            return u'No image file found'
    thumb.allow_tags = True

class Brand(MPTTModel):

    title = models.CharField(max_length=50, default='')
    parent = TreeForeignKey('self', null=True, blank=True, verbose_name='parent brand', related_name='brands')
    slug = models.SlugField(unique=True)

    def get_absolute_url(self):
            return reverse('brands', kwargs={'path': self.get_path()})

    def __unicode__(self):
        return self.title

模板

<div class="rightpart">
    <div class="prodbrand h2">
        <h1>{{ product.brand }}</h1>        
        <div class="brandlogo">
            {% for image in product.brand.brandimages.all %}
                <img src="{{image.get_logo_url }}"/>
            {% endfor %}
        </div>
    </div>
    <div class="prodtitle"><h2>{{ product.title }}</h2>
</div>

views.py

 class ProductDetailView(DetailView):
    model = Product
    template_name = 'products/product.html'

    def get_context_data(self , *args , **kwargs):
        context = super(ProductDetailView , self).get_context_data(*args,**kwargs)
        instance = self.get_object()
        context["related"] = Product.objects.get_related(instance)
        return context

urls.py

url(r'^$', ProductDetailView.as_view(), name='products'),

有没有办法在这样的django模板中访问外来字段?

1 个答案:

答案 0 :(得分:2)

当您使用ListView来展示您的产品时,需要注意以下几点:

  • get_context_data()必须返回字典:return context缺少
  • 如果您决定在稍后的某个时间点继承super().get_context_data,则应使用*args,**kwargs调用
  • ProductListView
  • super().get_context_data将包含一个object_list键,其中包含get_queryset()返回的对象列表,在您的案例Product的对象中。

当从模板访问属性时,如果可调用,django将尝试在没有参数的情况下调用它。这通常很有用,例如:{{ request.user.is_authenticated }}product.brand.brandimages.all

您的模板应如下所示:

<强> product_list.html

{% for product in object_list %}
    <div class="rightpart">
        <div class="prodbrand h2">
            <h1>{{ product.brand }}</h1>      
            <div class="brandlogo">    
                {% for image in product.brand.brandimages.all %}
                    <img src="{{image.image.url}}"/>
                {% endfor %}
            </div><!-- End brandlogos -->
        </div><!-- End prodbrand -->
        <div class="prodtitle">
            <h2>{{ product.title }}</h2>
        </div>
    </div><!-- End rightpart -->
{% endfor %}

考虑到这将导致从模板中进行多次数据库查找。您通常希望避免表示层进入数据库的情况,这就是您希望在相应的View中进行数据库查找的原因。同样,对于属性访问,请考虑使用select_relatedprefetch_related,以避免不必要的数据库查询。

<强> views.py

class ProductListView(ListView):

    model = Product
    queryset = Product.objects.all().active()

    def get_context_data(self, *args, **kwargs):
        context = super(ProductListView, self).get_context_data(*args, **kwargs)
        context["now"] = timezone.now()
        return context

    def get_queryset(self, *args, **kwargs):
        # We call super() for potential subclasses
        queryset = super(ProductListView, self).get_context_data(*args, **kwargs)
        queryset.prefetch_related('brand__brandimages')
        return queryset