D
D
Dmitry2015-04-01 18:06:24
Flask
Dmitry, 2015-04-01 18:06:24

Is it correct to write many-to-many in terms of Flask-SqlAlchemy?

I need to write a many-to-many relationship using Flask-SqlAlchemy.

Please check if I wrote correctly?

About the task itself:
There are users and there are files that they send to my web application. Each user can send many files. Nuance: it may turn out that different users sent the same file, then my application saves only and only one file, but the database must save information about this file for everyone who sent such a file.

What queries will I make to the database?
1. What files does the user have?
2. Which users are using this file?

By the number of operations: item 2 will be more often than item 1

UPD2 :

from .application import db


uploaded_files_users = db.Table('uploaded_files_users',
  db.Column('user_id', db.Integer, db.ForeignKey('users.id')),
  db.Column('uploaded_file_id', db.Integer, db.ForeignKey('uploaded_files.id'))
)


class UploadedFile(db.Model):
  __tablename__ = 'uploaded_files'
  id = db.Column(db.Integer, primary_key=True)
  uuid = db.Column(db.String(36), unique=True, index=True)
  md5 = db.Column(db.String(32), unique=True)
  filename = db.Column(db.String)

  def __init__(self, uuid, md5, filename):
    self.uuid = uuid
    self.md5 = md5
    self.filename = filename

  def __repr__(self):
    return '<UploadedFile %r, %r>' % (self.filename, self.uuid)


class User(db.Model):
  __tablename__ = 'users'
  id = db.Column(db.Integer, primary_key=True)
  username = db.Column(db.String(20), unique=True)
  email = db.Column(db.String(), unique=True)
  uploaded_files = db.relationship('UploadedFile',
    secondary=uploaded_files_users,
    backref=db.backref('users', lazy='dynamic'),
    lazy='dynamic')

  def __init__(self, username, email):
    self.username = username
    self.email = email

  def __repr__(self):
    return '<User %r, %r>' % (self.username, self.email)


All right?

Answer(2015-04-02). Yes, this option is OK.

Tests:
>>> us1 = User('user1', '[email protected]')
>>> uf1 = UploadedFile('232-3232-3232', '998798798723982318', 'calc.exe')
>>> us1.uploaded_files.append(uf1)
>>> db.session.add(us1)
>>> db.session.commit()
>>> User.query.filter_by(username='user1').first().uploaded_files.all()
[<UploadedFile 'calc.exe', '232-3232-3232'>]
>>> UploadedFile.query.filter_by(filename='calc.exe').first().users.all()
[<User 'user1', '[email protected]'>]

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Alexey Ismailov, 2015-04-02
@EvilsInterrupt

You need to remove either the UploadedFile or the User from the relation qualifier if you use backref, since backref just defines the name of the field of this class for the entity being linked, and it will be available there anyway.
In terms of frequency, there is not much difference here, all the same, when specifying a backref, both entities will have access to the records associated with it.

A
Andrew_Lvov, 2015-04-01
@Andrew_Lvov

backref is the name by which you can get the list of resp. objects in the opposite direction.
In the case of the uploaded_files field, backref is the name of the attribute by which the list of users associated with the given uploaded_file will be returned, that is, it is adequate to specify backref='users'.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question