Django: если пользователь ранее ввел адрес

#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 = models.OneToOneField(Song)
поэтому, когда я пытаюсь сохранить как в song, так и в songprofile, где songprofile.песня сохраняет последний id / pk записи, созданной в песне. это неправильно?

Комментарии:

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) , вы увидите разницу.