【问题标题】:Django get_or_create model functionDjango get_or_create 模型函数
【发布时间】:2020-07-28 04:17:30
【问题描述】:

在我最近的一个项目中,我创建了一个网站供用户以多阶段的形式提交他们的信息,在每个表单中我使用 get_or_create 来查看用户之前是否提交过信息,例如,考虑用户教育模型如下,

class UserEducation(models.Model):
    user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE)
    university_name = models.CharField(max_length=100)

在视图中,我有以下代码,

def education_view(request):
    if request.method == "POST":
        uedu, created = UserEducation.objects.get_or_create(user=request.user)
        uedu.university_name = request.POST['university_name']
        uedu.save()
        return HttpResponse("success")

我没有为提交按钮设置上传,问题是一些用户有多个教育对象

有谁知道为什么会发生这种情况以及 get_or_create 有什么问题?

【问题讨论】:

    标签: django django-models django-views


    【解决方案1】:

    你可以使用 update_or_create

    uedu, created = UserEducation.objects.update_or_create(
        user=request.user,uedu.university_name = request.POST['university_name'],
        defaults={'user': 'default_value'},
    )
    

    【讨论】:

    • 惊人的建议,我没有发现任何关于此功能的并发注释或其他内容,我认为这是最好的答案
    • 但是,你的答案应该改变,因为我想根据用户找到教育,然后更新大学
    • 不,这不起作用,因为它根据大学名称搜索并每次创建一个新的
    【解决方案2】:

    我认为原因是,每次您进行下一步时,Django 都会认为您告诉它创建一个新对象,因为每次提交表单时,都会创建一个新模型。

    您应该做的是停止该过程,直到一切都完成。比如:

    class Person(models.Model):
        fn = models.CharField(max_length=40)
    
    class Pet(models.Model):
        owner = models.ForeignKey(Person)
        name = models.CharField(max_length=40)
    
    class PersonForm(forms.ModelForm):
        class Meta:
            model = Person
    
    class PetForm(forms.ModelForm):
        class Meta:
            model = Pet
            exclude = ('owner',)
    
    #views
    def step1(request):
        initial={'fn': request.session.get('fn', None)}
        form = PersonForm(request.POST or None, initial=initial)
        if request.method == 'POST':
            if form.is_valid():
                request.session['fn'] = form.cleaned_data['fn']
                return HttpResponseRedirect(reverse('step2'))
        return render(request, 'step1.html', {'form': form})
    
    def step2(request):
        form = PetForm(request.POST or None)
        if request.method == 'POST':
            if form.is_valid():
                pet = form.save(commit=False)
                person = Person.objects.create(fn=request.session['fn'])
                pet.owner = person
                pet.save()
                return HttpResponseRedirect(reverse('finished'))
        return render(request, 'step2.html', {'form': form})
    

    Reference

    【讨论】:

    • 这似乎是一个合理的答案,但我的方法在第一步(登录/注册)中创建人员,然后在每一步中将有关它的内容存储在数据库中,我根本没有使用会话,在每一步我都只是更新数据库
    • 你可以试试update_or_create吗? Documentation
    • 首先我没有大学名称只是用户,我认为如果我根据文档将大学名称放入 kwargs 中,则会再次创建一个新实例
    【解决方案3】:

    我在文档中找到以下注释,

    警告

    假设数据库强制唯一性,此方法是原子的 的关键字参数(参见 unique 或 unique_together)。如果 关键字参数中使用的字段没有唯一性 约束,对这个方法的并发调用可能会导致多个 插入具有相同参数的行。

    大学对用户外键没有唯一约束,因此并发调用中会保存多个对象。

    【讨论】:

      猜你喜欢
      • 2021-12-08
      • 2015-06-09
      • 1970-01-01
      • 2017-11-05
      • 2018-05-12
      • 1970-01-01
      • 1970-01-01
      • 2018-08-07
      • 2016-11-18
      相关资源
      最近更新 更多