简体   繁体   中英

Django ManyToMany relationship not persisting

I've encountered a nuisance in a Django application on which I'm working where when a user attempts to create a many-to-many relationship then that relationship does not persist. I can create such relationships via the admin interface, though.

Here's some code which I hope might explain it.

models.py:

class Foo(models.Model):
    ...
    linked_bar = models.ManyToManyField(Bar, blank=True)
    ...

views/foo.py:

def editFoo(request,foo_id):
    fooQuery = Foo.objects.filter(id=foo_id)
    if len(fooQuery) > 0:
       foo = fooQuery.get(id=foo_id)
    else:
        # handle error &c.
    ...
    print str(len(foo.linked_bar.all())) # prints '0'
    linked_bar_id = request.POST.get('linked-bar-id', '')
    barQuery = Bar.objects.filter(id=linked_bar_id)
    if len(barQuery) > 0:
       bar = barQuery.get(id=bar_id)
       foo.linked_bar.add(bar)
       print str(len(foo.linked_bar.all())) # prints '1'
    return redirect("/foo/" + foo_id) # calls showFoo()

def showFoo(request,foo_id):
    fooQuery = Foo.objects.filter(id=foo_id)
    if len(fooQuery) > 0:
       foo = fooQuery.get(id=foo_id)
    ...
    print str(len(foo.linked_bar.all())) # prints '0'

So, the ManyToMany relationship appears to be being created in foo.py during the edit stage, but doesn't persist to where it should be shown to the user. Can anyone suggest what might be happening here, or where I might look for further clues?

It is a bit hard to understand what is attempting to be done because of the generic names, but I will attempt to rewrite your code using a few recommended conventions, and it should hopefully clear up any errors you are having:

def editFoo(request, foo_id):

    try:
        foo_obj = Foo.objects.get(id=foo_id)
    except Foo.DoesNotExist:
        ...  # Handle error here

    ...  # More code here?

    print foo_obj.linked_bar.count()  # Prints current linked_bar count

    linked_bar_id = request.POST.get('linked-bar-id', '')

    try:
        bar_obj = Bar.objects.get(id=linked_bar_id)
    except Bar.DoesNotExist:
        ...  # Handle error here

    if bar_obj:
       foo_obj.linked_bar.add(bar_obj)
       print foo_obj.linked_bar.count()  # Prints current linked_bar count
    return redirect("/foo/" + foo_id)  # Calls showFoo()


def showFoo(request, foo_id):
    foo_obj = Foo.objects.get(id=foo_id)

    ...  # More code here?
    print foo_obj.linked_bar.count()  # Prints current linked_bar count
    return render(request, 'TEMPLATE.html', {'foo': foo_obj})  # Replace 'TEMPLATE.html' with your template name

The solution turned out to be that there was some other code elsewhere in the application which wiped out foo.linked_bar after I'd added to it, which I did not spot initially. So, a trivial matter in the end, but most annoying.

I'll accept the other answer due to the useful coding convention suggestions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM