【问题标题】:Whats the most Django/pythonic way to create or overwrite a record?创建或覆盖记录的最 Django/pythonic 方式是什么?
【发布时间】:2011-07-31 07:41:41
【问题描述】:

使用 Django 1.2 我正在创建一个葡萄酒评论网站。用户应该只能对每种葡萄酒进行一次评论,但应该能够返回并重新评论一种葡萄酒而不会引发错误。

使用 get_or_create 方法似乎是最合理的解决方案,但我在实现它时遇到了各种问题。搜索我发现这篇文章看起来很有希望: Correct way to use get_or_create?

当然还有关于它的 django 文档: http://docs.djangoproject.com/en/1.2/ref/models/querysets/#get-or-create

但似乎没有回答我的问题。这是我的代码:

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

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,因为我没有匹配所有值 like_dislike 等...然后 django 认为它是唯一的。我尝试删除其他表单参数,但随后它们没有与发布请求一起提交。

建议将不胜感激。

【问题讨论】:

  • 唯一的like_dislike 字段不会有问题吗?那不应该只是一个不唯一的 BooleanField 吗?

标签: django-models django-forms django-views


【解决方案1】:

我在制作基于 CRUD 的应用程序时也遇到了这个问题。我不确定是否有更好的方法,但我最终得到的方法是使用exists() 检查条目是否存在。

您可以在 is_valid() 范围内使用 get_or_create,但是,您需要在显示表单之前检查评论是否存在,以便在评论已经存在的情况下将实例数据加载到表单中。

您的 models.py 可能如下所示:

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 可能如下所示:

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 可以让你这样做:

@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 仅通过访问页面来创建评论,并要求其他信息具有默认值或在模型级别允许为空白。

使用exists(),如果评论存在,您将获得两个数据库命中,但是除非用户提交有效表单,否则您不会创建对象:

@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(),但我认为这可能会更好?

try:
    review = Review.objects.get(user=request.user, wine=wine)
except Review.DoesNotExist:
    review = None

希望有更多经验的人加入。


编辑:

这是来自 Daniel Roseman 的 Blog 的相当老的帖子。我不知道它是否仍然适用,但可能与您的问题有关。

【讨论】:

  • 感谢克里格的回复!我尝试了存在的代码,但得到一个关于实例的错误等于审查:form = WineReviewForm(instance=review), Thoughts?
  • 错误是什么?应该可以,WineReviewForm 是一个 ModelForm for Review?
  • 错误:__init__() 得到了一个意外的关键字参数“实例”
  • 看起来您使用的是表单而不是模型表单。 docs.djangoproject.com/en/dev/topics/forms/modelforms
  • 嗯,以前从未使用过 ModelForm。将不得不检查出来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多