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 <[email protected]
> <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 [email protected] <javascript:>.
> > To post to this group, send email to [email protected]
> <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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.