【问题标题】:how to save Many to Many relationship in django如何在 Django 中保存多对多关系
【发布时间】:2014-11-21 16:17:52
【问题描述】:

How to create an object for a Django model with a many to many field?

从上面的问题我知道我们只能在以后保存多对多字段。

models.py

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

class Foo(models.Model):
   file = models.FileField(upload_to='')
   store = models.ManyToManyField(Store, null=True, blank=True)

views.py

new_track.file = request.FILES['file']
new_track.save()

文件上传工作正常,然后我修改我的代码以添加商店,然后我就在这里......

现在我确定 db return id 在这里。然后我尝试了下面的代码,但这只是给了我错误

    x = new_track.id
    new = Foo.objects.filter(id=x)
    new.store.id = request.POST['store']
    new.save()

好的,这里的错误是'QuerySet' object has no attribute 'store'

我还尝试了add,现在也可以使用。 所以问题是如何保存()

【问题讨论】:

  • 尝试将您的代码更改为 new.store = request.POST['store']
  • .filter 返回一个查询集。要获取对象,您需要 .get().filter()[0]
  • @karthikr 我很确定在保存时会获得 id 值。我的方法是保存多对多关系的正确方法吗?如果我按照自己的方式行事,我会得到Foo' object has no attribute 'name',我也试过你的。并且 doniyor 告诉不同的方法返回存储对象,然后使用 add 方法保存。什么是正确的方法?请帮忙
  • @cdvv7788 我改变了我的问题,请看一下

标签: python django


【解决方案1】:

截至 2020 年,这是我将 ManyToMany 字段保存到给定对象的方法。

简答

class HostingRequestView(View):
    def post(self, request, *args, **kwargs):
        form = VideoGameForm(request.POST)
        if form.is_valid():
            obj = form.save(commit=False)
            obj.updated_by = request.user
            obj.save()

            selected_categories = form.cleaned_data.get('category') #returns list of all selected categories e.g. ['Sports','Adventure']
            #Now saving the ManyToManyField, can only work after saving the form
            for title in selected_categories:
                category_obj = Category.objects.get(title=title) #get object by title i.e I declared unique for title under Category model
                obj.category.add(category_obj) #now add each category object to the saved form object
            return redirect('confirmation', id=obj.pk)

完整答案

models.py

class Category(models.Model):
    title = models.CharField(max_length=100, null=True, unique=True)

class VideoGame(models.Model):
    game_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=50, blank=False, null=False)
    updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=False, on_delete=models.CASCADE)
    category = models.ManyToManyField(Category) #ManyToMany Category field
    date_added = models.DateTimeField(auto_now_add=True, verbose_name="date added")

forms.py 模型表单

class VideoGameForm(forms.ModelForm):
    CATEGORIES = (
        ('Detective', 'Detective'),
        ('Sports', 'Sports'),
        ('Action', 'Action'),
        ('Adventure', 'Adventure'),
    )

    category = forms.MultipleChoiceField(choices=CATEGORIES, widget=forms.SelectMultiple())

    class Meta:
        model = VideoGame
        fields = ['name', 'category', 'date_added']

post 上的views.py

class HostingRequestView(View):
    def post(self, request, *args, **kwargs):
        form = VideoGameForm(request.POST)
        if form.is_valid():
            obj = form.save(commit=False)
            obj.updated_by = request.user
            obj.save()

            selected_categories = form.cleaned_data.get('category') #returns list of all selected categories e.g. ['Sports','Adventure']
            #Now saving the ManyToManyField, can only work after saving the form
            for title in selected_categories:
                category_obj = Category.objects.get(title=title) #get object by title i.e I declared unique for title under Category model
                obj.category.add(category_obj) #now add each category object to the saved form object
            return redirect('confirmation', id=obj.pk)

重定向的 URL 路径

urlpatterns = [
    path('confirmation/<int:id>/', Confirmation.as_view(), name='confirmation'),
]

我希望这会有所帮助。问候

【讨论】:

    【解决方案2】:

    保存具有多对多关系的对象的正确方法是:

    ...
    new_track.file = request.FILES['file']
    new_track.save()
    
    new_store = Store.objects.get(id=int(request.POST['store']))
    new_track.store.add(new_store)
    

    【讨论】:

    • 我试过你的,得到了​​像nvalid literal for int() with base 10: 'on'这样的错误
    • @em___life 试试这个new_store = Store.objects.get(id=int(request.POST['store']))
    • ok.. 现在没有错误。我猜对象正在保存。然后我访问了mysql工作台,表'dsp_foo_store`有三个字段(id,foo_id,store_id)。如果 foo_id 为 9,则对应的 store_id 为 3,但我选择多个表示超过三个复选框,但它只返回一个对象。怎么会?
    • @em___life(如果它解决了您的第一个问题,请不要忘记投票并检查作为答案)。我不明白你所说的"i select multiple means more than three checkbox" 是什么意思。你能再描述一下这个案例吗
    • 我怀疑objects.get 只返回一个对象,但request.POST['store'] 返回多个值 bcse 每个复选框呈现存储ids.....
    【解决方案3】:

    为什么这么混乱..你在那里得到了 id,像这样打电话给商店

    new_track.save()
    new_track.store.add(request.POST['store'])
    

    【讨论】:

    • 感谢现在保存选项,但我有多项选择条目然后mysql给我这个错误(1062, "Duplicate entry '4-5' for key 'tracks_id'")
    • request.POST['store'] 只是一个字符串,您不能将.add() 与许多相关对象一样
    【解决方案4】:

    也许:

    1. 将 Foo 更改为 Tracks
    2. Tracks.objects.filter(id=x) 到 Tracks.objects.get(id=x)

    告诉我进展如何

    【讨论】:

    • 我改变了我的问题,请看一下
    • @em___life 检查我的第二个建议。过滤器返回结果列表(您可以查看类似的查询集)并且您需要一个对象。通过 get 更改过滤器或尝试 filter()[0]
    【解决方案5】:
    new.stores.all()
    

    返回链接到该对象的所有商店。

    【讨论】:

    • 我认为这与问题无关。
    • 他收到的错误与商店有关,应作为stores.filter或任何模型对象进行查询。
    猜你喜欢
    • 2015-07-02
    • 2017-12-16
    • 2018-07-05
    • 1970-01-01
    • 2010-10-05
    • 2021-08-09
    • 2021-10-18
    • 1970-01-01
    • 2011-01-21
    相关资源
    最近更新 更多