Как вставить в url имя пользователя на django. django-allauth

Domohod45

Новичок
Пользователь
Дек 7, 2021
68
3
8
Я сделал регистрацию на django при помощи django-allauth, я сделал шаблон для профиля пользователя, однако адрес на этот шаблон не содержит имени пользователя.
сейчас это так:
а нужно:
в документации к allauth есть раздел для пользовательских перенаправлений с помощью адаптера.
Python:
# project/settings.py:
ACCOUNT_ADAPTER = 'project.users.adapter.MyAccountAdapter'

# project/users/adapter.py:
from django.conf import settings
from allauth.account.adapter import DefaultAccountAdapter

class MyAccountAdapter(DefaultAccountAdapter):

    def get_login_redirect_url(self, request):
        path = "/accounts/{username}/"
        return path.format(username=request.user.username)
И это действительно работает, имя пользователя отображается в url адресе, но этот адрес ведет на 404 страницу.
что мне нужно изменить для решения мой задачи? Помогите пожалуйста.

Windows 10.
 

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
в views.py я переписал код адаптера
Код адаптера лучше перенести в adapter.py
Во views.py можно создать простой обработчик на основе TemplateView например:
Python:
from django.views.generic import TemplateView


class Profile(TemplateView):
    template_name = 'registration/profile.html'
потом импортировать его в urls.py и должно работать.
Также в ссылке нужно указать параметр <str:username> и она должна идти в списке после ссылок для allauth чтобы не перекрывать их.
у меня возникает ошибка об отсутствии as_view
Ошибка возникает потому, что у вас класс унаследован от адаптера а не от вью.
 
Последнее редактирование:
  • Мне нравится
Реакции: Domohod45

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
что мне нужно изменить для решения мой задачи
Нужно создать ссылку (в urls.py) для обработки данного адреса.
Вот пример:
Python:
# urls.py
urlpatterns = [
    path('admin/', admin.site.urls), # ссылки для админки
    path('accounts/', include('allauth.urls')),  # ссылки для allauth
    # после ссылок для allauth нужно добавить ссылку для обработки адреса для редиректа
    # Home - это пример обработчика из views.py, его нужно создать и импортировать
    # также в нем нужно прописать используемый шаблон
    path('accounts/<str:username>/', Home.as_view(), name='home'),
]
 
  • Мне нравится
Реакции: Domohod45

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
Может есть причина в том, что я использовал request.user в ссылке html?
request.user указывает на текущего пользователя (того, который перешел на страницу и соответственно был получен из request`a)
я не могу перейти на другой профиль.
то есть, если вставить в ссылку профиль с именем другого пользователя, то ты переходишь на собственный профиль.
При переходе по ссылке на экран выводится html, который прописан в шаблоне.
Видимо у вас в шаблоне выводится профиль для текущего пользователя.
 

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
хм... шаблону вообще все равно, что принимать.
На сайте отображается html, который прописан в шаблоне. Данные в шаблон передаются из обработчика (вью), а выбор этого обработчика осуществляется в зависимости от ссылки (в urls).
я могу что угодно писать после profile/, но страница все равно вернет профиль пользователя. как так?
Все правильно, любые символы после profile/ в адресе соответствуют шаблону ссылки
Python:
path('profile/<str:username>/', Profile.as_view(), name='profile')
если нужно чтобы шаблон показывался только если после profile/ указан существующий username, то
можно сделать проверку во вью.
Например такую:
Python:
from django.views.generic import TemplateView
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.models import User


class Profile(TemplateView):
    template_name = 'registration/profile.html'

    def get(self, request, username):
        user = get_object_or_404(User, username=username)

        return render(request, template_name)
 

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
Почему же шаблон profile работает только для 1 человека
Это зависит от того что написано в шаблоне.
да, это работает, но основная проблема все же остается
Как я понял вам нужно чтобы при переходе на страницу другого пользователя на экран выводилось "Страница пользователя {{username}}".
Это можно сделать так: получить пользователя по его username`у в адресной строке и потом передать его в шаблон, а в шаблоне выводить.
Вот простой пример:
Python:
# адрес в адресной строке
http://127.0.0.1/profile/user1
Python:
# ссылка (ссылочный шаблон) для обработки адреса
path('profile/<str:username>/', Profile.as_view(), name='profile'),
Python:
# обработчик(вью)
class Profile(TemplateView):
    template_name = 'registration/profile.html'

    def get(self, request, username):
        # получаем пользователя по username если он существует
        user = get_object_or_404(User, username=username)
        # передаем его в шаблон как profile
        return render(request, self.template_name, {'profile': user})
HTML:
<!-- Шаблон registration/profile.html-->
<!-- profile - это пользователь, которому принадлежит страница (определяется по username в адресе) -->
<h1>{{profile.username}}`s page</h1>
<!-- Здесь user - это request.user (тот кто смотрит страницу) -->
<!-- Если смотрит страницу залогиненый пользователь - то -->
{% if user.is_authenticated %}
<!-- Выведет - вы вошли как user.username -->
<p>You are logged in as {{ user.username }}</p>
{% else %}
<!-- Если не залогиненый - выведет вы не вошли -->
<p>You are not logged in.</p>
<!-- тут можно добавить ссылку на login -->
{% endif %}
 

Domohod45

Новичок
Пользователь
Дек 7, 2021
68
3
8
Нужно создать ссылку (в urls.py) для обработки данного адреса.
Вот пример:
Python:
# urls.py
urlpatterns = [
    path('admin/', admin.site.urls), # ссылки для админки
    path('accounts/', include('allauth.urls')),  # ссылки для allauth
    # после ссылок для allauth нужно добавить ссылку для обработки адреса для редиректа
    # Home - это пример обработчика из views.py, его нужно создать и импортировать
    # также в нем нужно прописать используемый шаблон
    path('accounts/<str:username>/', Home.as_view(), name='home'),
]
Логично, у меня возникает ошибка об отсутствии as_view
Код:
    path('profile/', Profile.as_view(), name='profile'),
AttributeError: type object 'Profile' has no attribute 'as_view'
в views.py я переписал код адаптера:
Python:
from allauth.account.adapter import DefaultAccountAdapter

class Profile(DefaultAccountAdapter):

    template_name = 'registration/profile.html'

    def get_login_redirect_url(self, request):
        path = "/profile/{username}/"
        return path.format(username=request.user.username)

settings.py:
ACCOUNT_ADAPTER = "registration.views.Profile"

ссылку я вставлял не в url проекта, а в url приложения registrations
registrations/urls.py:

Python:
from .views import Profile

urlpatterns = [
    ...
    # другие url
    ...
    path('profile/', Profile.as_view(), name='profile'),
]

полагаю мне нужно что-то изменить в Profile.as_view()?
 

Domohod45

Новичок
Пользователь
Дек 7, 2021
68
3
8
Код адаптера лучше перенести в adapter.py
Во views.py можно создать простой обработчик на основе TemplateView например:
Python:
from django.views.generic import TemplateView


class Profile(TemplateView):
    template_name = 'registration/profile.html'
потом импортировать его в urls.py и должно работать.
Также в ссылке нужно указать параметр <str:username> и она должна идти в списке после ссылок для allauth чтобы не перекрывать их.

Ошибка возникает потому, что у вас класс унаследован от адаптера а не от вью.
это сработало! спасибо! однока есть проблема.
я не могу перейти на другой профиль.
то есть, если вставить в ссылку профиль с именем другого пользователя, то ты переходишь на собственный профиль.
Может есть причина в том, что я использовал request.user в ссылке html?
HTML:
<a href="{% url 'profile' request.user %}" >
                {% avatar user 100 class="Avatar" %}
</a>
PS: я вошел за 2 разных пользователях на 2 браузерах.

а request.user я использую из0за того, что без него возникает ошибка на главной странице:

NoReverseMatch at /​

Reverse for 'profile' with no arguments not found. 1 pattern(s) tried: ['profile/(?P<username>[^/]+)/$']
 
Последнее редактирование:

Domohod45

Новичок
Пользователь
Дек 7, 2021
68
3
8
request.user указывает на текущего пользователя (того, который перешел на страницу и соответственно был получен из request`a)

При переходе по ссылке на экран выводится html, который прописан в шаблоне.
Видимо у вас в шаблоне выводится профиль для текущего пользователя.
хм... шаблону вообще все равно, что принимать.
я могу что угодно писать после profile/, но страница все равно вернет профиль пользователя. как так?
 

Domohod45

Новичок
Пользователь
Дек 7, 2021
68
3
8
На сайте отображается html, который прописан в шаблоне. Данные в шаблон передаются из обработчика (вью), а выбор этого обработчика осуществляется в зависимости от ссылки (в urls).

Все правильно, любые символы после profile/ в адресе соответствуют шаблону ссылки
Python:
path('profile/<str:username>/', Profile.as_view(), name='profile')
если нужно чтобы шаблон показывался только если после profile/ указан существующий username, то
можно сделать проверку во вью.
Например такую:
Python:
from django.views.generic import TemplateView
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.models import User


class Profile(TemplateView):
    template_name = 'registration/profile.html'

    def get(self, request, username):
        user = get_object_or_404(User, username=username)

        return render(request, template_name)
да, это работает, но основная проблема все же остается. Имена других пользователей не работают в ссылках, только теперь при введении их в адрес показывается вместо профиля вошедшего пользователя 404 страница.
Почему же шаблон profile работает только для 1 человека?В этом "виноват" сам шаблон(как вы и писали) или что-то не так в urls.py?
Сильно извиняюсь, что я заставляю вас так много внимания уделять этому вопросу.
 

Domohod45

Новичок
Пользователь
Дек 7, 2021
68
3
8
да, это работает, но основная проблема все же остается. Имена других пользователей не работают в ссылках, только теперь при введении их в адрес показывается вместо профиля вошедшего пользователя 404 страница.
Почему же шаблон profile работает только для 1 человека?В этом точно
Сильно извиняюсь, что я заставляю вас так много внимания уделять этому вопросу.

Это зависит от того что написано в шаблоне.

Как я понял вам нужно чтобы при переходе на страницу другого пользователя на экран выводилось "Страница пользователя {{username}}".
Это можно сделать так: получить пользователя по его username`у в адресной строке и потом передать его в шаблон, а в шаблоне выводить.
Вот простой пример:
Python:
# адрес в адресной строке
http://127.0.0.1/profile/user1
Python:
# ссылка (ссылочный шаблон) для обработки адреса
path('profile/<str:username>/', Profile.as_view(), name='profile'),
Python:
# обработчик(вью)
class Profile(TemplateView):
    template_name = 'registration/profile.html'

    def get(self, request, username):
        # получаем пользователя по username если он существует
        user = get_object_or_404(User, username=username)
        # передаем его в шаблон как profile
        return render(request, self.template_name, {'profile': user})
HTML:
<!-- Шаблон registration/profile.html-->
<!-- profile - это пользователь, которому принадлежит страница (определяется по username в адресе) -->
<h1>{{profile.username}}`s page</h1>
<!-- Здесь user - это request.user (тот кто смотрит страницу) -->
<!-- Если смотрит страницу залогиненый пользователь - то -->
{% if user.is_authenticated %}
<!-- Выведет - вы вошли как user.username -->
<p>You are logged in as {{ user.username }}</p>
{% else %}
<!-- Если не залогиненый - выведет вы не вошли -->
<p>You are not logged in.</p>
<!-- тут можно добавить ссылку на login -->
{% endif %}
похоже дело в django-allauth, а не в шаблоне.
мой профиль состоит из аватара, даты регистрации, имя пользователя.
все эти данные по-прежнему принимают значения пользователя за которого я вошел. Изменить некоторые из них можно изменив " user.username" на "'profile.username" к примеру в
<p>You are logged in as {{ user.username }}</p>
Изменяется: имя, аватар на профиле

Однако в ситуации с датой регистрации где используется {{ user.date_joined|date:"DATETIME_FORMAT" }} это не работает( просто престает выводится дата).

Для изменения аватара при помощи django avatar есть ссылка
<a href="{% url 'avatar_change' %}" class="link">
При переходе на которую выводятся фотографии для пользователя я вошел.

Получается, нужно для каждого элемента в шаблоне , связанного с пользователем нужно profile.useravatar; profile.userregistrationdata, которые надо прописать во views? Это странно и наверняка неверно, и вы уже 2 написали, что все завись от того, что прописано в шаблоне, но я все не могу, что в нем не так.
вот, что я подключаю в profile.html
HTML:
{% load avatar_tags %}
{% render_avatar avatar 250 %}
{% load account %}
{% load i18n %}
{% load static %}
 

stud_55

Модератор
Команда форума
Модератор
Апр 3, 2020
1 522
672
113
похоже дело в django-allauth, а не в шаблоне.
django-allauth служит только для регистрации через сторонние сервисы (соцсети и т. д.) и к проблеме отображения данных в профиле отношения не имеет.
Вы можете отключить django-allauth, потом сделать так чтобы все работало как вам нужно с помощью стандартных средств аутентификации джанго (по логину и паролю), а потом снова подключить django-allauth и все продолжит работать.
Изменяется: имя, аватар на профиле

Однако в ситуации с датой регистрации где используется {{ user.date_joined|date:"DATETIME_FORMAT" }} это не работает( просто престает выводится дата).
Проверил вывод даты регистрации в шаблон.
Если заменить user на profile, то дата отображается. Так как profile это такой же пользователь и у него тоже есть дата регистрации.
Для изменения аватара при помощи django avatar есть ссылка
<a href="{% url 'avatar_change' %}" class="link">
При переходе на которую выводятся фотографии для пользователя я вошел.
Видимо django avatar работает только с текущим пользователем, что вполне логично, так как менять свой аватар должен только сам пользователь.
Можно просто показывать ссылку на смену аватара только хозяину профиля.
Например сделать простую проверку:
HTML:
{% if user == profile %}
<!-- Показываем ссылку на смену аватара-->
{% endif %}
Получается, нужно для каждого элемента в шаблоне , связанного с пользователем нужно profile.useravatar; profile.userregistrationdata, которые надо прописать во views? Это странно и наверняка неверно, и вы уже 2 написали, что все завись от того, что прописано в шаблоне, но я все не могу, что в нем не так.
Если вы хотите в профиле выводить данные для пользователя, то они должны где-то храниться и при запросе передаваться в шаблон для вывода.
Обычно для сайтов с профилями (соц. сетей, форумов и т. д.) это делается в моделях. Создается модель profile связанная с user с помощью отношения один-к-одному. В этой модели хранятся все данные пользователя и вспомогательные методы (например, получение абсолютной ссылки на профиль, получение полного имени и т. д.), а также возможно связи с другими пользователями через отношения многие-ко-многим. Создание экземпляра модели часто автоматизируют с помощью сигнала (привязывают к сохранению нового пользователя).
У вас в проекте видимо это не реализовано. Так что чтобы не прописывать что-то дополнительно во вью лучше реализуйте это сначала в модели, а потом можно будет передавать в шаблон пользователя по ссылке из адреса и из его профиля выводить нужные данные.
Если не знаете как это лучше реализовать можете посмотреть видеоуроки по созданию социальной сети на django (их можно найти на youtube).

Ваш изначальный вопрос был связан с переопределением адреса редиректа после логина через django-allauth. Проблема заключалась в отсутствии ссылочного шаблона для обработки адреса (а также обработчика для него).
Вопрос был решен, остальные вопросы относятся к особенностям реализации вашего проекта, а не к регистрации через django-allauth.
Также для каждого вопроса создавайте отдельную тему, потому что для пользователей, которые ищут ответ на конкретный вопрос не удобно читать большие темы с большим количеством сообщений не относящихся непосредственно к ответу на вопрос.
 

Форум IT Специалистов