最多Django / pythonic的创建或覆盖记录的方式是什么? [英] Whats the most Django/pythonic way to create or overwrite a record?
问题描述
使用Django 1.2我正在做一个葡萄酒评论网站。用户应该只能检查一次葡萄酒,但应该可以回去并重新检查葡萄酒,而不会出现错误。
Working with Django 1.2 I am making a wine review site. A user should only be able to review each wine once, but should be able to go back and re-review a wine without raising an error.
使用get_or_create方法似乎最合理的解决方案,但我一直在执行它的各种问题。搜索我发现这篇文章看起来很有希望:
正确的方法来使用get_or_create ?
Using the get_or_create method seems the most rational solution but I have been running into various problems implementing it. Searching I found this article which looked promising: Correct way to use get_or_create?
当然还有django文档:
http://docs.djangoproject.com/en/1.2/ref/models/querysets/#get-or-create
and of course the django documentation on it: http://docs.djangoproject.com/en/1.2/ref/models/querysets/#get-or-create
但似乎没有回答我的问题。这是我的代码:
But didn't seem to answer my question. Here is my code:
Views.py
@login_required
def wine_review_page(request, wine_id):
wine = get_object_or_404(Wine, pk=wine_id)
if request.method == 'POST':
form = WineReviewForm(request.POST)
if form.is_valid():
review, created = Review.objects.get_or_create(
user = request.user,
wine = wine,
like_dislike = form.cleaned_data['like_dislike'],
...
)
variables = RequestContext(request, {
'wine': wine
})
review.save()
return HttpResponseRedirect(
'/detail/%s/' % wine_id
)
else:
form = WineReviewForm()
variables = RequestContext(request, {
'form': form,
'wine': wine
})
return render_to_response('wine_review_page.html', variables)
Models.py p>
Models.py
class Review(models.Model):
wine = models.ForeignKey(Wine, unique=True)
user = models.ForeignKey(User, unique=True)
like_dislike = models.CharField(max_length=7, unique=True)
...
如果我明白如何正确使用get_or_create ,因为我不匹配所有的值,如__dislike等等,那么django会觉得它是独一无二的。我尝试删除其他表单参数,但是后来没有提交发布请求。
If I understand how to use get_or_create correctly, since I am not matching on all the values like_dislike, etc... then django perceives it to be unique. I tried removing the other form parameters, but then they are not submitted with the post request.
建议将不胜感激。
推荐答案
在制作基于CRUD的应用程序时,我也遇到了这个问题。我不知道是否有更好的方法,但是我最终的做法是使用 exists()
来检查是否存在条目。
I came across this too when making a CRUD based app. I'm not sure if there's a better way but the way I ended up getting doing was using a exists()
to check if an entry ... exists.
您可以在is_valid()范围内使用get_or_create,但是在显示表单之前,您需要检查是否存在审阅,以便在审核已经存在的情况下将实例数据加载到表单中。
You can use get_or_create within the is_valid() scope, however, you need to check if the review exists before displaying your form in order to load instance data into the form in the case that the review already exists.
您的models.py可能如下所示:
Your models.py might look like this:
from django.db import models
from django.contrib.auth.models import User
class Wine(models.Model):
name = models.CharField()
class Review(models.Model):
wine = models.ForeignKey(Wine)
user = models.ForeignKey(User)
like = models.BooleanField(null=True, blank=True) # if null, unrated
您的forms.py可能如下所示:
Your forms.py might look like this:
from django import forms
class WineReviewForm(forms.ModelForm):
class Meta:
model = Review
fields = ['like',] # excludes the user and wine field from the form
使用get_or_create可以让您如此使用:
Using get_or_create will let you do this if used like so:
@login_required
def wine_review_page(request, wine_id):
wine = get_object_or_404(Wine, pk=wine_id)
review, created = Review.objects.get_or_create(user=request.user, wine=wine)
if request.method == 'POST':
form = WineReviewForm(request.POST, instance=review)
if form.is_valid():
form.save()
return HttpResponseRedirect('/detail/%s/' % wine_id )
else:
form = WineReviewForm(instance=review)
variables = RequestContext(request, {'form': form, 'wine': wine })
return render_to_response('wine_review_page.html', variables)
只需访问该页面即可创建评论,并要求其他信息默认或允许在模型级别为空。
Doing creates a review just by visiting the page and requires that the other information either have a default or are allowed to be blank at the model level.
使用 exists()
,如果审核存在,您将得到两个db命中,但是除非用户提交有效的表单,否则您不创建对象:
With exists()
, you get two db hits if the review exists, however you don't create an object unless the user submits a valid form:
@login_required
def wine_review_page(request, wine_id):
wine = get_object_or_404(Wine, pk=wine_id)
review = None
if Review.objects.filter(user=request.user, wine=wine).exists():
review = Review.objects.get(user=request.user, wine=wine)
if request.method == 'POST':
form = WineReviewForm(request.POST, instance=review)
if form.is_valid():
form.save()
return HttpResponseRedirect('/detail/%s/' % wine_id )
else:
form = WineReviewForm(instance=review)
variables = RequestContext(request, {'form': form, 'wine': wine })
return render_to_response('wine_review_page.html', variables)
我使用 exists()
我认为这可能会更好?
I used exists()
but I think that this might be better?
try:
review = Review.objects.get(user=request.user, wine=wine)
except Review.DoesNotExist:
review = None
充满希望有更多经验的人将会进入。
Hopefully someone with more experience will chime in.
编辑:
以下是Daniel Roseman的 键博客
强> 。我不知道它是否仍然适用,但可能与您的问题有关。
Here is a fairly old post from Daniel Roseman's Blog
. I don't know if it is still applicable, but might be relevant to your question.
这篇关于最多Django / pythonic的创建或覆盖记录的方式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!