【问题标题】:How to save a random item returned from QuerySet. Django, Python如何保存从 QuerySet 返回的随机项。姜戈,蟒蛇
【发布时间】:2019-04-07 16:37:45
【问题描述】:

我正在尝试从 QuerySet 中保存返回的项目,以便稍后它将在下一个模板中显示所有已保存的项目。但是不知道怎么办?

1.) 如何正确地将“镜头”发送到数据库??

我的models.py

class City(models.Model):
    name = models.CharField(max_length=100)

class User(models.Model):
    name = models.CharField(max_length=100)
    city = models.ForeignKey(City, on_delete=models.CASCADE)

class UserDecision(models.Model):
    decision = models.BooleanField(default=False)
    relation = models.ManyToManyField(User)

我的意见.py

from django.shortcuts import render
from .models import User
from .forms import UserDecisionForm

def random_views(request):
    shot = User.objects.all().order_by('?')[:1]

    #Begining form here
    if request.method == "POST":
        form = UserDecisionForm(request.POST)
        if form.is_valid():
            decision = form.save(commit=False)
            decision.relation = shot #<--- how to pass this element to the database automatically. According to the result returned from the QuerySet query.
            decision.save()
    else:
        form = UserDecisionForm()

    # other elements
    context = {'shot': shot, 'form':form }
    return render(request, 'index.html', context)

forms.py

from django import forms

from .models import UserDecision

class UserDecisionForm(forms.ModelForm):
    class Meta:
        model = UserDecision
        fields = ('decision',)

【问题讨论】:

  • shot 是一个数组,你可能错过了。你想通过分配给pk 来实现什么?您是否尝试复制随机用户并将其显示在模板中?
  • pk - 是我尝试进行的尝试的残余,按照文档行事。是的,我正在尝试复制一个随机用户,以便我可以显示它。我知道如何从表单中保存数据以及如何创建它。但是如何从 QuerySet 中保存结果,例如 (all() 或 order_by('?'))。我必须创建一个单独的模型吗?如果是这样,如何将查询集结果传递给模型?我正在学习 django,但还没有找到合适的例子。
  • 你的问题我不清楚。您是在问如何将某些内容分配给decision.relation?如果是这样,请查看docs.djangoproject.com/en/2.1/topics/db/examples/many_to_many

标签: python django django-queryset


【解决方案1】:

更新

短版:试试decision.relation = [shot]

长版:
decision.relation 将返回一个related manager instance;一个很像 &lt;model&gt;.objects 返回的管理器,除了它管理与实例 decision 相关的所有记录。
需要注意的是decision.relation实际上是a data descriptor,一个对象的特殊属性(这里:decision)允许在访问(__get__)或更改(__set__)属性时使用一些巧妙的小技巧: 访问属性relation 后,您将通过描述符的__get__ 方法获得上述管理器实例。

在设置属性时(使用decision.relation = some_variable),描述符使用它的__set__ 方法,如下所示:

# django.db.models.fields.related_descriptors.py: 518
def __set__(self, instance, value):
    """
    Set the related objects through the reverse relation.

    With the example above, when setting ``parent.children = children``:

    - ``self`` is the descriptor managing the ``children`` attribute
    - ``instance`` is the ``parent`` instance
    - ``value`` is the ``children`` sequence on the right of the equal sign
    """
    ...
    manager = self.__get__(instance)
    manager.set(value)

因此,当您编写 decision.relation = shot 从而调用上述 __set__ 方法时,描述符将为该关系创建正确的管理器,然后在其上调用 set(shot)
最后,set() 期待模型实例的可迭代,但您只给了它一个单独的模型实例。


我不太确定这是否真的能回答你的问题,但我不想在开篇文章中添加长评论,而且在解释代码时答案会更加清晰。

values() 将返回查询中对象的字典表示形式的查询集。您可以使用这些字典制作这些对象的相同副本。

user_data = User.objects.order_by('?').values()[:1][0]
user_data[User._meta.pk.name] = None # We cannot use an existing pk for the copy
copied_user = User.objects.create(**user_data)
return render(request, 'index.html', {'shot':copied_user})

不清楚您在下一个视图中对这些副本做了什么。如果您只想显示复制的对象以避免任何人实际更改原始对象,然后在您离开视图后再次丢弃副本(以免最终得到一个充满副本的表格),那么最好更改模板/使用简单的表单首先只显示原始数据。

【讨论】:

  • 谢谢您的回答,我的意思是正确地将镜头传输到数据库。我已经澄清了我上面的问题。
猜你喜欢
  • 1970-01-01
  • 2016-01-19
  • 1970-01-01
  • 2018-03-02
  • 1970-01-01
  • 2016-04-29
  • 1970-01-01
  • 2016-06-09
  • 1970-01-01
相关资源
最近更新 更多