Ignore a base model in a Django ORM query - sql

I have these models:
class Foo(models.Model):
some_field = models.CharField()
class Meta:
pass
class Bar(Foo):
some_other_field = models.CharField()
class Meta:
pass
The example is simplified, in reality both models have a lot of fields.
When I query Bar, the Django ORM creates a query containing an inner join with Foo.
I don't need the information in Foo.
Question: Is there a way to query Bar without an inner join with Foo?
I realize that removing Bar extending Foo and making it a foreign key would be a better way to solve this problem. However, there's a lot of legacy code relying on this so I'd prefer a quick solution until I have the time and guts to refactor legacy parts of the app.
I also realize I can write an SQL query myself, but I'd prefer a solution that uses the ORM.

The way I've done it is to use a new unmanaged model for this instance
class SkinnyBar(models.Model):
some_other_field = models.CharField()
class Meta:
managed = False
db_table = "app_bar"
This will allow you to use the ORM.
If you want to avoid the duplication you could try adding most of your properties and methods to a meta class
class BaseBar(models.Model):
some_other_field = models.CharField()
def some_common_method(self):
return True
class Meta:
abstract = True
class Bar(BaseBar, Foo):
def some_method_that_requires_foo(self):
return self.some_field == 1
class SkinnyBar(BaseBar):
class Meta:
managed = False
db_table = "app_bar"

The proper way of doing this is making the Foo model abstract by adding abstract = True in the Meta. In your case, some_field is in the app_foo table and the join is needed in order to create the Bar object completely. If you don't need some_field, you can always drop to raw SQL. But in order to retrieve it, you must join app_bar and app_foo tables.

Interesting issue you have.
The inner join on it's own shouldn't be that big of a deal so long as your queries are setup appropriately. What is the main reason for trying to limit it, performance I assume? Can you post some code of how you're trying to work on these models?
I'm not positive this would work, but you could always look into using the 'defer' function on your queryset. This function is really only for advanced use-cases, and may not apply here. In essence, defer doesn't try to query the fields you specify. if you defer'some_field', perhaps it won't do the join. The downside is that as soon as you try to access 'some_field' from the object, it will perform a query (iteration will cause n extra queries).

Related

Peewee Meta class inherence

I am struggling with the following:
from my_db_definition import db
from peewee import *
class A(Model):
class Meta:
database=db
table_name = 'random'
class B(A):
pass
when running
print(A._meta.table_name)
print(B._meta.table_name)
random
b
My question is now, why is the table name changed in this case, and can this be prevented? I am completely confused
http://docs.peewee-orm.com/en/latest/peewee/models.html#model-options-and-table-metadata
The docs list which options are inherited and which are not.
Only certain attributes are passed to the subclass via the inner "Meta" class. It's purpose is 1) namespacing, and 2) provide conventions around DRY code.
table name is not inherited because presumably you only want one class-per-table, whereas database is inherited because it makes sense to only declare that once.

OOP - Best way to populate Object

I try to follow OOP and S.O.L.I.D for my code and came across a topic where I'm not sure what's the best way to align it with OOP.
When I have an Object with different properties, what's the ideal way to populate those properties?
Should the Object if possible populate them?
Should separate code assign the values to the properties?
I have the following example (Python), which I created based on how I think is the best way.
The Object has methods that will populate the properties so if you instantiate the Object, in this case an Account with and Id, it should automatically populate the properties since they can be retrieved with the ID using DB and API.
class Account:
def __init__(self, account_id):
self.id = account_id
self.name = None
self.page = Page(self.id)
def populate(self):
self.get_name()
def get_name(self):
''' Code to retrieve Account name from DB with account_id '''
self.name = <NAME>
class Page:
def __init__(self, account_id):
self.id = 0
self.name = None
self.user_count = 0
self.populate()
def populate():
self.get_id()
self.get_name()
self.get_user_count()
def get_id(self):
''' Code to retrieve Page Id from DB with account_id '''
self.id = <Page_ID>
def get_name(self):
''' Code to retrieve Account name from DB with account_id '''
self.name = <NAME>
def get_user_count(self):
''' Code to retrieve user_count from API with page_id '''
self.user_count = <user_count>
So instead of doing something like:
account = Account()
account.id = 1
account.name = function.to.get.account.name()
account.page = Page()
account.page.id = 1
I will have it managed by the class itself.
The problem I could see with this is the dependency on the DB and API classes/methods which go against S.O.L.I.D (D - Dependency Inversion Principle) as I understand.
For me it makes sense to have the class handle this, today I have some similar code that would describe the Object and then populate the Object properties in a separate Setup class, but I feel this is unnecessary.
The articles I found for OOP/S.O.L.I.D did not cover this and I didn't really find any explanation on how to handle this with OOP.
Thanks for your help!
Michael
Your design seems fairly ok. Try having a look # Builder Pattern and Composite pattern. And for your question on violation of D principle.
The problem I could see with this is the dependency on the DB and API classes/methods which go against S.O.L.I.D (D - Dependency Inversion Principle) as I understand.
The dependencies are already abstracted into separate components I guess. It is the responsibility of that component to give the data you needed per the contract. Your implementation should be independent of the what that component internally does. A DAO layer for accessing DB and Data APIs can help you achieve this.
The dependency then your system will have is the DAO component. That can be injected with different ways. There are frameworks available to help you here or you can control the creation of objects and injections when needed with some combinations of factory, builder and singleton patterns. If it is single DB instance or LogFile you may also consider using Singleton to get the component.
Hope it helps!
In looking at SOLID and OOP the key is to analyze what it is your doing and separate out the various elements to make sure that they do not end up mixed together. If they do the code tends to become brittle and difficult to change.
Looking at the Account class several questions need to be answered when considering the SOLID principles. The first is what is the responsibility of the Account class? The Single Responsibility Principle would say there should be one and only one reason for it to change. So does the Account class exist to retrieve the relevant information from the DB or does it exist for some other purpose? If for some other purpose then it has multiple responsibilities and the code should be refactored so that the class has a single responsibility.
With OOP typically when retrieving data from a DB a repository class is used to retrieve information from the DB for an object. So in this case the code that is used to retrieve information from the DB would be extracted out form the Account class and put in this repository class: AccountRepository.
Dependency Inversion means that the Account class should not depend explicitly on the AccountRepository class, instead the Account class should depend on the abstraction. The abstraction would be an interface or abstract class with no implementation. In this case we could use an interface called IAccountRepository. Now the Account class could use either an IoC container or a factory class to get the repository instance while only having knowledge of IAccountRepository

Laravel relationship : hasMany of different classes

Consider the following scenario in Laravel 4.1
there is a Set model that may have many items (sorted by precedence, but this can be put aside for now)
each of these items can be of a different "kind" (think of a bag (the Set) that contains keys,wallet,cigs...)
Ideally I would like to achieve the following:
have a simplified, eager-loadable relationship between a Set and its items (explained better below)
keep the item models DRY (ideally each item extends an abstract class with basic boilerplate code)
To better illustrate what I have in mind:
class Set extends Eloquent {
// ...
public function items() {
// provides a "transparent" method to access ALL of its items ... no matter what class
}
}
and
class SubItemOne extends Item { // ... }
class SubItemTwo extends Item { // ... }
abstract class Item extends Eloquent {
public function set() {
return $this->belongsTo('Set');
}
}
because at its core each sub-class shares a lot in common with the others (think of: they can all be moved around in the set, or they can be attached an image etc. ... all of which could be defined within the abstract Item class).
Essentially, I want to be able to access all of the items belonging to my Set in situations like
Set::with('items')->find(1);
but I'm really unsure about what kind of relationship to use for the 'inverse'.
Things I've considered so far:
take out the subclassed models and just keep one Item model with a "item_kind" flag to identify its type. Have each item define a relationship to another class based on this flag... (already sounds butt-ugly to me)
polymorphic relations (including the new N-2-N introduced in L 4.1) although they don't really seem to be thought for this specific scenario: especially N2N still doesn't solve the problem of accessing ALL the items via one simple relation
ditch the eager-loadable relation and write a custom "get_items()" method that would access the individual relationships (as in ->subitemones(), ->subitemtwos() etc ) but this seems like a rather dumb way to solve this problem (i really would like to be able to access the relationship within the query builder)
I'm kinda stuck here but I can't believe I'm the only one facing this situation... I'm really hoping for a "best practice" kind of suggestion here!
You could consinder maping your class hierarcy to DB hierarcy. There are many ways to represent inheritance in your DB schema.
Considering your scenario you can have the following tables:
Set: This entity maps your parent class and stores all common information of a Set Item (eg Position etc)
SubItemOne: Extends the "set" entity, and stores only the additional information specific to this type.
SubitemTwo... etc
SubItemXXX have a 1:1 relationship with the Set entity. All you have to do is a simple JOIN to merge SubItemXXX and Set
You can read more at: How can you represent inheritance in a database?

OOP: class inheritance to add just one property vs constructor argument

I'm new to OOP and I'm in the following situation: I have something like a report "Engine" that is used for several reports, the only thing needed is the path of a config file.
I'll code in Python, but this is an agnostic question.So, I have the following two approaches
A) class ReportEngine is an abstract class that has everything needed BUT the path for the config file. This way you just have to instantiate the ReportX class
class ReportEngine(object):
...
class Report1(ReportEngine):
_config_path = '...'
class Report2(ReportEngine):
_config_path = '...'
report_1 = Report1()
B) class ReportEngine can be instantiated passing the config file path
class ReportEngine(object):
def __init__(self, config_path):
self._config_path = config_path
...
report_1 = ReportEngine(config_path="/files/...")
Which approach is the right one? In case it matters, the report object would be inserted in another class, using composition.
IMHO the A) approach is better if you need to implement report engines that are different from each other. If your reports are populated using different logic, follow this approach.
But if the only difference among your report engines is the _config_path i think that B) approach is the right one for you. Obviosly, this way you'll have a shared logic to build every report, regardless the report type.
Generally spoken, put everything which every Report has, in the superclass. Put specific things in the subclasses.
So in your case, put the _config_path in the superclass ReportEngine like in B) (since every Report has a _config_path), but instanciate specific Reports like in A), whereas every Report can set its own path.
I don't know Python, but did a quick search for the proper syntax for Python 3.0+, I hope it makes sense:
class ReportEngine(object):
def __init__(self, config_path):
self._config_path = config_path
def printPath(self):
print self._config_path
...
class Report1(ReportEngine):
def __init__(self):
super().__init__('/files/report1/...')
Then a
reportObj = Report1()
reportObj.printPath()
should print
'/files/report1/...'
Basically the main difference is that approach A is more flexible than B(not mutual change in one report does not influence other reports), while B is simpler and clearer (shows exactly where the difference is) but a change affecting one report type would require more work. If you are pretty sure the reports won't change in time - go with B, if you feel like the differences will not be common in the future - go with A.

How do I get all instances that inherited from the same parent class in django

I have two models than inherited from the same abstract base class.
I would expect to be able to get all instances from classes that are children of the base class with something like AbstractClass.objects.all()
Of course I could join queries on all children but that's awful and it stops working if I add new children class.
Is this possible with Django ORM ? What would be the elegant solution ?
I have used django's other inheritance methods because I hit the same problem you are running into. I'm not sure if there is an elegant solution. Ultimately, you need several queries done on the DB and for the results to be merged together. I can't picture the ORM supporting that.
Here is my usual hackish approach for this situation:
class NotQuiteAbstractBaseClass(models.Model):
def get_specific_subclass(self):
if self.model1:
return self.model1
elif self.model2:
return self.model2
else:
raise RuntimeError("Unknown subclass")
class Model1(NotQuiteAbstractBaseClass):
def whoami(self):
return "I am a model1"
class Model2(NotQuiteAbstractBaseClass):
def whoami(self):
return "I am a model2"
Then, you can query the entire list like this:
for obj in NotQuiteAbstractBaseClass.objects.iterator():
obj = obj.get_specific_subclass()
print obj.whoami()