2

我的 MySQL 数据库中有一个名为 mysite_categories 的表,有 4 列,但出于我的目的,我只需要两个(名称,base_url)。

我目前有一个模板“*base_categories.html*”,用于手动加载类别。

base_categories.html(精简)

{% block content %}
  <div class="section" style="float: right;">
    <h4 class="gradient">Category List</h4>
    <ul>
      <li><a href="/categories/Art" id="nav_font">Art</a></li>
      <li><a href="/categories/Biography" id="nav_font">Biography</a></li>
      <li><a href="/categories/Science" id="nav_font">Science</a></li>
    </ul>
  </div>
{% endblock %}

我想做的是从数据库中提取数据并在 for 循环中使用它。就像是:

{% block content %}
  <div class="section" style="float: right;">
    <h4 class="gradient">Category List</h4>
    <ul>
      {% for category in mysite_categories %}
        <li><a href="{{ category.base_url }}" id="nav_font">{{ category.name }}</a></li>
      {% endfor %}
    </ul>
  </div>
{% endblock %}

这可能是一个新手问题,但是否可以在不创建应用程序的情况下完成类似的事情?

*EDIT 1*

这些是我的应用程序文件,我承认这可能是垃圾,我已经从很多不同的帖子中尝试了很多编辑,我确定我已经在某个地方打破了它:P。我打算删除它并重新开始,但我想我不妨张贴它看看我可能哪里出错了?

视图.py

from django.shortcuts import render_to_response
from categories.models import categoryList


def index(request):
    categories = categoryList.objects.all()
    extra_context = {"categories": categories}

    return render_to_response("myapp/index.html", extra_context)

模型.py

from django.db import models


class categoryList(models.Model):
    #id = models.IntegerField(unique=True, db_column='ID') # Field name made lowercase.
    name = models.CharField(max_length=255L, unique=True)
    base_url = models.CharField(max_length=255L, unique=True)
    thumb = models.CharField(max_length=1L, unique=True, blank=True)
    class Meta:
        db_table = 'mysite_categories'

索引.html

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<div class="section" style="float: right;">
  <h4 class="gradient">Category List</h4>
  <ul>
    {% for category in categories %}
      <li><a href="" id="nav_font">{{ category.title }}</a></li>
    {% endfor %}
  </ul>
</div>

如前所述,此时它可能是垃圾,如果你们中的任何人能帮助我解决这个问题,将不胜感激!

*EDIT 2*

base_right_panel.html

{% block content %}
  <div style="float: right;">
    <div id="base_categories" style="margin: 10px; padding-bottom: 10px;">
      {% block base_categories %}
        {% include "base_categories.html" %}
      {% endblock %}
    </div>
  </div>
{% endblock %}

*Edit 3*

base_categories.html

{% block content %}
  <div class="section" style="float: right;">
    <h4 class="gradient">Category List</h4>
    <ul>
      {% if categories %}
        {% for category in categories %}
          <li><a href="" id="nav_font">{{ category.title }}</a></li>
        {% endfor %}
      {% else %}
        <p>no data! {{ categories|length }}</p>
      {% endif %}
    </ul>
  </div>
{% endblock %}

*EDIT 4*

(应用程序名称已更改为 CategoryList)

类别列表/views.py

from django.views.generic import TemplateView
from CategoryList.models import CategorylistCategorylist #<-- Changed to match inspectdb result

class IndexView(TemplateView):
    template_name="categorylist.html" #<-- Changed name from index.html for clarity

    def get_context_data(self, **kwargs):
        context = super(IndexView, self).get_context_data(**kwargs)
        context["categories"] = CategorylistCategorylist.objects.all()
        return context

类别列表/models.py

from django.db import models

class CategorylistCategorylist(models.Model): #<-- Changed to match inspectdb
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=255L, unique=True)
    base_url = models.CharField(max_length=255L, unique=True)
    thumb = models.ImageField(upload_to="dummy", blank=True) #<-- Ignored inspectdb's suggestion for CharField

    def __unicode__(self):
        return self.name

    # Re-added Meta to match inspectdb
    class Meta:
        db_table = 'categorylist_categorylist'

类别列表/urls.py

from django.conf.urls.defaults import patterns, url, include
from django.contrib import admin
from django.conf import settings
from CategoryList import views

admin.autodiscover()

urlpatterns = patterns('',
    url(r'^$', views.IndexView.as_view(), name='categorylist'),
)

if settings.DEBUG:
    urlpatterns = patterns('',
    url(r'^media/(?P<path>.*)$', 'django.views.static.serve',
        {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
    url(r'', include('django.contrib.staticfiles.urls')),
) + urlpatterns

我的网站/urls.py

from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
from home import views as home_view
from CategoryList import views as index_view

admin.autodiscover()

urlpatterns = patterns('',
    url(r'^$', home_view.HomeView.as_view(), name="home"),

    url(r'^categories/$', index_view.IndexView.as_view(), name='categorylist'),#include('CategoryList.urls')),

    url(r'^admin/', include(admin.site.urls)),
    #url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
)

if settings.DEBUG:
    urlpatterns = patterns('',
    url(r'^media/(?P<path>.*)$', 'django.views.static.serve',
        {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
    url(r'', include('django.contrib.staticfiles.urls')),
) + urlpatterns

到目前为止,我可以加载 url“ localhost:8000/categories ”,我将看到屏幕右侧出现如预期的类别名称列表,但没有应用模板格式。在我的“*base_right_panel.html*”文件中,我尝试使用“ {% include “categorylist.html %} ”直接链接到应用程序,该应用程序显示正确的模板格式,但显示“ {% else %} ”响应从“ {% if categories %} ”而不是类别?我尝试将包含更改为指向“类别/ ”,这在浏览器中有效,但它告诉我找不到模板?

我现在好难过..?

4

2 回答 2

5

这个答案并不意味着不同意 Alasdair 的 - 它只是添加一些关于使用模板的更多信息。

对 Django 应用程序的 HTTP 请求的核心处理程序是视图。视图接收 HTTP 请求以及从 URL 捕获的任何参数,并负责返回HttpResponse将返回给浏览器的实例(或其子类之一的实例)。

视图不一定要使用任何特定的方法来创建HttpResponse. 渲染模板以包含从数据库和请求信息或 URL 参数派生的信息非常普遍,以至于有代码支持它,例如render快捷方式或其大部分过时的先行项render_to_response,但这绝不是必需的。直接构造视图是完全合法的HttpResponse

def index(request):
    return HttpResponse('This is an index page.')

或者,对于非常简单的 HTML:

def index(request):
    return HttpResponse('<html><head><title>example</title></head><body>This is an index page.</body></html>')

在实践中,我经常HttpResponse直接创建实例来返回 json 数据或动态创建的 PDF 或 Excel 文件。

将从数据库检索到的信息插入响应的一种简单方法是使用 Python 的内置字符串插值:

def index(request):
    return HttpResponse('Hello, %s' % request.user.email)

或者您可以使用高级字符串格式化选项:

def index(request):
    user_names = {}
    user_names['first_name'] = request.user.first_name
    user_names['last_name'] = request.user.last_name
    return HttpResponse('Hello, %(first_name)s %(last_name)s' % user_names)

所有这一切都建立在一点,即如何生成HttpResponse. 重要的是你返回一个。

模板系统是用于生成文本内容的强大且可扩展的工具,但仅此而已。如果您查看有关渲染模板的模板文档,您会看到一些与上面的字符串插值几乎完全相同的示例。

render_to_response是一个快捷方式,它将接受一个模板和一个上下文,并返回一个HttpResponse带有该模板和上下文的渲染内容的。为了演示,跳过它的context_instance和参数,这两个代码块实际上是相同的:content_type

def index(request):
    t = Template('Hello, {{ first_name }} {{ last_name }}')
    c = Context({'first_name': request.user.first_name, 'last_name': request.user.last_name})
    response_text = t.render(c)
    return HttpResponse(response_text)

假设存在如下定义的模板index.txt,位于设置元组中条目的顶层TEMPLATE_DIRS

index.txt
Hello, {{ first_name}} {{ last_name}}

然后上面的视图可以替换为:

def index(request):
    t = get_template('index.html')
    c = Context({'first_name': request.user.first_name, 'last_name': request.user.last_name})
    response_text = t.render(c)
    return HttpResponse(response_text)

或者,您可以跳过上下文对象的显式创建并将模板呈现为字符串,因此:

def index(request):
    return render_to_response('index.html', {'first_name': request.user.first_name, 'last_name': request.user.last_name})

在更新的 Django 版本中,您通常应该使用render快捷方式而不是render_to_response- 如果您仍在努力将上下文添加到模板中,那么详细信息就有点过多了。

def index(request):
    return render('index.html', {'first_name': request.user.first_name, 'last_name': request.user.last_name})

当然,使模板有用的部分原因是渲染引擎可以执行某些类型的逻辑和查找。我实际上并不需要明确地继续查找- 我可以作为我的上下文的一部分传入first_name并在模板中查找它的属性:last_namerequest

index_showing_context.html
Hello, {{ request.user.first_name }} {{ request.user.last_name }}

def index_showing_context(request):
    return render('index_showing_context.html', {'request': request})

在该示例中,即使传入也不是绝对必要的,因为我在上面提到的和request之间的区别之一是它始终是. 但是,这又是一门高级学科。renderrender_to_responserequestrender

因此,对于您的特定问题,您在模板中的哪个位置渲染您想要的数据并不重要,只要您已将其提供给视图的上下文并渲染正确的模板。模板实际上只是一个用于查找和构建字符串的文件名,您的上下文将被插入到该字符串中。

{% include %}模板标签是将模板片段混合到其他模板中的一种方式。如果我愿意,我可以这样设置:

header.html:
<head>
<title>This is a sample title.</title>
</head>

index.html:
<html>
{% include "header.html" %}
<body><p>This is my template body, {{ request.user.first_name }} {{ request.user.last_name }}.</p></body>
</html>

detail.html:
<html>
{% include "header.html" %}
<body><p>This is a detail page, probably for something selected in the context and given the context key 'object'.</p>
      <p>{{ object }}</p>
</body>
</html>

这很好用,但这不是唯一的选择。从您的问题中,我看到您正在使用块和模板继承。一个常见的习惯用法是定义一个基本模板,所有或几乎所有其他模板都将从中继承:

base.html
<html>
<head>
<title>{% block title %}Default title{% endblock %}</title>
{% block extra_head_elements %}{% endblock %}
</title>
<body>
{% block body_header %}Standard page header here {% endblock %}
{% block body_content %}{% endblock %}
{% block body_footer %}Standard page footer here {% endblock %}
</body>
</html>

index.html
{% extends "base.html" %}
{% block title %}index {% endblock %}
{% block body_content %}<p>This is my template body, {{ request.user.first_name }} {{ request.user.last_name }}.</p>{% endblock %}

detail.html
{% extends "base.html" %}
{% block title %}detail{% endblock %}
{% block body_content %}<p>This is a detail page, probably for something selected in the context and given the context key 'object'.</p>
      <p>{{ object }}</p>
{% endblock %}

所以最终,我不太确定你应该如何最好地将你的右面板概念拼接在一起,因为这取决于你希望你的页面工作的方式。如果它将出现在任何地方或几乎任何地方,我建议将其放入基本模板中,其余模板将扩展。如果您希望它恰好在一页上,只需将其包含在该模板中即可。如果您希望在某些但不是所有页面上使用它,那么您可以使用的模板片段{% include %}可能是最好的。

主要是了解模板引擎将如何组成您的{% include %}{% extends %}标签,并在您的视图中为模板的上下文提供必要的数据。

编辑:如果我想要一个视图和模板对来检索类别,这是一种使用示例模型代码和渲染进行布局的简单方法。还有其他选择。

index.html
<html>
<head><title>Simple category listing</title></head>
<body><p>The categories are:</p>
      <ul>
        {% for category in categories %}
          <li><a href="{{ category.base_url }}" id="nav_font">{{ category.name }}</a></li>
        {% endfor %}
      </ul>
</body>
</html>

view:
def index(request):
    categories = categoryList.objects.all()
    extra_context = {"categories": categories}
    return render_to_response("index.html", extra_context)

如果我想在多个页面上重复使用类别列表,这又回到了上面的includevs.extends讨论中。无论哪种方式,模板都将始终要求您的视图categories作为上下文变量传入。

于 2013-07-18T04:55:37.700 回答
2

您可以直接执行自定义 SQL以获取视图中的类别,并在模板中循环输出。这不需要应用程序。

如果你创建了一个模型,你就可以使用Django queryset api,非常方便,例如

mysite_categories = Category.objects.all()

这确实需要您创建一个应用程序。但是,创建一个应用程序真的很容易,只需使用startapp命令即可。

python manage.py startapp myapp

创建应用程序后,您可以使用该inspectdb命令检查您的数据库,并为您的mysite_categories表创建一个模型。

于 2013-07-17T23:41:22.667 回答