英文:
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'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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论