## Установка пакета Python
### Установите пакет Python:
```python
## Уже определены связанные с Django контексты
## `allauth` необходим доступ к этому из Django
## Методы аутентификации `allauth`, такие как вход по электронной почте
## Добавьте посредника учетной записи:
## Настройки, специфические для провайдера # Для каждого провайдера на основе OAuth либо добавьте ``SocialApp`` # (`socialaccount` приложение), содержащее необходимые клиентские данные # либо перечислите их здесь:
Добавьте это в ваш проект:
## Постустановочные шаги
В корневой директории Django выполните следующую команду для создания таблиц базы данных:
Я провожу достаточно много времени на настройке OAuth через ВКонтакте с использованием QOAuth2AuthorizationCodeFlow и застрял на вопросе получения email пользователя. Я разобрался, как получать всю остальную информацию о пользователе, но не могу понять, как получить почту. В документации нет никакой информации об этом. Возможно, VK API не предусматривает этого?
Вот мой тестовый код, в котором я получаю имя, фамилию пользователя и его screen_name. Я читал на форуме, что email возвращается ВКонтакте вместе с токеном, поэтому я попытался получить QByteArray с ответом от ВКонтакте с помощью QObject::connect(this->replyHandler(), &QAbstractOAuthReplyHandler::replyDataReceived, this, &VkOAuth2::onReplyDataReceived), но там нет email, только токен и id пользователя. Может кто-то, кто работал с VK API, подскажет, как получить почту пользователя?
```cpp
VkOAuth2::VkOAuth2(QObject *parent) : QOAuth2AuthorizationCodeFlow{parent}
{ auto replyHandler = new QOAuthHttpServerReplyHandler(REDIRECT_URI.port(), qApp); setReplyHandler(replyHandler); setAccessTokenUrl(TOKEN_URL); setAuthorizationUrl(AUTH_URL); setClientIdentifier(CLIENT_ID); setClientIdentifierSharedKey(CLIENT_SECRET); setScope(SCOPE_MASK); QObject::connect(this, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, &QDesktopServices::openUrl); QObject::connect(this->replyHandler(), &QAbstractOAuthReplyHandler::replyDataReceived, this, &VkOAuth2::onReplyDataReceived); QObject::connect(this, &QOAuth2AuthorizationCodeFlow::replyDataReceived, this, &VkOAuth2::onReplyDataReceived); QObject::connect(this, &QOAuth2AuthorizationCodeFlow::granted, [this]() { const QUrl getEmail{ https://api.vk.com/method/account.getProfileInfo }; const QString token = this->token(); auto network_reply = get(getEmail, { { fields, screen_name }, { v, 5.131 } }); QObject::connect(network_reply, &QNetworkReply::finished, [network_reply] { network_reply->deleteLater(); }); });
} ```markdown
### Подключение парсера к Django
```cpp
QJsonDocument response = QJsonDocument::fromJson(network_reply->readAll());
//qDebug() << response;
});
});
this->grant();
} Я написал парсер на Python, который мониторит новые объявления на досках объявлений, каждую секунду делает запрос, чтобы найти новое объявление.
Связь парсера и CRM
Далее я написал что-то типо CRM на Django, которое ДОЛЖНО выводить новые объявления из парсера. Но у меня вопрос. Как связать парсер и CRM?
- Запустить отдельно на сервере парсер.
- Запустить отдельно Django и ловить от парсера запросы и потом выводить в новые объявления в CRM (таблицу).
Использование Celery
Я начал пробовать это реализовать через Celery. Для начала создал новый пакет в моем приложении, туда закинул скрипты моего парсера. Запустил worker Celery, запустил Django. Вызвал задачу парсера, вроде worker запустился. Но я так понял парсер работает не верно, потому что функция использует асинхронный код (asyncio). Celery, в свою очередь, работает на основе синхронных задач.
Использование вэбхуков и WebSocket
Вместо использования вэбхуков, вы можете использовать WebSocket для реального времени обновления контента в CRM. Как лучше реализовать задачу?
- Сохраните данные в базу данных.
- Используйте WebSocket для обновления контента в реальном времени без перезагрузки страницы.
Пример WebSocket реализации
channel_layer = get_channel_layer()
## Когда парсер находит новое объявление:
async_to_sync(channel_layer.group_send)( listings, # Название группы { type: listing_message, listing: data # Данные объявления }
) Вопрос по шаблону авторизации
У меня есть шаблон авторизации, в котором левая часть отвечает за авторизацию, а правая за регистрацию login.html
id=id_last_name placeholder=Введите вашу фамилию required> {% if form.last_name.errors %} <div style=color:red>{{ form.last_name.errors }}</div> {% endif %} <label for=id_password1 class=form-label></label> <input type=password class=form-input name=password1 id=id_password1 placeholder=Пароль required> {% if form.password1.errors %} <div style=color:red>{{ form.password1.errors }}</div> {% endif %} <label for=id_password2 class=form-label></label> <input type=password class=form-input name=password2 id=id_password2 placeholder=Подтверждение пароля required> {% if form.password2.errors %} <div style=color:red>{{ form.password2.errors }}</div> {% endif %} <button type=submit class=form-button>Зарегистрироваться</button> <p>У вас уже есть аккаунт? <a href=# class=form-link>Войти</a></p> </form> </div> <code class="language-markdown">id=id_last_name placeholder=Введите вашу фамилию required>
{% if form.last_name.errors %}
</code><div style="color:red">{{ form.last_name.errors }}</div>Привет, как дела?<label for="id_username" class="form-label"></label><input type="text" class="form-input" name="username" value="{%" if="" form.username.value="" %}{{="" }}{%="" endif="" %}="" id="id_username" placeholder="Введите" ваш="" username="" required="">Ошибка отправки формы.<div style="color:red">{{ form.username.errors }}</div><li>The sun is shining: Солнце светит.</li><label for="id_password1" class="form-label"></label><input type="password" class="form-input" name="password1" value="{%" if="" form.password1.value="" %}{{="" }}{%="" endif="" %}="" id="id_password1" placeholder="Введите" ваш="" пароль="" required="">Я говорю по-русски.<div style="color:red">{{ form.password1.errors }}</div>Мы должны стремиться к лучшему каждый день.<label for="id_password2" class="form-label"></label><input type="password" class="form-input" name="password2" value="{%" if="" form.password2.value="" %}{{="" }}{%="" endif="" %}="" id="id_password2" placeholder="Подтвердите" пароль="" required="">Пожалуйста, введите ваш пароль снова.<div style="color:red">{{ form.password2.errors }}</div>Привет, как дела?<button type="submit">Регистрация</button><script>
$(document).on(submit, #registration-form, function (e) {
e.preventDefault();
$.ajax({
url: /user/login/,
type: POST,
dataType: json,
data: {
email: $(#id_email).val(),
first_name: $(#id_first_name).val(),
last_name: $(#id_last_name).val(),
username: $(#id_username).val(),
password1: $(#id_password1).val(),
password2: $('#id_password2').val(), csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val() }, success: function (data){ $('#success').html(data) }, }) }) </script> </div> <!-- Авторизация --> <div class="form-container sign-in-container"> <form class="form-control-login" action="{% url 'user:login' %}" method="post"> {% csrf_token %} {% if request.GET.next %} <input type="hidden" name="next" value="{{ request.GET.next }}"> {% endif %} {{ form.non_field_errors }} <h1>Вход</h1> <div class="social-container"> <a href="#" class="social"> <i class="fab fa-google-plus-g"> <img src="{% static 'icons/vk.svg' %}" alt="vkontakte" width="38" height="38"> </i> </a> <a href="#" class="social"> <i class="fab fa-facebook-f"> <img src="{% static 'icons/odnoclassniki.svg' %}" alt="odnoclassniki" width="38" height="38"> </i> </a> <a href="#" class="social"> <i class="fab fa-linkedin-in"> <img src="{% static 'icons/google.svg' %}" alt="google" width="38" height="38"> </i> </a> </div> <label for="id_email" class="form-label"></label> <input type="email" class="form-input" name="username" id="id_email" placeholder="Телефон или почта" required> <label for="id_password" class="form-label"></label> <input type="password" class="form-input" name="password" id="id_password" placeholder="Пароль" required> <a href="#">Забыли пароль?</a> <button type="submit">Вход</button> </form> </div> <div class="overlay-container"> <div class="overlay"> <div class="overlay-panel overlay-left"> <h1>Добро пожаловать!</h1> <p>Пожалуйста, войдите, используя свои личные данные.</p> <button class="ghost" id="signIn">Вход</button> </div> <div class="overlay-panel overlay-right"> <h1>Привет, Друг!</h1> <p>Введите свои личные данные и начните арендовать вместе с нами</p> <button class="ghost" id="signUp">Регистрация</button> </div> </div> </div> </div> <div class="pop-up-close" id="pop-up-close">✖</div> </div> </div> </div>
</div> Перемещение между формами происходит с помощью javascript

from django.urls import path
from users import views
app_name = 'users'
urlpatterns = [ path('login/', views.login, name='login'), path('registration/', views.registration, name='registration'), path('profile/', views.profile, name='profile'), path('logout/', views.logout, name='logout'),
]
При неверном вводе данных при регистрации, страница обновляется и пользователю придется опять сдвигать шаблон на регистрацию, помогите настроить так чтобы не происходило обновления страницы
Вот views.py def login(request): if request.method == 'POST': form = UserLoginForm(data=request.POST) if form.is_valid(): username = request.POST['username'] password = request.POST['password'] user = auth.authenticate(username=username, password=password) if user: auth.login(request, user) if request.POST.get('next', None): return HttpResponseRedirect(request.POST.get('next')) return HttpResponseRedirect(reverse('main:index')) else: form = UserLoginForm() context: dict = { 'title': 'Lendme - Авторизация', 'form': form } return render( request, template_name='users/login.html', context=context ) def registration(request): if request.method == 'POST': form = UserRegistrationForm(data=request.POST) if form.is_valid(): form.save() user = form.instance auth.login(request, user) return HttpResponseRedirect(reverse('main:index')) else: form = UserRegistrationForm() context: dict = { 'title': 'Lendme - Регистрация', 'form': form, } return render( request, template_name='users/login.html', context=context ) 