Django: Показать предыдущие варианты выбора пользователя для ModelForm в шаблоне - PullRequest
0 голосов
/ 16 сентября 2018

Я пытаюсь создать страницу профиля пользователя, где пользователи могут видеть и обновлять свои предпочтения для определенных вещей, например, являются ли они вегетарианцами или имеют определенную аллергию, и т. Д. Я хочу, чтобы данные отображались в виде, с их текущие настройки уже заполняют поля формы.

Итак, я создал следующую модель:

class FoodPreferences(models.Model):

    user = models.OneToOneField(User, on_delete=models.CASCADE)  # One user has one set of food prefs
    vegetarian = models.BooleanField()
    vegan = models.BooleanField()
    ...

это указано в моих формах .py:

class FoodPreferencesForm(forms.ModelForm):

    class Meta:
        model = FoodPreferences
        exclude = ('user', )

Я попытался создать представление, которое наследует FormView, а затем сослаться на форму, например:

class UserProfileView(generic.FormView):

    template_name = "registration/profile.html"
    form_class = FoodPreferencesForm
    success_url = reverse_lazy('user_profile')

Это правильно сохраняет форму в экземпляре модели, но, очевидно, она просто отображает пустую форму после обновления, поэтому пользователь не имеет представления о своих текущих предпочтениях.

Чтобы реализовать это, я подумал, что мне может понадобиться переопределить get() и post(), чтобы получить экземпляр FoodPreferences для пользователя, а затем передать эти значения в форму, как если бы вы были request.POST объектом. Однако, во-первых, я не знаю, как это сделать, а во-вторых, я бы взял на себя ответственность за правильное обновление базы данных, что уже делал FormView.

Вот что у меня есть для этого решения:

def get(self, request, *args, **kwargs):

    prefs = FoodPreferences.objects.get(user=request.user)
    form = self.form_class(prefs)
    return render(request, self.template_name, {'form': form, })


def post(self, request, *args, **kwargs):

    form = self.form_class(request.POST)
    if not form.is_valid():
        return render(request, self.template_name, {'form': form, 'error': 'Something went wrong.'})

    curr_prefs = FoodPreferences.objects.update_or_create(form.fields)
    prefs.save()

    return render(request, self.template_name, {'form': form, })

но я получаю TypeError: argument of type 'FoodPreferences' is not iterable на линии в get():

form = self.form_class(prefs)

потому что он не ожидает экземпляра модели.

Думаю ли я об этом правильно? Это кажется достаточно распространенной проблемой, что у Django есть что-то встроенное, чтобы сделать это, но я ничего не могу найти.

1 Ответ

0 голосов
/ 16 сентября 2018

Вам редко нужно определять get или post в представлении на основе классов, а вам определенно нет здесь.

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

Во-вторых, вы должны указать классу, как получить существующий объект для обновления, что вы можете сделать, определив get_object. Итак:

class UserProfileView(generic.UpdateView):

    template_name = "registration/profile.html"
    form_class = FoodPreferencesForm
    success_url = reverse_lazy('user_profile')

    def get_object(self, queryset=None):
        return self.request.user.foodpreferences
        # or, if you aren't certain that the object already exists:
        obj, _ = FoodPreferences.objects.get_or_create(user=self.request.user)
        return obj
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...