Форма обновления пользователя Django и представление

Я очень рано нахожусь в своем пути разработки Django/Python, большинство вещей, которые я смог медленно понять после нескольких часов/дней царапанья головы и проб/ошибок. Теперь у меня есть часто задаваемый вопрос, который я не могу заставить работать правильно:

Как создать представление/форму обновления профиля пользователя?

Я взломал несколько решений из Stack Overflow и просто не могу понять, что я делаю неправильно до сих пор. Вот первоначальная версия моей неудачной попытки с использованием Django 1.9:

#forms.py
class profileForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'email']

#views.py
@login_required
def profile(request):
    if request.method == 'POST':
        form = profileForm(data=request.POST, instance=request.user)
        update = form.save(commit=False)
        update.user = request.user
        update.save()
    else:
        form = profileForm(instance=request.user)

    return render(request, 'profile.html', {'form': form})

#urls.py
urlpatterns = [
    url(r'^dashboard/$', views.dashboard, name='dashboard'),
    url(r'^dashboard/profile$', views.profile, name='profile'),
]

#profile.html
<form action="." method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Update Profile</button>
</form>

Таким образом, текущее поведение моего обновления профиля пользователя заключается в том, чтобы не обновлять ни одно из указанных полей в форме при POST, но страница загружается по другому URL-адресу. Например, URL-адрес формы обновления профиля — /dashboard/profile, который перенаправляет на /dashboard при отправке формы. Если я вручную добавлю адрес электронной почты/имя/фамилия в администраторе Django, он правильно отображается в моей форме... Я просто не могу заставить его сохранять обновленные данные.

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

Заранее извиняюсь за глупый вопрос, я погуглил и попробовал другие решения, но я либо не могу получить те же начальные ошибки, либо не могу получить рабочую версию, как подробно.

Всем спасибо и хорошего дня/ночи!

ИЗМЕНИТЬ:

Я также пробовал это решение Как обновить объект пользователя без создания нового one?, который также имеет такое же поведение: не обновляет ни одно из указанных полей в форме при POST, но страница загружается по другому URL-адресу... что меня больше смущает, возможно, проблема связана с моим urls.py вместо этого?


person TRACT    schedule 26.05.2016    source источник


Ответы (2)


Здесь нет ничего конкретного для пользователей. У вас есть две проблемы: первая из-за ваших URL-адресов. Вид вашего профиля не заканчивается косой чертой, поэтому действие формы «.» отправляет его родительскому элементу "/dashboard" и вообще не обрабатывает код обработки.

url(r'/dashboard/profile/$'...)

Во-вторых, модель не будет обновлена, потому что вы не вызвали метод проверки формы.

if request.method == 'POST':
    form = profileForm(data=request.POST, instance=request.user)
    if form.is_valid():
        form.save()
        return redirect('somewhere')

Обратите внимание, что здесь нет причин использовать commit=False; экземпляр уже является пользователем.

person Daniel Roseman    schedule 26.05.2016
comment
Спасибо за объяснение, Даниэль, очень признателен - urls.py должен был быть первым местом, которое я проверил со странным поведением при отправке. В вашем примере отсутствует двоеточие if form.is_valid(): Еще раз спасибо. - person TRACT; 26.05.2016

Я пробовал с абстрактным пользователем, и он отлично работает. Прежде всего, я создал приложение с именем Dashboard. Затем перезапишите модель пользователя по умолчанию.

Теперь обновите приложение панели инструментов — models.py, urls.py, forms.py и views.py.

В models.py

class User(AbstractUser):    
    middle_name = models.CharField(max_length=50, blank=True, null=True)
    sdl_service_code = models.CharField(choices=SDL_CHOICES, max_length=5)
    account = models.CharField(choices=ACCOUNT_CHOICES, max_length=5)

Я сделал эту новую модель пользователя (в приложении панели инструментов) моделью пользователя django по умолчанию, обновив файл настроек, как показано ниже.

В settings.py

AUTH_USER_MODEL = 'dashboard.User'

В urls.py

urlpatterns = [
    path('users', ListUserView.as_view(), name='users'),
    path('users/add/', CreateUserView.as_view(), name='users-add'),
    path('users/<int:pk>/', UpdateUserView.as_view(), name='users-edit'),
    )
]

В Forms.py

class UserForm(forms.ModelForm):            
        middle_name = forms.CharField(required=False, max_length=50)
        password = forms.CharField(widget=forms.PasswordInput())
        about_company = form.CharField(required=False, max_length=50)

        def __init__(self, *args, **kwargs):
            super(UserForm, self).__init__(*args, **kwargs)
            for field in iter(self.fields):
                self.fields[field].widget.attrs.update({
                    'class': 'form-control',
                    'placeholder': '{}'.format(field).replace("_", ' ').capitalize(),

                })

            self.fields['email'].widget.attrs['placeholder'] = '[email protected]'
            self.fields['email'].required = True
            self.fields['first_name'].required = True
            self.fields['last_name'].required = True
            self.fields['password'].required = True

            if self.instance.pk:
                self.fields['username'].required = False
                self.fields['username'].widget.attrs['readonly'] = True
                self.fields['email'].required = False
                self.fields['email'].widget.attrs['readonly'] = True
                self.fields['password'].widget.attrs['readonly'] = True
                self.fields['password'].required = False

        def save(self, *args, **kwargs):
            self.date_joined = date.today()
            super(UserForm, self).save(*args, **kwargs)
            return self

        class Meta:
            model = User
            fields = '__all__'
            exclude = ('date_joined',)

В views.py

from dashboard.models import User
from django.views.generic import ListView, DetailView, CreateView, UpdateView
from dashboard.forms import UserForm

class CreateUserView(CreateView):
    model = User
    template_name = 'dashboard/user_add.html'
    form_class = UserForm

    def get_success_url(self):
        return '/users'

class UpdateUserView(UpdateView):
    model = User
    form_class = UserForm
    template_name = 'dashboard/user_add.html'
    success_url = '/users'

class ListUserView(ListView):
    model = User
    template_name = 'dashboard/user_list.html'
person Nids Barthwal    schedule 26.08.2019
comment
Это не имеет отношения к моему первоначальному вопросу, принятое решение Дэниела Роузмана более 3 лет назад напрямую решает проблемы в моем коде. - person TRACT; 30.08.2019