In Symfony, I'm trying to create a document management system and create relationships to a document.
These documents can belong to a user or to an organization (which also has users). So, similar to github, where a repository can belong to a user (github.com/iamtheuser/coolrepo) or to an organization (github.com/myorg/coolrepo), this document can belong to a user or an organization.
Now, in order to do this, I've created an abstract class Documentable. Documentable has the Many-to-One relationship to Document. The Organization class extends Documentable and the User class should also extend Documentable.
But I'm using FOSUserBundle and I'm having difficulty extending the User Model. The original one looks like
abstract class User implements UserInterface, GroupableInterface
{
//...
}
and I want to somehow extend it like so
abstract class User extends Documentable implements UserInterface, GroupableInterface
{
//...
}
The Documentable annotation basically looks like:
/**
* Documentable
*
* #ORM\Table(name="documentable")
* #ORM\Entity(repositoryClass="AppBundle\Repository\DocumentableRepository")
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="discr", type="string")
* #ORM\DiscriminatorMap({"user" = "AppBundle\Entity\User", "organization" = "AppBundle\Entity\Organization"})
*/
I've tried overriding the FOSUserBundle Model several ways, but it doesn't seem to work.
Is this at all possible?
Related
Assuming I have a Django model with a number of relationships that are related, is it possible to nest them through a non-model type for querying purposes? A specific example:
Assume I have a model Organization with relationships that include X_projects, X_accounts, etc which are also Django models.
It is pretty easy to allow queries like:
query fetchOrganization($id: Int!) {
organization(id: $id) {
id,
... other fields ...
X_accounts {
...
}
X_projects {
...
}
}
}
but I would prefer to support queries like:
query fetchOrganization($id: Int!) {
organization(id: $id) {
id,
... other fields ...
X {
accounts {
...
}
projects {
...
}
}
}
}
Given that X doesn't actually make sense to be a Django model / relation on the backend, is there a way to achieve this?
Yes, you can do this by modifying a new resolver for "X" that uses a custom object type that has fields for accounts and projects.
You'll need to create a new composite object type that is a container for accounts and projects, for example (assuming that you've also defined a DjangoObjectType class already for your account and project models)
class XType(graphene.ObjectType):
account = graphene.Field(AccountType)
project = graphene.Field(ProjectType)
Then modify your Organization type definition to add the new field, something like
class OrganizationType(DjangoObjectType):
x = graphene.Field(XType)
class Meta:
model = Organization
# You might want to exclude the x_project and x_account fields
def resolve_x(self, info, **kwargs):
# You'll have to work out how to parse arguments and fetch account and project
return XType(account=account, project=project)
When using a Custom Model Manager the way it is shown in the documentation and examples that I have found, the Custom Managers are placed in the same source file as the Model.
My models.py file has a base class with four sub-classes and the base class has several static methods to provide some common queries. I will need to add quite a few custom queries. I would prefer to put these in a Custom Model Manager that is a Base class for each of the subclasses Model Managers. I would also like to be able to separate the Model Managers into a separate source file called managers.py to make the code less messy.
The problem is that there is a cyclic dependency between the Models and Managers.
Is there a way to set the Manager to the "objects" variable by name instead of the actual Model Manager class? Or perhaps some other way to be able to put the code into the two separate files?
models.py
class MyBaseModelClass(models.Model): (abstract)
list_of_values (Many to Many Field)
class class SubclassA(MyBaseModelClass):
objects = SubclassAManager()
# list_of_values pulled from external system
class class SubclassB(MyBaseModelClass):
objects = SubclassBManager()
# list_of_values manually added by the user in the UI and stored in the DB
class class SubclassC(MyBaseModelClass):
objects = SubclassCManager()
# list_of_values derived from subclass fields and not stored in the DB
class class SubclassD(MyBaseModelClass):
objects = SubclassDManager()
# list_of_values derived from subclass fields and not stored in the DB
managers.py
class MyCustomBaseManager(models.Manager):
# Does custom queries that do calculations and other data manipulations that are common to all of the
# Subclasses. Note that MyBaseModelClass can't have a Manager because it is Abstract.
class SubclassAManager(MyCustomBaseManager):
class SubclassBManager(MyCustomBaseManager):
class SubclassCManager(MyCustomBaseManager):
class SubclassDManager(MyCustomBaseManager):
I have a model set up that is
class BasePage(Page):
class Meta:
abstract = True
class PageTypeA(BasePage):
...
class PageTypeB(BasePage):
...
class PageTypeC(BasePage):
...
etc..
How do I create a query to list all of the pages that inherit from BasePage?
If i am understand you properly you need a parent model that have some generic information and other child models need some extra additional information. You can try third-party django-polymorphic link for that. One of important feature that it support Django-Rest-Framework serializer too.
So I have a base abstract model class
class AbstractBase(models.Model):
category = models.CharField()
// Some fields
class Meta:
abstract = True
Now many classes inherit from this Base. Each category has its own fields
class Category1(AbstractBase):
//some code
class Category2(AbstractBase):
//some code
.
.
.
class CategoryN(AbstractBase):
//some code
Now I do not wish to create separate inlines etc for each of these models.
This is because in the admin only one of these models need to be displayed depending on which category it is.
class CategoryAdminInLine(nested.NestedTabularInline):
model = Category
fields = //some common fields
Is there any easy way to do it?
Try the package django-polymorphic https://github.com/django-polymorphic/django-polymorphic
It adds transparent admin and QuerySet integration for inherited models.
Another solution is to simply remove the abstract=True from the base class.
However, I'm afraid this may not be the right way to do it as it may be copying and duplicating the tables and stuff but works great if the tables won't get too big!..
According to how it's done here.. https://godjango.com/blog/django-abstract-base-class-multi-table-inheritance/
I have a situation where I need to subclass a custom user model for a django 1.5 project (related question/background here: Subclassing AbstractUser in Django for two types of users )
I need an abstract user class SchoolPerson and a number of subclasses (Student, Teacher, etc) based on this. I think I've resolved that I need to have the user model in a separate DB table to the subclasses as other apps rely on AUTH_USER_MODEL, of which there can only be one.
So the way I see it, I have to options to do this: add one-to-one to the standard user model in my abstract SchoolPerson class:
class SchoolPerson(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
...
class Meta:
abstract = True
class Student(SchoolPerson):
year_level = models.CharField(max_length=3)
...
class Teacher(SchoolPerson):
govt_id = models.CharField(max_length=10)
...
Or I can make my SchoolPerson model inherit AbstractUser, but keep this class non-abstract:
class SchoolPerson(AbstractUser):
...
#no Meta abstract here
class Student(SchoolPerson):
year_level = models.CharField(max_length=3)
...
class Teacher(SchoolPerson):
govt_id = models.CharField(max_length=10)
...
Are there any advantages to one of these over the other?
I haven't tested this but what I expect is for your first suggestion to create two db tables:
one for Student and one for Teacher each with a foreign key to the AUTH_USER_MODEL.
For the second one I expect Django to create three db tables:
One for the SchoolPerson(which will be exact as the default Users table with the additional fields) and two for Student and Teacher with foreign keys to SchoolPerson.
So I think the answer depends on your requirements.