Flask自引用多对多关系,如何防止引用中的重复。

huangapple go评论49阅读模式
英文:

Flask selfreferential many to many relationship, how to prevent duplicates in references

问题

如果你要创建的引用已经存在,请显示一条消息并重定向到您之前访问的页面。
英文:

I am working on a Flask application that manages a database containing notes. These notes can have references to one another. With a selfreferential many-to-many-relation of the table Note that works fine but now I'm trying to prevent that the user may make duplicates of references. I think I should write something like: "If the reference that you are about to make already exists, show a message and redirect to the page you were coming from." I have looked for examples for that but I don't find them and my own efforts don't seem to work.

Here's my model:

from datetime import datetime
from app import db

references = db.Table('references',
    db.Column('refers_id', db.Integer, db.ForeignKey('note.id')),
    db.Column('is_referred_id', db.Integer, db.ForeignKey('note.id')))

class Note(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(140), index=True, unique=True)
    timestampCr = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    content = db.Column(db.Text)
    external_source = db.Column(db.String(300))
    internal_document = db.Column(db.String(300))
    timestampRe = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    timestampUp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
    category = db.Column(db.Boolean, default=False, nullable=False)
    referred = db.relationship(
        'Note', secondary=references,
        primaryjoin=(references.c.refers_id == id),
        secondaryjoin=(references.c.is_referred_id == id),
        backref=db.backref('references', lazy='dynamic'), lazy='dynamic')
  
    def __repr__(self):
        return '[Note] {}' .format(self.title)

And here the view:
`

@app.route("/addref/<id>", methods=['GET', 'POST'])
def addref(id):
    form = RefNoteForm()
    noteref = Note.query.filter_by(id=id).first_or_404()
    if form.validate_on_submit():
       refnote = form.opts.data
       if refnote==noteref: 
           flash ('A note can not refer to itself')
           return redirect(url_for('readnote', id=id))
       noteref.referred.append(refnote)
       db.session.commit()
       return redirect(url_for('readnote', id=id))
    return render_template('addref.html', form=form, id=id)`

I tried to insert between

       if refnote==noteref: 
           flash ('A note can not refer to itself')
           return redirect(url_for('readnote', id=id))

And

   noteref.referred.append(refnote)

Something like:


   if noteref.referred(refnote: 
       flash ('This reference already exists')
       return redirect(url_for('readnote', id=id))
And all kinds of syntactical variations but I can't get it working.
What is the right syntax for what I am trying to do or should I approach the problem in a different way?

</details>


# 答案1
**得分**: 0

以下是已翻译好的部分:

"The phrase I was looking for I found on ChatGPT:

In order to check if a reference already exists, you can use the in operator to check if the refnote is already in the noteref.referred relationship. Here's the modified code snippet:
css

if refnote == noteref: 
    flash('A note can't refer to itself')
    return redirect(url_for('readnote', id=id))
if refnote in noteref.referred:
    flash('This reference already exists')
    return redirect(url_for('readnote', id=id))
noteref.referred.append(refnote)
db.session.commit()
return redirect(url_for('readnote', id=id))

Here, the in operator checks if refnote is already in the noteref.referred relationship. If it is, then the function returns with a flash message indicating that the reference already exists.
If the reference does not already exist, then the code continues to add the reference to the relationship, and commits the changes to the database.
Note that the in operator works for checking if an object is a member of a collection in Python, but it requires that the objects are comparable. In this case, since you are checking if refnote is in the noteref.referred relationship, you need to make sure that the Note class implements the __eq__ method to define when two notes are considered equal. You can add the following method to your Note class to compare notes by their id attribute:
python

def __eq__(self, other):
    return isinstance other, Note and self.id == other.id

With this method implemented, the in operator can now check if refnote is in noteref.referred by comparing their id attributes.

I commented on that: 
I was thinking about your suggestion to add the '__eq__' method to the Note model. When I tried your code for preventing duplicates, it did not seem necessary, it works OK without it. And I thought that that was logical because the id-field in the model is the primary key so if the id's are equal the notes compared must also be equal. Could you comment on that?
To which chatGPT replied:
You make a good point. Since the id field is the primary key in the Note model, it uniquely identifies each note in the database. Therefore, if two Note objects have the same id, they are the same object, and you don't need to compare them any further.
In that case, you don't need to add the __eq__ method to the Note class. 
Thank you for bringing this up, and I apologize for any confusion my previous suggestion may have caused."

<details>
<summary>英文:</summary>

The phrase I was looking for I found on ChatGPT:

In order to check if a reference already exists, you can use the in operator to check if the refnote is already in the noteref.referred relationship. Here&#39;s the modified code snippet:
css

    if refnote == noteref: 
        flash(&#39;A note can&#180;t refer to itself&#39;)
        return redirect(url_for(&#39;readnote&#39;, id=id))
    if refnote in noteref.referred:
        flash(&#39;This reference already exists&#39;)
        return redirect(url_for(&#39;readnote&#39;, id=id))
    noteref.referred.append(refnote)
    db.session.commit()
    return redirect(url_for(&#39;readnote&#39;, id=id))

Here, the in operator checks if refnote is already in the noteref.referred relationship. If it is, then the function returns with a flash message indicating that the reference already exists.
If the reference does not already exist, then the code continues to add the reference to the relationship, and commits the changes to the database.
Note that the in operator works for checking if an object is a member of a collection in Python, but it requires that the objects are comparable. In this case, since you are checking if refnote is in the noteref.referred relationship, you need to make sure that the Note class implements the __eq__ method to define when two notes are considered equal. You can add the following method to your Note class to compare notes by their id attribute:
python

    def __eq__(self, other):
        return isinstance(other, Note) and self.id == other.id

With this method implemented, the in operator can now check if refnote is in noteref.referred by comparing their id attributes.

I commented on that: 
I was thinking about your suggestion to add the &#39;__eq__&#39; method to the Note model. When I tried your code for preventing duplicates, it did not seem necessary, it works OK without it. And I thought that that was logical because the id-field in the model is the primary key so if the id&#39;s are equal the notes compared must also be equal. Could you comment on that?
To which chatGPT replied:
You make a good point. Since the id field is the primary key in the Note model, it uniquely identifies each note in the database. Therefore, if two Note objects have the same id, they are the same object, and you don&#39;t need to compare them any further.
In that case, you don&#39;t need to add the __eq__ method to the Note class. 
Thank you for bringing this up, and I apologize for any confusion my previous suggestion may have caused.

</details>



huangapple
  • 本文由 发表于 2023年4月17日 17:53:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76033844.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定