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.

Reply via email to