Basic Entity Management System - python

How can I design an Entity Management system in Django which can be able to adapt to any kind of entity with minimal code changes (e.g. a product in a catalog, patient information in healthcare etc.).
Adding, removing, modifying the attributes of an entity should be simple
It should allow for nested attributes (sub-entities) e.g Patient -> Consulting doctor
Each attribute or sub-entity in the entity can have a set of business rules

Sounds like you have the need for a rather standard django app. I would follow their tutorial in order to grasp django and get you started.
In regards to your questions, I've quoted parts and given links to how you can achieve this:
"Adding" (CreateView), "removing" (DeleteView), "modifying the attributes"(UpdateView) of an entity should be
simple
It should allow for "nested attributes" (models.ForeignKey) (sub-entities) e.g Patient ->
Consulting doctor
Each attribute or sub-entity in the entity can have a set of
business rules. (create a 'controller' and call it in overiden methods, this SO answer answers where to put it perfectly)
Your requirements pretty much define what django does.

Related

Django model design - How to handle multiple optional attributes?

I'm a novice in Django (but an experienced developer), and I'm starting to build my first Django project.
The project is really simple: a website where people can join events. An administrator sets an sports event, chooses the date, the kind of event (running, tennis match, bycicle ride), etc, and users can join it.
My problem is that the events can have very different data inside, depending on his category. For example, if it's a two-people team tennis match, an users should enter his name and his teammate name, their team name, etc. If the event is a bycicle ride, he can choose if he wants the difficult or the easy route, etc.
I know I can create a big model with all the attributes for every kind of event, but this is a really ugly design... There should be a common table for all registrations, with a link to the event and the basic and common data (name, address, phone, email, etc), but I don't know how to handle the specific data for each sport/event category... Any idea about how to organize this in Django models? Maybe adding a simple (key, inscription_id, type, value) table? And then, how can I render the form?
I believe what you suggested is called Entity-attribute-value model
http://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model
I think there could be a good argument for keeping all data belonging to your events defined inside of a model instead of through a related generic EAV table.
To do this you could use one of django's polymorphic libraries. I have used django-model-utils' InheritanceManager in production. There are quite a few libraries including django-polymorphic.
Taking an inhertance based approach you might define a single Event model or Sport model. A sport might have a name, league, etc. All Events might have a start date and end date and sport.
Using this approach you can defined foriegn keys from your registrations to the base Event class and use djangos built in ORM to select all events or registrations of certain types, without having the additional application logic/object inspection/ property inspection of taking an EAV approach!
You can store all additional data in Text field using JSON object or other serializer.
Take look at django-jsonfield

Python / Django multi-tenancy solution

I could use some help creating a plan of attack for a project I'm working on.
Imagine that the site is for a group that oversees regional sales offices, distributed around the world. The purpose of this project is to let superusers spin up a new sub-site specific to each and every office, at a fast pace -- sites are added on a frequent basis. The office sub-sites should be wholly contained with "admin" users specific to that sub-site and should be user-friendly CMS. A superuser should be able to step in and manage all of these office sub-sites.
In addition to the self-contained office sub-site instance, there is also a need for each sub-site to manage contacts, leads, etc and store this in one central area for the superusers.
I've done a few sites using Django, but never anything multi-tenant. I'd like suggestions for technologies to use or tutorials/documentation that might be helpful.
Requirements:
Each sub-site uses the same source (templates, JS, available features, etc), but can be modified to reflect custom content within the templates.
Assigned subdomains (with an option of using a fully qualified domain) per sub-site, configured within the project, not in a hardcoded settings file.
Sub-site specific user access controls, in addition to superusers who can access all sub-sites.
The ability to provide an "independent" CMS for each sub-site. i.e., A sub-site admin only sees their content. My preference for this project would be django-cms, but I'm open to suggestions.
Support for apps that pool the data from all the sub-sites, but limit sub-site "admins" to only viewing their records into that app.
Considering the above, what approach would you recommend? I am open to reconsidering technologies, but I would like to stick with Python.
There is a great app called django-tenant-schemas that uses PostgreSQL schemas mechanism to create multi-tenancy.
What you get is specyfing SHARED_APPS that contain objects shared across all the schemas (sub-sites), and TENANT_APPS that contain objects specific for a sub-site, i.e. users, records etc. The schemas are completely isolated from each other.
Each PostgreSQL schema is tied to a domain url, so that middleware checks the HOST part of the request and sets the db connection's schema to appriopriate one.
In addition, it allows you to define a PUBLIC_SCHEMA_URLCONF which allows you to specify urlconf file for public schema - the meta site that is not tied to any sub-site.
Sorry for quick and dirty answer, i just share what i've done to achieve multi tenancy:
django-tenancy I like the author's approach of using "dynamic model"
django-dynamicsite This is where dynamic SITE_ID based on domain will be linked to a tenant
Both libraries above, when combined, is able to serve a django instance which is multi-tenant, and flexible. What i mean flexible here is: you can define any model whether is it "tenant" or "global". So, you can have a site with global user but per tenant product catalogue, or per tenant + product. From many django app i've tried, this is the most flexible way to achieve multi tenancy
The Django based CMS Mezzanine also has multi-tenancy support.
It has most of the features you requested except the sub-site user controls I think. The admin page can be separated by site for admin users, but the normal users not.
However, if you dont need a CMS this might be an overkill for your use-case, But I wanted to mention it here for completeness.
I have been trying to use django-tenants for a while along with Wagtail but this combination didn't work very well, or let me say, despite of a lot of try I was not able to get wagtail admin-page working correctly. I think will try to switch to django-tenant-schemas which I more widely used .
NOTE: django-tenant-schemas is not maintained now.

Implementing workflows in Django Admin - Django

I have a nice admin panel setup so users can manage the data within the site.
Problem is that I need to implement a workflow, so saved models can be approved from and to various stages, to then be finally published.
As the model in question is just one, I thougth of adding a boolean 'approved_for_publishing' field and a 'approved_by' manytomany field.
The obstancle is integrating this within the admin panel.
If someone has a few opinions on the topic that would be really awesome. =)
Some time early I completed similar functionality. Here is what you need to do:
Create an approval status model, and have different variants of approval, i.e each model object represents different approval stage.Also you must have a StatusHistory model which reflects what current status does your article(for example) has.
class Article(models.Model)
title=models.CharField(max_length=32)
body=models.TextField()
class ApprovalStatus(models.Model):
name=models.CharField(max_length=32)
alias=models.CharField(max_length=32,pk=True)
class StatusHistory(models.Model):
status=models.ForeignKey(ApprovalStatus)
article=models.ForeignKey(Article)
current=models.BooleanField(default=True)
So when in your admin you change the status of the article, a new StatusHistory object is created and old object is given current=False variable.
This approach seems a bit bulky, but when you implement it, all you need easily falls into ORM: status history is just a list of all objects, changes to workflow involve only creating new approval status and changing your hardcoded status flow routines
django-werewolf is exactly what you're looking for (https://pypi.python.org/pypi/django-werewolf).
Check the example app here (https://bitbucket.org/barseghyanartur/django-werewolf/src).
For any questions and support, contact me.

Fully customized login system in Django?

I am currently writing an application which I plan to sell as SaaS. Without giving away "secrets," I can say that it is basically a "document editing system" in which many users will be submitting documents.
The basic heirarchy is this:
Institution
Individual
Document
Sub-document
So each Individual should be able to BROWSE all documents that were submitted by anybody in their institution, but should only be able to EDIT documents that they created.
No individual should even be aware of the existence of another Institution--that should all be completely hidden.
I have written a Django/Python class that would facilitate this, but every document regarding authentication that I have read requires that I use the User object. Is this just a limitation of Django, or is there a way to do this?
If there is a way, how can I get my own "Individual" class details attached to the "request" objects so I can validate the things I should be showing the users?
What you're looking for is authorization, not authentication. Django's built-in authorization system is fairly crude, as you've discovered. You'll need something like django-authority if you want a more complete solution.
The auth module is typically used to cover authentication cases.
Gives you groups (Institutions), Users (Individuals) and permissions.
Using these features you can perform checking if a user is a member of a group or owns a doc before allowing them to see or edit the doc.
http://docs.djangoproject.com/en/dev/topics/auth/
If you need to go beyond the typical use case, supporting LDAP for example, then you can look at writing your own authentication backend.
http://docs.djangoproject.com/en/dev/topics/auth/#other-authentication-sources
In general, if you need to attach more information to the builtin User model, you would create new model which subclasses models.Model (not User), and identify it in settings as AUTH_PROFILE_MODULE. You can get the appropriate instance of your model from a user by calling user.get_profile(). (see http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users).
This is generally useful for adding extra fields to User such as address, contact information, etc. While it would be possible to use this for your authentication needs, you'd most likely be better off using the built in groups, or a more comprehensive solution like django-authority as others have mentioned. I've included this answer only because it seems to be what you were asking for (a way to attach a class to User), but not really what you need (authorization).

Eliminating multiple inheritance

I have the following problem and I'm wondering if there's a nice way to model these objects without using multiple inheritance. If it makes any difference, I am using Python.
Students need contact information plus student information. Adults need contact information plus billing information. Students can be adult students, in which case I need contact/student/billing info, or they can be children, in which case I need contact/student/parent info.
Just to be clear on how the system will be used, I need to be able to ask for a list of all adults (and I will get adult students plus parents), or a list of all students (and I will get child students plus adult students).
Also, all of these objects need to have a common base class.
What you have is an example of Role -- it's a common trap to model Role by inheritance, but Roles can change, and changing an object's inheritance structure (even in languages where it's possible, like Python) is not recommended. Children grow and become adults, and some adults will also be parents of children students as well as adult students themselves -- they might then drop either role but need to keep the other (their child changes schools but they don't, or viceversa).
Just have a class Person with mandatory fields and optional ones, and the latter, representing Roles, can change. "Asking for a list" (quite independently of inheritance or otherwise) can be done either by building the list on the fly (walking through all objects to check for each whether it meets requirements) or maintaining lists corresponding to the possible requirements (or a mix of the two strategies for both frequent and ad-hoc queries). A database of some sort is likely to help here (and most DBs work much better without inheritance in the way;-).
As I'm sure someone else will comment soon (if they haven't already), one good OO principle is "Favor composition over inheritance". From your description, it sounds suspiciously like you're breaking the Single Responsibility Principle, and should be breaking down the functionality into separate objects.
It also occurs to me that Python supports duck typing, which begs the question "Why is it so important that all the classes have a common base class?"
Very simple solution: Use composition rather than inheritance. Rather than having Student inherit from Contact and Billing, make Contact a field/attribute of Person and inherit from that. Make Billing a field of Student. Make Parent a self-reference field of Person.
It doesn't sound like you really need multiple inheritance. In fact, you don't ever really need multiple inheritance. It's just a question of whether multiple inheritance simplifies things (which I couldn't see as being the case here).
I would create a Person class that has all the code that the adult and student would share. Then, you can have an Adult class that has all of the things that only the adult needs and a Child class that has the code only the child needs.
This sounds like something that could be done quite nicely and flexibly with a component architecture, like zope.components. Components are in a way a sort of super-flexible composition patterns.
In this case I'd probably end up doing something when you load the data to also set marker interfaces on it depending on some information, like if age >= 18 you set the IAdult interface, etc. You can then get the adult information by doing
adultschema = IAdultSchema(person)
or something like that.
(Edit: Actually I'd probably use
queryAdapters(person, ISchema)
to get all schemas in one go. :)
A component architecture may be overkill, but once you got used to thinking like that, many problems get trivial. :)
Check out Brandons excellent PyCon talk about it: http://www.youtube.com/watch?v=UF77e2TeeQo
And my intro blog post: http://regebro.wordpress.com/2007/11/16/a-python-component-architecture/
I think your requirements are over-simplified, since in a real situation, you might have students with their own accounts to handle billing even if they are minors who need parent contact information. Also, you might have parental contact information be different from billing information in an actual situation. You might also have adult students with someone else to bill. BUT, that aside - looking at your requirements, here is one way:
classes: Person, BillingInfo, StudentInfo.
All people are instances of class Person...
class Person:
# Will have contact fields all people have - or you could split these off into an
# object.
parent # Will be set to None for adults or else point to their parent's
# Person object.
billing_info # Set to None for non-adults, else to their BillingInfo object.
student_info # Set to None for non-student parents, else to their StudentInfo
# object.
Checking the fields will allow you to create lists as you desire.
One solution is to create a base Info class/interface that the classes ContactInfo, StudentInfo, and BillingInfo inherit from. Have some sort of Person object that contains a list of Info objects, and then you can populate the list of Info objects with ContactInfo, StudentInfo, etc.
In pseudocode, you could do something like this:
Class Student
Inherits WhateverBase
Private m_StudentType as EnumStudentTypes 'an enum containing: Adult, Child
Private m_Billing as Billing
Private m_Contact as Contact
Private m_Parent as Parent
Public Sub Constructor(studentType, billing, contact, parent)
...logic to make sure we have the right combination depending on studentType.
...throw an exception if we try to assign a a parent to an adult, etc.
...maybe you could have seperate constructors, one for each studenttype.
End Sub
Public Property StudentType as EnumStudentTypes
Get
Return m_StudentType
End Get
End Sub
Public Property Parent
Get
...code to make sure we're using a studentType that has a parent,
...and throws an exception if not. Otherwise it returns m_Parent
End Get
End Sub
[more properties]
End Class Student
Then you could create a class called StudentManager:
Public Class StudentManager
Public Function GetAdults(studentCollection(Of Students)) as StudentCollection(Of Students)
Dim ResultCollection(Of Students)
...Loop through studentCollection, adding all students where Student.StudentType=Adult
Return ResultCollection
End Function
[Other Functions]
End Class
Public Enum StudentType
Adult=0
Child=1
End Enum

Categories

Resources