Django не возвращает данные из базы данных на той же HTML-странице, что и форма

Это мой финальный проект для моего класса в колледже, и они потребовали от нас сделать много ненужных шагов в разработке Я думаю, что, возможно, переусложнил свой код, но я не уверен, что лучший способ исправить это. Я могу получить данные из формы в базу данных, а затем передать эти данные в соответствующее представление, где оно запрашивает yelp и помещает их в JSON-файл, а затем определенные поля из JSON-файла сохраняются в базе данных. Моя проблема в том, что я не могу отобразить данные базы данных. После просмотра моего кода я думаю, что на этом пути может быть слишком много шагов. Я думаю, что есть более простой способ сделать это, но я не хочу разрушить то, что я пытаюсь понять и сделать это еще хуже. Я также обеспокоен тем, что я сделал такой беспорядок в вещах, что он нуждается в капитальном ремонте, но я, возможно, паникую lol. Я не против беспорядка, если я могу заставить информацию отображаться на HTML-странице, но я хотел бы знать, какой лучший способ написать это, если кто-то хочет этим заняться. Я пробовал множество вариантов HTML-страницы, чтобы получить данные, но это не работает, как бы я ни писал, поэтому я подумал, что, возможно, страница перезаписывается yelping, потому что я получаю сообщение об успехе поиска, когда я должен возвращать данные на страницу из query_api. Я добавил несколько операторов печати, чтобы посмотреть, что происходит, и обнаружил, что мой dict - это только одна часть данных, а не все поля строки, и я не уверен, почему это так. Я пробовал такие вещи, как

{% for key, values in yelp_data.items %}
<tr>
    <td>{{key}}</td>
    {% for v in values %}
    <td>{{v}}</td>
    {% endfor %}
</tr>
    {% endfor %}

но я получаю ошибку "Business is not iterable".
Вот мой код:

index.html

...
<div class="row">
    <div class="col-md-4">
        <h2>Getting started</h2>
        <p>
            Click here to begin with Yelp!
        </p>
        <p><a class="btn btn-default" href="yelping">Yelp! &raquo;</a></p>
    </div>
...

views.py

...
@csrf_exempt
def yelping(request):
    if request.method == "POST":
        form = YelpForm(request.POST or None)
        if form.is_valid():
            form.save(commit=False)
            term = request.POST['term']
            location = request.POST['location']
            form.save()
            print("yelping", term, location)
            yelp_main(request)
            messages.success(request, "Search successful." )
            return render(request, 'app/yelp.html', {'form' : form})
        else:
            form = YelpForm()
        messages.error(request, "Unsuccessful Search. Invalid information.")
        form = YelpForm()
        
    assert isinstance(request, HttpRequest)
    return render(request, 'app/yelp.html')
...

yelp.py

yelp.html

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

{% block content %}

<h2>{{ title }}</h2>
<form name='YelpForm' action="" class="post-form" method="post">
    {% csrf_token %}
    <label for="term">Term: </label>
    <input id="term" type="text" name="term" placeholder="Type..." value="{{ YelpForm.term }}">
    <label for="location">Location: </label>
    <input id="location" type="text" name="location" placeholder="Where..." value="{{ YelpForm.location }}">
    <input type="submit" value="OK">
</form>
<h1>{{ yelp_data.business_name }}</h1>
{% endblock %}

app/urls.py

from django.urls import re_path, path
from app import views
from .API.YelpAPI.yelp import yelp_main, query_api

# SET THE NAMESPACE!
app_name = 'app'
# Be careful setting the name to just /login use userlogin instead!
urlpatterns=[
    path('yelp_main/', yelp_main, name='yelp_main' ),
    path('query_api/', query_api, name='query_api'),
    path('registration/', views.register_request, name='registration'),
    re_path(r'^user_login/$', views.user_login,name='user_login'),
]

capstone/urls.py

from datetime import datetime
from django.urls import re_path, path, include
from django.contrib import admin
from django.contrib.auth.views import LoginView, LogoutView
from app import forms, views

urlpatterns = [
    path('home/', views.home, name='home'),
    path('contact/', views.contact, name='contact'),
    path('about/', views.about, name='about'),
    path('admin/', admin.site.urls),
    re_path(r'^$',views.index,name='index'),
    re_path(r'^special/',views.special,name='special'),
    re_path('', include('app.urls', namespace='app')),
    re_path(r'^logout/$', views.user_logout, name='logout'),
    path('foodie/', views.foodie, name='foodie'),
    path('yelping/', views.yelping, name='yelping'),
]

models.py

...
class Business(models.Model):
    business_id = models.CharField(max_length=100)
    business_name = models.CharField(max_length=100)
    yelp_business_id = models.CharField(max_length=45, blank=True, null=True)
    phone = models.CharField(max_length=100)
    city = models.CharField(max_length=100)
    state = models.CharField(max_length=100)
    address = models.CharField(max_length=100, blank=True, null=True)
    postal_code = models.CharField(max_length=15, blank=True, null=True)
    latitude = models.DecimalField(max_digits=100, decimal_places=2, blank=True, null=True)
    longitude = models.DecimalField(max_digits=100, decimal_places=2, blank=True, null=True)
    business_stars = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=False)
    business_review_count = models.IntegerField(blank=True, null=True)
    is_open = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = True
        db_table = 'business'
        ordering = ['business_name', 'business_stars', 'is_open']
        verbose_name = 'Business Information'
        verbose_name_plural = "Business's Information"

    def __str__(self):
        return self.business_name
...

class YelpInputModel(models.Model):
    term = models.CharField(blank=True, null=False, max_length=100)
    location = models.CharField(blank=True, null=False, max_length=100)

    class Meta:
        managed = True
        db_table = 'yelpinputmodel'
...

python.exe

Performing system checks...

System check identified no issues (0 silenced).
November 11, 2022 - 10:20:42
Django version 4.1.3, using settings 'capstone.settings.development'
Starting development server at http://127.0.0.1:61098/
Quit the server with CTRL-BREAK.
[11/Nov/2022 10:20:43] "GET / HTTP/1.1" 200 2624
[11/Nov/2022 10:20:44] "GET /static/app/content/site.css HTTP/1.1" 200 723
[11/Nov/2022 10:20:44] "GET /static/app/content/bootstrap.min.css HTTP/1.1" 200 97968
[11/Nov/2022 10:20:44] "GET /static/app/scripts/modernizr-2.6.2.js HTTP/1.1" 200 52810
[11/Nov/2022 10:20:44] "GET /favicon.ico HTTP/1.1" 404 3796
[11/Nov/2022 10:20:50] "GET /yelping HTTP/1.1" 301 0
[11/Nov/2022 10:20:50] "GET /yelping/ HTTP/1.1" 200 2035
yelping dinner 08501
yelp_api dinner 08501
query_api dinner 08501
Querying https://api.yelp.com/v3/businesses/search ...
Querying https://api.yelp.com/v3/businesses/a0FEhgrOIk_M6_o0ie-NpQ ...
{'yelp_data': <Business: The Roost Restaurant>}
[11/Nov/2022 10:20:54] "POST /yelping/ HTTP/1.1" 200 2095

Проблема

Я признаю, что это выше моих сил, но я думаю, что суть в том, что ваша первая интуиция, что страница yelp.html была перезаписана, была правильной. Ваша функция yelping возвращает render(request, 'app/yelp.html'), в которой нет данных, потому что ей не был задан контекст. Теперь эта функция представления сначала вызывает yelp_main(request), которая также возвращает render(request, 'app/yelp.html'), страницу без данных. Но она вызывает def query_api(request, term, location):. Этот возвращает данные со страницей, поскольку у него есть контекст, с ним, dic. Но render(request, 'app/yelp.html', dic) возвращается в query_api, которая перезаписывает его версией страницы без данных, а затем первоначальная вызывающая функция заменяет его yelp_main другой версией страницы без данных.

Возможное решение

Вместо того, чтобы возвращать страницы с рендером, не могли бы вы просто вернуть пустой HttpResponse, а затем только в конце отправить словарь:

# views.py

from django.http import HttpResponse

@csrf_exempt
def yelping(request):

    form = YelpForm(request.POST or None)
    
    if form.is_valid():
        form.save(commit=False)
        term = request.POST['term']
        location = request.POST['location']
        form.save()
        print("yelping", term, location)
        yelp_main(request)
        messages.success(request, "Search successful." )
        return redirect('app:yelping')
        #return render(request, 'app/yelp.html', {'form' : form})
        
    messages.error(request, "Unsuccessful Search. Invalid information.")
        
    assert isinstance(request, HttpRequest)

    yelp_data = Business.objects.filter(business_id=business_id).order_by('-id').first()
    dic = {
        'yelp_data': yelp_data,
        }
    print(dic)
    
    return render(request, 'app/yelp.html', dic)

и

# yelp.py

from django.http import HttpResponse

@csrf_exempt
def yelp_main(request):
    #request.session._get_or_create_session_key()
    term = request.POST.get('term')
    location = request.POST.get('location')
    db()
    print("yelp_api", term, location)
    query_api(request, term, location)
    return HttpResponse("OK")
    #return render(request, 'app/yelp.html')


def query_api(request, term, location):
    
    print("query_api", term, location)
    response = search(API_KEY, term, location)

    businesses = response.get('businesses')

    if not businesses:
        print(u'No businesses for {0} in {1} found.'.format(term, location))
        return

    business_id = businesses[0]['id']

    response = get_business(API_KEY, business_id)

    write_to_file = json.dumps([response], indent=4)

    with open('app/API/YelpAPI/yelp.json', 'w') as f:
        f.write(write_to_file)
    
    return HttpResponse("OK")
    #return render(request, 'app/yelp.html', dic)

Почему dict печатает только одну часть данных, а не все строки, я не знаю. Может быть, это Business.objects.filter(business_id=business_id).order_by('-id').first() выдает такое?

Вернуться на верх