Below is the text of the page https://livedev.org/articles/tag/to stored 2008-06-08 by archive.org.ua. The original page over time could change. View as original html

Tag to, everything about to : Веб-разработка «по-русски» | lived

livedev.org [http://livedev.org] Веб-разработка «по-русски» Две модели в newforms 10 Posted by dobrych Mon, 17 Mar 2008 00:37:00 GMT На днях нужно было за короткое время решить одну несложную и довольно типичную задачу на django — построение формы профайла пользователя. Я не стал искать в закладках ссылки на старые известные how-to от мэтров-джангистов :-), а попробовал посмотреть что же нового и интересного у нас имеется в последней версии django (trunk). Итак, модель была приготовлена заранее, вопрос больше касался построения формы (через newforms ) пользовательского профайла. Итак, модель. class UserProfile(models.Model): user = models.ForeignKey(User, verbose_name=_('user'), unique=True, related_name="profile") country = models.ForeignKey(Country, verbose_name=_('country'), blank=True, null=True) city = models.CharField(verbose_name=_('city'), max_length=30, blank=True, null=True) post_zip = models.CharField(verbose_name=_('post zip'), max_length=10, blank=True) address = models.CharField(verbose_name=_('address'), max_length=250, blank=True) Обратите внимание, что профайл ссылается на модель User с unique=True . Это в принципе самый простой и работающий вариант расширения модели пользователя в django. Можно смело использовать для объекта User метод profile.get() . Например: from django.contrib.auth.models import User u = User.objects.get(username='test') profile = u.profile.get() Теперь для моделей User и UserProfile необходимо построить единую форму. Для каждой отдельной модели сделать это не проблема. А вот сделать «два в одном» не так просто. Итак, по порядку: Новенькое — широко используемые функции form_for_model и form_for_instance оказывается уже не актуальны. Они работают, но есть более новый и интересный метод получения формы для модели — ModelForm . В отличии от форм полученных через form_for_model и form_for_instance , формы от ModelForm можно наследовать (а вот это очень интересно в нашем случае!!!). Поэтому, как только эти два пункта появились в моей голове, я сразу же открыл Python-консоль и начал экспериментировать с кодом. Не уверен на 100%, что мое решение максимально красивое, но тем не менее оно вполне простое и аккуратное (особенно если учесть, что времени на «подумать» особо не было)... Итак кусочек моего forms.py ниже. from django.newforms.models import ModelForm from django.contrib.auth.models import User from django import newforms as forms from profile.models import UserProfile class ProfileForm(ModelForm): class Meta: model = UserProfile fields=('country', 'city', 'post_zip', 'address') class ProfileFormFull(ProfileForm): def __init__(self, *args, **kwargs): super(ProfileFormFull, self).__init__(*args, **kwargs) self.fields['first_name'] = User._meta.get_field('first_name').formfield() self.fields['last_name'] = User._meta.get_field('last_name').formfield() def save_user_data(self): if self.instance: user = self.instance.user user.first_name = self.cleaned_data['first_name'] user.last_name = self.cleaned_data['last_name'] return user.save() else: raise instance.DoesNotExist Теперь мои комментарии к коду (что я делаю): Создаю форму ProfileForm из моей модели UserProfile . Наследую от ProfileForm новую форму ProfileFormFull , которую буду расширять для возможности редактирования двух моделей (User и UserProfile) в одной форме. Суть расширения в добавлении двух полей из модели User ( first_name и last_name ) и метода save_user_data который эти поля сохраняет в модель User. Остальные поля из модели UserProfile обрабатываются автоматически созданным методом save . При сохранении формы нужно вызывать два метода — save и save_user_data . Я специально оставил эту возможность для моего случая. Но вы можете сделать сохранение save_user_data внутри save , расширив его. Как выглядит код, который работает с этой формой: @login_required @render_to('profile/main.html') def profile_save(request): if request.method == 'GET': return HttpResponseRedirect(reverse('profile.views.profile_page')) profile, created = UserProfile.objects.get_or_create(user=request.user) form = ProfileFormFull(data=request.POST, instance=profile) if form.is_valid(): form.save() form.save_user_data() request.user.message_set.create(message="Your profile details saved.") return HttpResponseRedirect(reverse('profile.views.profile_page')) else: return {'profile': profile, 'profile_form': form, 'user': request.user} На этом пожалуй откланиваюсь. Был бы очень рад любым конструктивным замечаниям и вопросам в комментариях. Хотелось бы унифицировать кусок кода с формой (forms.py) и может вынести в отдельный сниппет . PS: обязательно почитайте документацию по ModelForm , интересно :-) Posted in статьи Tags code , django , how , ModelForm , newforms , profile , to , user Meta 10 comments , permalink , rss , atom Searching... О блоге Мысли, идеи, задачи и решения по веб-разработке. Взгляд с персональной позиции автора. Об авторе Зовут меня Илья. В рабочее время занимаюсь веб-разработкой. Интересуюсь новыми и модными веб-технологиями. Нерабочее время посвещаю семье, по возможности фотографии и музыке . Подробнее. Tags 2008 ajax conference css development django downshifting exception javascript kiev life python rails ruby syntax typo uaweb update web xml Блогролл Amazon byteflow Маниакальный Веблог Подробно Appleworms Андрей Ясинецкий Собираю блогролл Свежие комментарии by krovati-gostinichnye on Мультисайтовость в django trunk by mybryco on Линкотека №2 by krovati-gostinichnye on Мультисайтовость в django trunk by farinaska on Не изобретая велосипед by semicon on Линкотека №2 Archives May 2008 (2) April 2008 (2) March 2008 (5) February 2008 (2) January 2008 (4) December 2007 (2) November 2007 (2) October 2007 (3) September 2007 (2) August 2007 (4) June 2007 (1) May 2007 (1) April 2007 (3) February 2007 (1) January 2007 (3) December 2006 (4) November 2006 (4) October 2006 (4) September 2006 (3) del.icio.us/dobrych/webdev Design Stencils - Yahoo! Design Pattern Library Набор wireframe для созданию web ui прототипов от Yahoo Natural Docs Софт для генерации документации из кода. Юзабельная дока получается js-ria-tools - Google Code Набор утилит для оптимизации и тестирования JavaScript, возможность минимизации файлов JS mapfish Готовое приложение (клиент и сервер) для работы с гео-данным. Построено на базе Pylons и ExtJS/Openlayers Resizable Polygons Пример создания полигонов с возможностью ресайзинга на Google maps (javascript) Python Package Index : virtualenv 1.0 Скрипт для создания варитуального окружения (модули итп) для Python-приложений Google Maps JavaScript API Example - Snap to Polyline Пример кода для привязки курсора к полигонам и полилиниям Take Control of Your Maps (A List Apart Article) Отличный обзор картографического (GIS) софта для построения веб-приложений Mapstraction - a javascript library to hide differences between mapping APIs. Библиотека JS для работы с многими картографическими сервисами через единый API Modest Maps Библиотека для ActionScript (2/3) и Python для работы с картографическими сервисами Плюшки © livedev.org / powered by typo / styled with clerkly