如何从 Wagtail 页面的 Orderable 中获取值,然后调用一个函数,该函数将根据 Orderable 的输入返回一个值?

问题描述 投票:0回答:2

我有一个 Django/Wagtail 项目。

我修改了 models.py 中的主页,然后在 Wagtail CMS 中填充了主页新创建的字段。

这是我的 models.py 的样子:

from django.db import models
from wagtail.core.models import Page
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, MultiFieldPanel
from wagtail.core.fields import RichTextField
from modelcluster.fields import ParentalKey
from modelcluster.models import ClusterableModel
from wagtail.core.models import Orderable
from wagtail.images.edit_handlers import ImageChooserPanel

from django.shortcuts import render




class HomePage(Page):
    templates = "templates/home/home_page.html"

    background_image = models.ForeignKey(
        'wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+'
    )
    hero_title = models.CharField(max_length=255, blank=True, null=True)
    form_placeholder_text = models.CharField(max_length=255, blank=True, null=True)
    form_cta_button_text = models.CharField(max_length=255, blank=True, null=True)
    hero_title_2 = models.CharField(max_length=255, blank=True, null=True)
    hero_title_3 = models.CharField(max_length=255, blank=True, null=True)
    description = RichTextField(blank=True, null=True)
    hero_title_4 = models.CharField(max_length=255, blank=True, null=True)

    content_panels = Page.content_panels + [
        MultiFieldPanel([
            ImageChooserPanel('background_image'),
            FieldPanel('hero_title'),
            FieldPanel('form_placeholder_text'),
            FieldPanel('form_cta_button_text'),
            InlinePanel('slider_items', label="Slider Items"),
        ], heading="Hero Section 1"),
        MultiFieldPanel([
            FieldPanel('hero_title_2'),
            InlinePanel('card_locations', label="Card Locations"),
        ], heading="Hero Section 2"),
        MultiFieldPanel([
            FieldPanel('hero_title_3'),
            FieldPanel('description'),
        ], heading="Hero Section 3"),
        MultiFieldPanel([
            FieldPanel('hero_title_4'),
            InlinePanel('column_one_items', label="Column One Items"),
            InlinePanel('column_two_items', label="Column Two Items"),
            InlinePanel('column_three_items', label="Column Three Items"),
        ], heading="Hero Section 4"),
    ]


class SliderItem(Orderable):
    page = ParentalKey(HomePage, on_delete=models.CASCADE, related_name='slider_items')
    slider_text = models.CharField(max_length=255, blank=True, null=True)
    slider_link = models.URLField(blank=True, null=True)

    panels = [
        FieldPanel('slider_text'),
        FieldPanel('slider_link'),
    ]

class CardLocation(Orderable):
    page = ParentalKey(HomePage, on_delete=models.CASCADE, related_name='card_locations')
    card_location_text = models.CharField(max_length=255, blank=True, null=True)
    card_location_link = models.URLField(blank=True, null=True)

    panels = [
        FieldPanel('card_location_text'),
        FieldPanel('card_location_link'),
    ]

class ColumnOneItem(Orderable):
    page = ParentalKey(HomePage, on_delete=models.CASCADE, related_name='column_one_items')
    column_one_title = models.CharField(max_length=255, blank=True, null=True)
    column_one_link = models.URLField(blank=True, null=True)

    panels = [
        FieldPanel('column_one_title'),
        FieldPanel('column_one_link'),
    ]

class ColumnTwoItem(Orderable):
    page = ParentalKey(HomePage, on_delete=models.CASCADE, related_name='column_two_items')
    column_two_title = models.CharField(max_length=255, blank=True, null=True)
    column_two_link = models.URLField(blank=True, null=True)

    panels = [
        FieldPanel('column_two_title'),
        FieldPanel('column_two_link'),
    ]

class ColumnThreeItem(Orderable):
    page = ParentalKey(HomePage, on_delete=models.CASCADE, related_name='column_three_items')
    column_three_title = models.CharField(max_length=255, blank=True, null=True)
    column_three_link = models.URLField(blank=True, null=True)

    panels = [
        FieldPanel('column_three_title'),
        FieldPanel('column_three_link'),
    ]

现在,在views.py 中,我创建了一个函数,该函数调用天气API 并返回该位置的温度(我将其作为参数传递)。这是函数:

def get_today_weather(location):
    """
    Fetch the weather data for the current day for a given location.
    """
    url = f"{BASE_URL}/{location}/today?unitGroup=metric&key={API_KEY}&contentType=json"
    response = requests.get(url)
    
    if response.status_code == 200:
        data = response.json()
        return data["currentConditions"]["temp"]
    else:
        return None  # Return None if there's an error

现在,我的目标是,当我访问我的主页 www.example.com 时,我希望显示我通过 Wagtail CMS(可订购)插入的所有位置的温度。

因此,如果我想获取新位置的数据,我只需转到 Wagtail CMS 并在我的 Orderable 中添加一个新位置即可。


我尝试了很多方法:

  1. 我尝试在views.py中创建一个函数来获取Orderable的值,然后调用get_today_weather函数,最后在我的home_page.html中渲染这些值。这里的问题是,当我访问我的主页 www.example.com 时,它会呈现一个全新的模板,而不是我的主页(我已使用 Wagtail 管理 CSM 字段中的数据填充该主页)。这里,数据是从 API 显示的,但不幸的是,我创建的其他字段消失了。

  2. 我尝试在 models.py 中为我的模型创建一个函数,它将调用 get_today_weath 函数,然后将数据传递到我的主页,但没有成功。


有人可以建议我解决这个问题吗?

python django wagtail
2个回答
0
投票

在主页模型上定义 a

get_context
方法。这可用于将您想要的任何其他变量添加到模板上下文中,因此您可以根据从页面的
weather_reports
关系检索到的位置创建一个
card_locations
列表:

class HomePage(Page):
    # ...

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, *args, **kwargs)
        context["weather_reports"] = [
            {
                "location": card.card_location_text,
                "weather": get_today_weather(card.card_location_text)
            }
            for card in self.card_locations.all()
        ]
        return context

然后,在您的模板中:

    <ul>
        {% for report in weather_report %}
            <li>{{ location }}: {{ weather }}</li>
        {% endfor %}
    </ul>

0
投票

这是我解决问题的方法:

首先我将views.py中的get_today_weather函数转换为models.py中的主页。

class HomePage(Page):
    templates = "templates/home/home_page.html"
    background_image = models.ForeignKey(
        'wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+'
    )
    hero_title = models.CharField(max_length=255, blank=True, null=True)
    form_placeholder_text = models.CharField(max_length=255, blank=True, null=True)
    form_cta_button_text = models.CharField(max_length=255, blank=True, null=True)
    hero_title_2 = models.CharField(max_length=255, blank=True, null=True)
    hero_title_3 = models.CharField(max_length=255, blank=True, null=True)
    description = RichTextField(blank=True, null=True)
    hero_title_4 = models.CharField(max_length=255, blank=True, null=True)
    content_panels = Page.content_panels + [
        MultiFieldPanel([
            ImageChooserPanel('background_image'),
            FieldPanel('hero_title'),
            FieldPanel('form_placeholder_text'),
            FieldPanel('form_cta_button_text'),
            InlinePanel('slider_items', label="Slider Items"),
        ], heading="Hero Section 1"),
        MultiFieldPanel([
            FieldPanel('hero_title_2'),
            InlinePanel('card_locations', label="Card Locations"),
        ], heading="Hero Section 2"),
        MultiFieldPanel([
            FieldPanel('hero_title_3'),
            FieldPanel('description'),
        ], heading="Hero Section 3"),
        MultiFieldPanel([
            FieldPanel('hero_title_4'),
            InlinePanel('column_one_items', label="Column One Items"),
            InlinePanel('column_two_items', label="Column Two Items"),
            InlinePanel('column_three_items', label="Column Three Items"),
        ], heading="Hero Section 4"),
    ]
    def get_today_weather(self, location):
        """
        Fetch the weather data for the current day for a given location.
        """
        url = f"{BASE_URL}/{location}/today?unitGroup=metric&key={API_KEY}&contentType=json"
        response = requests.get(url)
        if response.status_code == 200:
            data = response.json()
            return data["currentConditions"]["temp"]
        else:
            return None  # Return None if there's an error
    def get_all_weather_data(self):
        weather_data = []
        for card_location in self.card_locations.all():
            location_weather = self.get_today_weather(card_location.card_location_text)
            if location_weather is not None:
                weather_data.append({
                    'location': card_location.card_location_text,
                    'temperature': location_weather
                })
        return weather_data

然后我就可以在 HTML 中呈现信息了:

                {% for weather in page.get_all_weather_data %}
                <div class="single-weather">
                    <a href="#">
                        <span class="weather-box">
                            <div class="weather-img">
                                <div class="cloud cloud1">
                                    <img src="{% static 'img/Cloud1.png' %}" alt="">
                                </div>
                                <div class="sun cloud3">
                                    <img src="{% static 'img/sun.png' %}" alt="">
                                </div>
                            </div>
                            <div class="weather-containt">
                                <h3>{{ weather.location }}
                                    <span>
                                        <!-- Access the weather data for the current card location -->
                                        {{ weather.temperature }}°C
                                    </span>
                                </h3>
                                <h4>Oblacno</h4>
                                <p>Vjetar: 13km/h 236</p>
                                <p>Vlaznost: 65% </p>
                            </div>
                        </span>
                    </a>
                </div>
                {% endfor %}
© www.soinside.com 2019 - 2024. All rights reserved.