django 1.6.1, Form. Есть ли элегантный способ рендеринга старых данных и редактирования старых данных из модели?

У меня есть приложение «учетные записи», которое содержит пользовательскую модель User, модель Profile, которая содержит OneToOneField для User. Когда создается экземпляр пользователя, соответствующий экземпляр профиля также создается автоматически.

Теперь я разрабатываю страницу, которая содержит форму для редактирования трех полей профиля для существующего пользователя. Когда пользователь запрашивает URL-адрес типа «accounts/profile_edit/1/», если запрашивающий пользователь является законным, я сначала получаю данные его старого профиля из трех полей, а затем отвечаю на страницу редактирования со старыми данными в качестве начального значения форма.

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

То, как я получаю старые данные профиля в качестве начального значения для формы редактирования профиля.

Как я сохраняю данные редактирования для существующего профиля.

Так что, если кто-то может дать мне какой-либо совет, это будет оценено.

Поля urls.py, views.py, models.py и forms.py:

#urls.py
urlpatterns = patterns('accounts.views',
#...
    url(r'^profile_edit/(?P<user_id>\d+)/$',
        'profile_edit',
        {'template_name': 'accounts/profile_edit.html'},
        name='profile_edit'), 
#...
)


#views.py
def profile_edit(request,
    template_name, 
    user_id,
    edit_form=ProfileForm,):

    if not request.user.is_authenticated():
        return HttpResponseRedirect(reverse('accounts:login'),
        )

    #ensure the request user is the edit user
    if request.user.pk!=int(user_id):
        raise Http404

    if request.method == 'POST':
        form = edit_form(data=request.POST)
        if form.is_valid():
            form.edit(profile=request.user.profile)
            return HttpResponseRedirect(reverse('accounts:profile',kwargs={'user_id':user_id}))
    else:
        #render old profile data, also seems not elegant...how to solve it?
        profile = request.user.profile
        old_profile={'location':profile.location,
        'description':profile.description,
        'signature':profile.signature,
        }   
        form = edit_form(data=old_profile)
    context = {
    'form': form,
    }
    return TemplateResponse(request, template_name, context,)

#models.py
class User(AbstractBaseUser, PermissionsMixin):
    #lots of definations here...not related to this question

class Profile(models.Model):
    user = models.OneToOneField(User)  
    location = models.CharField(max_length=10,blank=True)  
    description = models.CharField(max_length=200,blank=True) 
    signature = models.CharField(max_length=30,blank=True) 

#forms.py
class ProfileForm(forms.ModelForm):

    class Meta:
        model = Profile
        fields = ['location', 'description', 'signature'] 

    #this is not elegant..how to solve it?
    def edit(self,profile):
        profile.location = self.cleaned_data['location']
        profile.description = self.cleaned_data['description']
        profile.signature = self.cleaned_data['signature']
        profile.save()

person tcpiper    schedule 13.01.2014    source источник


Ответы (1)


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

Ваше представление может быть изменено как

def profile_edit(request,
    template_name, 
    user_id,
    edit_form=ProfileForm,):

    if not request.user.is_authenticated():
        return HttpResponseRedirect(reverse('accounts:login'),
        )

    #ensure the request user is the edit user
    if request.user.pk!=int(user_id):
        raise Http404

    if request.method == 'POST':
        form = edit_form(data=request.POST, instance=request.user.profile)
        if form.is_valid():
            #no need for edit method
            updated_profile = form.save() 
            return HttpResponseRedirect(reverse('accounts:profile',kwargs={'user_id':user_id}))
    else:
        #no need to crate dict
        form = edit_form(instance=request.user.profile)
        context = {
          'form': form,
         }
        return TemplateResponse(request, template_name, context,)
person Rohan    schedule 13.01.2014
comment
Большое спасибо. Для других наблюдателей, кажется, опечатка: updated_profile = edit_form.save() должно быть updated_profile = form.save(). - person tcpiper; 13.01.2014