Hi Simon, I followed your advice, and changed my code to this:
def edit(id, tags=None): edit_post = Post.query.get(id) if tags is not None and tags != "": for tag in tags.split(','): tag = tag.strip(" ") if tag not in edit_post.tags: add_tags = Tag() add_tags.text = tag edit_post.tags_relationship.append(add_tags) db.session.add(add_tags) db.session.commit() tag_list = set(edit_post.tags) for tag in tag_list: if tag not in tags: edit_post.tags.remove(tag) db.session.commit() else: tag_list = set(edit_post.tags) for tag in tag_list: edit_post.tags.remove(tag) db.session.commit() It works as expected now. About Tag(), I am aware that it is creating new objects and not checking for duplicates in the database. It is not the ideal way I'd like to do things, but I didn't want to complicate things at this point. I'll look at UniqueObject anyway. Thanks a lot for your help :). On Monday, February 23, 2015 at 4:07:16 PM UTC+5:30, Simon King wrote: > > I haven't looked at your code in detail, so this may not be the cause > of the problem, but in general it is a bad idea to modify a collection > while you are iterating over it. ie. this is not generally safe: > > for tag in edit_post.tags: > edit_post.tags.remove(tag) > > Removing the tag from the "tags" list will confuse the "for" loop. > Instead, you should probably iterate over a *copy* of the list: > > tags = list(edit_post.tags) > for tag in tags: > edit_post.tags.remove(tag) > > From a performance point of view, that's not a great pattern - > edit_post.tags.remove(tag) requires searching the list to find the > item to remove. You might be able to get away with simply writing: > > edit_post.tags = [] > > ...depending on how the association proxy is set up. You might also > want to consider using a collection class other than a list here. > Since you want each string to only appear once in the collection, a > set() might be a better choice. > > Finally, unless you are doing something special in your Tag() > constructor, this code is going to create new Tag objects even if a > Tag with the same description is already in the database. If this > isn't what you intended, you might want to investigate one of the > approaches at > https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/UniqueObject. > > Hope that helps, > > Simon > > On Sun, Feb 22, 2015 at 9:27 PM, Asad Dhamani <dhama...@gmail.com > <javascript:>> wrote: > > I looked at my code some more, and found a now obvious mistake. I > changed my > > code to: > > > > def edit(id, tags=None): > > edit_post = Post.query.get(id) > > if tags is not None and tags != "": > > for tag in tags.split(','): > > tag = tag.strip(" ") > > if tag not in edit_post.tags: > > add_tags = Tag() > > add_tags.text = tag > > edit_post.tags_relationship.append(add_tags) > > db.session.add(add_tags) > > db.session.commit() > > for tag in edit_post.tags: > > if tag not in tags: > > edit_post.tags.remove(tag) > > db.session.commit() > > else: > > for tag in edit_post.tags: > > edit_post.tags.remove(tag) > > db.session.commit() > > > > However, now if I remove all the tags from a post, a last one remains, > and I > > have to remove it again to get rid of all the tags. > > > > On Monday, February 23, 2015 at 1:46:07 AM UTC+5:30, Asad Dhamani wrote: > >> > >> I have a many-to-many relationship in my models. This is what they look > >> like: > >> > >> class Post(db.Model): > >> __tablename__ = 'Posts' > >> id = db.Column(db.Integer, primary_key=True) > >> tags_relationship = db.relationship('Tag', secondary=tags, > >> backref=db.backref('posts', lazy='dynamic')) > >> tags = association_proxy('tags_relationship', 'text') > >> full_text = db.Column(db.Text, nullable=True) > >> fulltext_vector = db.Column(TSVectorType('full_text')) > >> > >> > >> > >> class Tag(db.Model): > >> id = db.Column(db.Integer, primary_key=True) > >> text = db.Column(db.String(255)) > >> > >> > >> tags = db.Table('tags', > >> db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')), > > >> db.Column('post', db.Integer, > db.ForeignKey('Posts.id')) > >> ) > >> > >> I need to add the ability to edit tags. I know how to add tags: > >> > >> def edit(id, tags=None): > >> edit_post = Post.query.get(id) > >> if tags is not None and tags != "": > >> for tag in tags.split(','): > >> tag = tag.strip(" ") > >> if tag not in edit_post.tags: > >> add_tags = Tag() > >> add_tags.text = tag > >> edit_post.tags_relationship.append(add_tags) > >> db.session.add(add_tags) > >> db.session.commit() > >> > >> This is what I'm doing for removing tags: > >> > >> for tag in edit_post.tags: > >> if tag not in tags: > >> edit_post.tags.remove(tag) > >> db.session.commit() > >> > >> However, I can not delete the last remaining tag from a post. Once I > add a > >> tag, it seems like there has to be a minimum of 1 tag on that post, as > I can > >> add more, and I can remove all but the last remaining tag. > >> > >> What am I doing wrong? > > > > -- > > You received this message because you are subscribed to the Google > Groups > > "sqlalchemy" group. > > To unsubscribe from this group and stop receiving emails from it, send > an > > email to sqlalchemy+...@googlegroups.com <javascript:>. > > To post to this group, send email to sqlal...@googlegroups.com > <javascript:>. > > Visit this group at http://groups.google.com/group/sqlalchemy. > > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.