Найти - Пользователи
Полная версия: INSERT вместо UPDATE
Начало » Django » INSERT вместо UPDATE
1
SorrowFuck
Есть модель:
class UserAbout(models.Model):
    user = models.ForeignKey(User, related_name='UserAboutToUser', unique=True)
    about = models.TextField(max_length = 1000, blank=True, null=True, unique=False)
    family = models.TextField(max_length = 140, blank=True, null=True, unique=False)
    why = models.CharField(max_length = 140, blank=True, null=True, unique=False)
    trust = models.TextField(max_length = 140, blank=True, null=True, unique=False)
    hobby = models.CharField(max_length = 1000, blank=True, null=True, unique=False)
    job = models.TextField(max_length = 140, blank=True, null=True, unique=False)
    politic = models.CharField(max_length = 140, blank=True, null=True, unique=False)
    book = models.TextField(max_length = 140, blank=True, null=True, unique=False)
    film = models.TextField(max_length = 140, blank=True, null=True, unique=False)
    music = models.TextField(max_length = 140, blank=True, null=True, unique=False)
    
class UserAboutForm(ModelForm):
    class Meta:
        model = UserAbout
        exclude = ('user',)

Есть представление которое должно обновлять данные в таблице.
def UserProfileEdit(request, *offset):
    if request.user.is_authenticated() and request.user.username == offset[0]:
        if request.method == 'POST':
            if offset[1] == 'person':
                form = UserAboutForm(request.POST)
                mainProfile = User.objects.get(username = offset[0])
                if form.is_valid():
                    addProfile = UserAbout(user = mainProfile, 
                                      about = request.POST.get('about'), 
                                      family = request.POST.get('family'), 
                                      why = request.POST.get('why'), 
                                      trust = request.POST.get('trust'), 
                                      hobby = request.POST.get('hobby'), 
                                      job = request.POST.get('job'), 
                                      politic = request.POST.get('politic'), 
                                      book = request.POST.get('book'), 
                                      film = request.POST.get('film'), 
                                      music = request.POST.get('music'),)
                    addProfile.save()
                return HttpResponseRedirect("/profile/print/%s/%s/" %(offset[0], offset[1]))
Не могу добиться от него именно обновления данных, запрос с такого кода идет на INSERT и соответственно БД возвращает ошибку, т.к. дублируется первичный ключ.
FishHook
Ой-ой. Что это Вы делаете, какой страшный код.
1. Почему Вы не используете формы для валидации и сохранения данных?
form.save()
вместо кучи
about = request.POST.get('about'), 
2. Откуда фреймворк должен знать, что Вам нужно апдейтить, а не инсертить? Если в Вашем коде нужен апдейт, то сделайте инстанс модели и апдейтите его, полученными данными
You may have noticed Django database objects use the same save() method for creating and changing objects. Django abstracts the need to use INSERT or UPDATE SQL statements. Specifically, when you call save(), Django follows this algorithm:

If the object's primary key attribute is set to a value that evaluates to True (i.e., a value other than None or the empty string), Django executes a SELECT query to determine whether a record with the given primary key already exists.
If the record with the given primary key does already exist, Django executes an UPDATE query.
If the object's primary key attribute is not set, or if it's set but a record doesn't exist, Django executes an INSERT.
The one gotcha here is that you should be careful not to specify a primary-key value explicitly when saving new objects, if you cannot guarantee the primary-key value is unused. For more on this nuance, see Explicitly specifying auto-primary-key values above and Forcing an INSERT or UPDATE below.
SorrowFuck
FishHook
Ой-ой. Что это Вы делаете, какой страшный код.1. Почему Вы не используете формы?2. Откуда фреймворк должен знать, что Вам нужно апдейтить, а не инсертить?
Я использовал формы весьма успешно, пока не столкнулся с exclude.
Форма валидна, а записывать ее нельзя т.к. она в базе будет пустое поле user.
Из-за этого такую муть и по-написал.
If the record with the given primary key does already exist, Django executes an UPDATE query.
Запись то с таким первичным ключом уже существует, в том-то и загвоздка, что Django не выполняет UPDATE.
Хотя, я думаю, что все будет вглядить гораздо проще если по нормальному сделаю с формой. Но не знаю как записать за один раз и PK и форму.
                form = UserAboutForm(request.POST)
                mainProfile = User.objects.get(username = offset[0])
                if form.is_valid():
                    addProfile = UserAbout(user = mainProfile, form)
                    addProfile.save()
Так не работает.
FishHook
Самый тупой и простой вариант
.....
user = models.ForeignKey(User, related_name='UserAboutToUser', unique=True, null=True, bkank=true)
.....
if form.is_valid():
                    mainProfile = User.objects.get(username = offset[0])
                    addProfile =form.save()
                    addProfile.user=mainProfile
                    addProfile.save()
А еще можно __init__ у формы переопределить, или save или заюзать form.instance + get_or_cretate, да еще много что можно придумать, но только не так как у Вас
SorrowFuck
FishHook
Самый тупой и простой вариант
Я попробовал в лоб, для простоты. На что postgre выругался:

2012-12-04 03:51:51 VLAT ERROR:  duplicate key value violates unique constraint "users_userabout_user_id_key"
2012-12-04 03:51:51 VLAT DETAIL:  Key (user_id)=(1) already exists.
2012-12-04 03:51:51 VLAT STATEMENT:  
UPDATE "users_userabout" 
SET "user_id" = 1, "about" = '1', "family" = '2', "why" = '3', "trust" = '4', 
"hobby" = '5', "job" = '6', "politic" = '7', "book" = '8', "film" = '9', "music" = '10' 
WHERE "users_userabout"."id" = 2 
2012-12-04 03:51:51 VLAT ERROR:  current transaction is aborted, commands ignored until end of transaction block
2012-12-04 03:51:51 VLAT STATEMENT:  SHOW default_transaction_isolation
Причин такой ругани на апдейт я не понимаю.
reclosedev
addProfile = form.save(commit=False)
?
SorrowFuck
reclosedev
?
То же самое выходит:
2012-12-04 05:00:57 VLAT ERROR:  duplicate key value violates unique constraint "users_userabout_user_id_key"
2012-12-04 05:00:57 VLAT DETAIL:  Key (user_id)=(1) already exists.
2012-12-04 05:00:57 VLAT STATEMENT:  INSERT INTO "users_userabout" ("user_id", "about", "family", "why", "trust", "hobby", "job", "politic", "book", "film", "music") VALUES (1, '1', '2', '3', '4', '5', '6', '7', '8', '9', '10') RETURNING "users_userabout"."id"
reclosedev
Так если он существует, значит надо сначала его найти
...
try:
    addProfile = UserAbout.objects.get(user=request.user)
except UserAbout.DoesNotExist:
    addProfile = None
form = UserAboutForm(request.POST, instance=addProfile)
if form.is_valid():
    addProfile = form.save(commit=False)
    addProfile.user = request.user
    addProfile.save()
...
Если конечно я правильно понял, т.к. названия offset, mainProfile и addProfile запутывают.
И похоже, request.user и есть mainProfile если
request.user.username == offset[0]

Кстати, для профайлов есть стандартные решения
https://docs.djangoproject.com/en/1.4/topics/auth/#storing-additional-information-about-users
Но в 1.5 изменится
https://docs.djangoproject.com/en/dev/topics/auth/#auth-custom-user
SorrowFuck
reclosedev
Так если он существует, значит надо сначала его найти
Да, действительно, так работает, спасибо.
С профайлом может быть велосипед вышел, но я просто расширил стандартную модель, добавив еще одну и связав ее с помощью ForeignKey. От сюда и такие название AddedProfile и MainProfile, расширенный и основной.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB