I come from programming in PHP and there I used the Factory pattern to access MySql data, I am trying to use it in Python, and later use the data for Flask. Is this the way it's written correct or are there other better ways to access the data, the idea is to build Jquery datatables in an HTML template.
import pymysql.cursors
from abc import ABC, abstractmethod
class Product:
def __init__(self, idproducte,referencia,nom,preu,iva,ean13,categoria,subcategoria,imatge):
self.idproducte = idproducte
self.referencia = referencia
self.nom = nom
self.preu = preu
self.iva = iva
self.ean13 = ean13
self.categoria = categoria
self.subcategoria = subcategoria
self.imatge = imatge
class productFactory:
@abstractmethod
def productos(connection):
listProducts = list()
with connection:
with connection.cursor() as cursor:
sql = "SELECT id,referencia,nom,preu,iva,ean13,categoria,subcategoria,imatge FROM productes_general.productes"
cursor.execute(sql)
for row in cursor:
pr = Product(row['id'],row['referencia'],row['nom'],row['preu'],row['iva'],row['ean13'],row['categoria'],row['subcategoria'], row['imatge'])
listProducts.append(pr)
return listProducts
connection = pymysql.connect(host='localhost',user='root',password='**',database='productes_general',cursorclass=pymysql.cursors.DictCursor)
cataleg = productFactory.productos(connection)
for ct in cataleg:
print(ct.referencia, "->", ct.nom)
With this, with productFactory.products() I can generate a JSON to pass the data to the template. Is the way to proceed correct?
If you're referring to the Gang of Four Factory Method Pattern , you're definitely not implementing it correctly.
The goal of this design pattern is to be able to use a common interface for object creation without the commitment of our client code having to know the class it is instantiating. The main advantage of this is the decoupling that is achieved between our business logic and the other classes in the system.
Beyond that, you are using the module
abc
incorrectly. First of all, if you want to implement an abstract class, it must inherit fromabc.ABC
. Second, the decorator's goal@abstractmethod
is to, well, create abstract methods. What is the function of an abstract method? Well, to give it a concrete definition in the classes that derive from the abstract class. In your case you are not even specializing the class (which I think you wanted to be abstract) that you have inProductFactory
.We have to remember that in Python abstract classes, abstract methods and explicit interfaces are not necessary. Although it is true that I am a fan of them to force certain good practices, their use in Python is given in a non-native and optional way.
Now, how would this design pattern be most sensibly implemented? The first condition that we would have to have is that we have several models (classes that represent database tables) to which it makes sense to delegate their instantiations to the factories classes. If you don't have this condition, then implementing a design pattern is discouraged because it increases complexity in your code base.
Furthermore, as Design Patterns are very close friends to Object Oriented Programming, it is necessary to maintain the fundamental principles of this programming paradigm. Therefore we should respect the SRP and have a class that is responsible for making the connection to the database, and apart from that, have the classes responsible for shaping our design pattern.
So, considering the above, we could implement something similar to the following:
Reviewing a little what happens here:
Person
so it makes a little more sense to implement the design pattern.namedtuple
to represent them. This in order to avoid having anemic models . Also, you have the bonus of having immutable objects.DBManager
is the class in charge of serving as a bridge between Python and sql commands.Factory
contains the necessary logic to carry out the operation of retrieving the records, and is flexible enough to integrate other similar operations. It includes a methodinstantiate()
that can be overridden by specific factories, in case it is necessary to carry out an additional operation when instantiating a class.PersonFactory
andProductFactory
override the initializer method__init__()
to inject the necessary dependencies. That is, the model and the name of the table.While it is true that the derived factory classes seem unnecessary because they only contain the override of
__init__()
, the purpose of the example is to show the flexibility and very low coupling that is achieved with this.As you can see, all of your code from then on can continue to exist with just a single reference to the classes (namedtuples, so far)
Product
andPerson
. This is, in essence, the goal of implementing the design patterns.Additional
json
. (json.dumps
). . .
Note: Sorry for the length of the answer. It's Saturday, there's still quarantine and I have free time :D