#django #django-templates #django-forms #django-views
#django #django-шаблоны #django-формы #django-просмотры
Вопрос:
Я хочу предоставить пользователю форму, если он не заполнил ее ранее при входе в систему, но перенаправить его на домашнюю страницу, если он ранее заполнил информацию. Как мне этого добиться?
Вот мое мнение:
def makinginfo(request):
form = SongForm(request.POST or None)
songprofile = SongProfile.objects.get().filter(user=request.user)
if songprofile = null: IS THIS RIGHT?
if form.is_valid():
form.save()
sp = SongProfile
sp.song = form.pk
sp.save()
if 'next' in request.POST:
next = request.POST['next']
else:
next = reverse('index_show')
return HttpResponseRedirect(next)
return render_to_response(
'song/create.html',
{'form':form},
context_instance = RequestContext(request)
)
else:
return render_to_response(
'song/show.html',
context_instance = RequestContext(request)
)
Я на правильном пути?
Спасибо,
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ:
SongProfile и Песня — это две разные модели. Модель SongProfile следующая: class SongProfile(models.Model):
поэтому, когда я пытаюсь сохранить как в song, так и в songprofile, где songprofile.песня сохраняет последний id / pk записи, созданной в песне. это неправильно?
song = models.OneToOneField(Song)
Комментарии:
1. 1) Вам не нужен
.get()
. Сделайте это простоSongProfile.objects.filter(user=request.user)
2)null
не существует в Python. ЭквивалентNone
, но все, что вам нужно сделать, это проверитьif songprofile:
3) Вообще говоря, отношения «Один к одному» имеют смысл только в том случае, если вам нужно добавить информацию в модель, которую вы не контролируете. Если вы управляете обоими, поля наSongProfile
должны просто продолжатьсяSong
. 4) В последнем файле вам не хватает параметра словаря данныхrender_to_response
, передайте пустой dict ({}
), если вам ничего не нужно.
Ответ №1:
Я предполагаю, что для каждого пользователя существует только один объект SongProfile.
try:
songprofile = SongProfile.objects.get(user=request.user)
# Render song/show.html
except SongProfile.DoesNotExist:
if form.is_valid():
# Process post
# Render song/create.html
Для создания нового объекта SongProfile с песней, созданной формой:
song = form.save()
songprofile = SongProfile(user=request.user)
songprofile.song = song
songprofile.save()
ОТРЕДАКТИРУЙТЕ ЕЩЕ РАЗ:
Исправлены ошибки в обратном направлении и добавлен объект Song.
Комментарии:
1. @Natim Это синтаксически правильная версия
songprofile = null
, да, но при использованииget()
несуществующий результат вызывает исключение — not возвращает null.2. Да, я знаю, что ваш ответ хороший 🙂 Я просто сказал ему, так как он спросил, правильно ли это.
3. SongProfile и Песня — это две разные модели. Модель SongProfile следующая:
class SongProfile(models.Model): song = models.OneToOneField(Song)
поэтому, когда я пытаюсь сохранить как в song, так и в songprofile, где songprofile. песня сохраняет последний id / pk записи, созданной в песне. это неправильно?4. также не должно ли быть наоборот … songprofile. должен ли not exist отображать форму и обрабатывать post?
Ответ №2:
Вы действительно можете сделать try/catch
, как продемонстрировал Тим, и это сработает. Если вы обнаружите, что в некоторых случаях начинаете фильтровать больше полей или что вам нужно разумное значение по умолчанию, вы можете поступить так, как предлагают документы, и использовать get_or_create()
метод, например:
sp, created = SongProfile.objects.get_or_create(user=request.user)
Из документов:
Любые аргументы ключевого слова, переданные в get_or_create() — за исключением необязательного, называемого defaults — будут использоваться в вызове get(). Если объект найден, get_or_create() возвращает кортеж этого объекта и значение False. Если объект не найден, get_or_create() создаст экземпляр и сохранит новый объект, возвращая кортеж нового объекта и значение True.
Таким образом, логическое значение указывает, нужно ли создавать объект или нет, и вы можете использовать его для руководства логикой метода.
Этот синтаксис тоже немного короче и чище.
Что касается попытки сохранить оба Song
и SongProfile
, нет, вы не ошибаетесь. Как продемонстрировал Тим, form.save()
создается новый адрес song
и songprofile.song = song
, после чего songprofile.save()
сохраняется songprofile
ссылка на песню.
В примере кода есть пара небольших ошибок. Одна ошибка,
if songprofile = null:
...
который, если бы вы его использовали, как отметил @Natim, должен быть,
if songprofile is None:
...
Другая проблема в строке,
sp = SongProfile
который Python действительно скомпилирует, но который присваивает SongProfile
ссылку на объект класса переменной, а не экземпляру самого класса. Обычно вы хотите сделать следующее,
sp2 = SongProfile()
и это создаст экземпляр объекта. Если вы выполните dir(sp)
и dir(sp2)
, вы увидите разницу.