Есть код, приведённый ниже. Вопрос, почему post-запрос не срабатывает? Где я примерно ошибся? Или же form-action работает непосредственно с формами(в которые надо ручкой вбивать?) Стоит ли пробовать реализовать отдельный скрипт для заполнения базы. И будет ли возможность вызывать его непосредственно из веб-интерфейса, а не через Django-shell?
Структура проекта:
- project
- --yadirectapi
- ----models.py
- ----urls.py
- ----views.py
- --templates
- ----yandex
- -----index.html
- -----yaapi.html
В файле project/yadirectapi/models.py определена модель "кампании", и функция запроса данных через api.(Её возможно тоже стоит перенести в views, хотя я думаю, что если он через views может обратиться к функции synch, то уже в через неё, он сможет обратиться к функции get_companies.
Собственно прикрепляю код project/yadirectapi/models.py:
from django.db import models
import requests, json
from requests.exceptions import ConnectionError
from time import sleep
import sys
# Create your models here.
class Company(models.Model):
# Id компании, уникальный параметр
Id = models.IntegerField(primary_key=True)
# Название компании
Name = models.CharField(max_length=255)
# Название клиента (до 255 символов). Значение по умолчанию — наименование из настроек рекламодателя.
ClientInfo = models.CharField(max_length=255)
# Дата начала показов объявлений в формате YYYY-MM-DD. Должна быть не меньше текущей даты.
StartDate = models.CharField(max_length=20)
# Дата окончания показов объявлений в формате YYYY-MM-DD.
# Показы объявлений прекращаются в 24:00 по московскому времени (независимо от значения параметра TimeZone).
EndDate = models.CharField(max_length=20)
# Часовой пояс в месте нахождения рекламодателя
TimeZone = models.CharField(max_length=50)
# Настройки дневного бюджета кампании.
# DailyBudget = models.CharField(max_length = 255)
# Тип кампании
Type = models.CharField(max_length=255)
# Статус кампании
Status = models.CharField(max_length=255)
# Состояние кампании
State = models.CharField(max_length=255)
# Статус оплаты кампании
StatusPayment = models.CharField(max_length=255)
# Текстовое пояснение статусу
StatusClarification = models.CharField(max_length=255)
# Статистика показов и кликов
Statistics = models.CharField(max_length=255)
# Валюта кампании
Currency = models.CharField(max_length=255)
# Финансовые показатели кампании
Funds = models.CharField(max_length=255)
# Дневной бюджет кампании в валюте рекламодателя, УМНОЖЕННЫЙ НА 1 000 000
Amount = models.FloatField()
# Режим показа объявлений
Mode = models.CharField(max_length=255)
# Количество показов
Impressions = models.FloatField()
# Количество кликов
Clicks = models.FloatField()
# Сумма средств зачисленных на баланс компании за время её существование
Sum = models.FloatField()
# Текущий баланс кампании
Balance = models.FloatField()
# Деньги затраченные на кампанию за всё время её существования
Spend = models.FloatField()
def __str__(self):
return self.Name
def get_companies():
if sys.version_info < (3,):
def u(x):
try:
return x.encode("utf8")
except UnicodeDecodeError:
return x
else:
def u(x):
if type(x) == type(b''):
return x.decode('utf8')
else:
return x
CampaignsURL = 'https://api-sandbox.direct.yandex.com/json/v5/campaigns'
token = ''
# clientLogin = ''
headers = {'Authorization': 'Bearer ' + token,
# 'Client-Login': clientLogin,
'Accept-Language': 'ru',
}
body = {'method': 'get',
'params': {'SelectionCriteria': {},
'FieldNames': ['Id',
'Name',
'ClientInfo',
'StartDate',
'EndDate',
# 'TimeTargeting',
'TimeZone',
'DailyBudget',
'Type',
'Status',
'State',
'StatusPayment',
'StatusClarification',
'Statistics',
'Currency',
'Funds',
# 'Amount',
# 'Mode',
# 'Impressions',
# 'Clicks',
# 'Sum',
# 'Balance',
# 'Spend',
]
}
}
jsonBody = json.dumps(body, ensure_ascii=False).encode('utf8')
try:
result = requests.post(CampaignsURL, jsonBody, headers=headers)
if result.status_code != 200 or result.json().get("error", False):
print("Произошла ошибка при обращении к серверу API Директа.")
print("Код ошибки: {}".format(result.json()["error"]["error_code"]))
print("Описание ошибки: {}".format(u(result.json()["error"]["error_detail"])))
print("RequestId: {}".format(result.headers.get("RequestId", False)))
else:
print("RequestId: {}".format(result.headers.get("RequestId", False)))
print("Информация о баллах: {}".format(result.headers.get("Units", False)))
# Вывод списка кампаний AHTUNG!!!
for campaign in result.json()["result"]["Campaigns"]:
print("Рекламная кампания: {} №{}".format(u(campaign['Name']), campaign['Id']))
if result.json()['result'].get('LimitedBy', False):
# Если ответ содержит параметр LimitedBy, значит, были получены не все доступные объекты.
# В этом случае следует выполнить дополнительные запросы для получения всех объектов.
# Подробное описание постраничной выборки -
# https://tech.yandex.ru/direct/doc/dg/best-practice/get-docpage/#page
print("Получены не все доступные объекты.")
except requests.exceptions.ConnectionError:
# В данном случае мы рекомендуем повторить запрос позднее
print("Произошла ошибка соединения с сервером API.")
# Если возникла какая-либо другая ошибка
except:
# В данном случае мы рекомендуем проанализировать действия приложения
print("Произошла непредвиденная ошибка.")
return result
В файле project/yadirectapi/views.py определена функция synch, а так же функции отрисовки index и yaapi страниц. Тут у меня появляются некоторые опасения касаемые работы самой функции synch возможно, ошибка находится где-то в ней, а конкретно в методе update_or_create.
Прикрепляю файл project/yadirectapi/views.py:
import sys
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .models import Company
import requests, json
def index(request):
return render(request, 'yandex/index.html')
def yaapi(request):
return render(request, 'yandex/yaapi.html')
def synch(request):
if request.method == "POST":
if sys.version_info < (3,):
def u(x):
try:
return x.encode("utf8")
except UnicodeDecodeError:
return x
else:
def u(x):
if type(x) == type(b''):
return x.decode('utf8')
else:
return x
result = Company.get_companies()
for campaign in result.json()['result']['Campaigns']:
company, created = Company.objects.update_or_create(
Id=u(campaign['Id']),
Name=u(campaign['Name']),
ClientInfo=u(campaign['ClientInfo']),
StartDate=u(campaign['StartDate']),
EndDate=u(campaign['EndDate']),
TimeZone=u(campaign['TimeZone']),
Type=u(campaign['Type']),
Status=u(campaign['Status']),
State=u(campaign['State']),
StatusPayment=u(campaign['StatusPayment']),
StatusClarification=u(campaign['StatusClarification']),
Statistics=u(campaign['Statistics']),
Currency=u(campaign['Currency']),
Funds=u(campaign['Funds']),
Amount=u(campaign['DailyBudget']['Amount']),
Mode=u(campaign['DailyBudget']['Mode']),
Impressions=u(campaign['Statistics']['Impressions']),
Clicks=u(campaign['Statistics']['Clicks']),
Sum=u(campaign['Funds']['CampaignFunds']['Sum']),
Balance=u(campaign['Funds']['CampaignFunds']['Balance']),
Spend=u(campaign['Funds']['CampaignFunds']['Spend']),
defaults={"Name": Name,
"ClientInfo": ClientInfo,
"StartDate": StartDate,
"EndDate": EndDate,
"TimeZone": TimeZone,
"Type": Type,
"Status": Status,
"State": State,
"StatusPayment": StatusPayment,
"StatusClarification": StatusClarification,
"Statistics": Statistics,
"Currency": Currency,
"Funds": Funds,
"Amount": Amount,
"Mode": Mode,
"Impressions": Impressions,
"Clicks": Clicks,
"Sum": Sum,
"Balance": Balance,
"Spend": Spend,
})
return HttpResponseRedirect('/')
Ну и оставшиеся файлы project/yadirectapi/urls.py:
from django.urls import path
from . import views
urlpatterns = [
path(r'', views.index),
path(r'ya_api/', views.yaapi, name='yaapi'),
path(r'synch/', views.synch),
]
И файл project/templates/yandex/yaapi.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="POST" action={{yadirectapi.views.synch}}>
{# Пробовал ещё вот так: <form method="POST" action="synch/"> #}
{% csrf_token %}
<input type='submit' value="synch">
</form>
<a href="/">index</a>
</body>
</html>
Ну и собственно вывод консоли:
[05/Nov/2018 17:27:43] "POST /ya_api/synch/ HTTP/1.1" 404 2447
Not Found: /ya_api/synch/
И вывод на сайте по нажатию на кнопку:
Page not found (404)
Request Method: POST
Request URL: http://127.0.0.1:8000/ya_api/synch
Using the URLconf defined in erpmod.urls, Django tried these URL patterns, in this order:
admin/
ya_api/ [name='yaapi']
synch/
The current path, ya_api/synch, didn't match any of these.
Updated 5 Nov. 2018, 19:49 by egor.megagun.