Is it possible to include a ForeignKey inside a JSONField schema? How else can I effect this? - json

I am building an app in Django that allows users to build their own forms and in effect customise dynamic models.
After much research, I've decided to effect this through Django, PostgreSQL and JSONFields where one model holds the schema and another holds the record data:
class = Template(models.Model):
schema = JSONField(null=True) # Schema for the form/model
class = DynamicModel(models.Model):
data = JSONField(null=True) # Corresponding data for the form/model
template = models.ForeignKey(Template, null=True,
blank=False, on_delete=models.SET_NULL)
This means users can define their own model templates and I can hold different records using that template in another model.
The idea is to parse the template.schema JSONField to display editable forms using jQuery and to store the output as dynamicmodel.data JSONField. Validations are passed on the client side.
However, this comes with the drawback if I want to allow users to include ForeignKey lookups in their models. For example, say they wanted to add a choice box that offered selections from different customer.ids in a Customer(models.Model) class.
Without hardcoding the ForeignKey directly into the DynamicModel class (which would defeat the point of the exercise) can you think of a way I can achieve this?

Related

Django GenereicForeignKey v/s custom manual fields performance/optimization

I'm trying to build a typical social networking site. there are two types of objects mainly.
photo
status
a user can like photo and status. (Note that these two are mutually exclusive)
means, We have two table (1) for Image only and other for status only.
now when a user likes an object(it could be a photo or status) how should I store that info.
I want to design a efficient SQL schema for this.
Currently I'm using Genericforeignkey(GFK)
class LikedObject(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
but yesterday I thought if I can do this without using GFK efficiently?
class LikedObject(models.Model):
OBJECT_TYPE = (
('status', 'Status'),
('image', 'Image/Photo'),
)
user = models.ForeignKey(User, related_name="liked_objects")
obj_id = models.PositiveIntegerField()
obj_type = models.CharField(max_length=63, choices=OBJECT_TYPE)
the only difference I can understand is that I have to make two queries if I want to get all liked_status of a particular user
status_ids = LikedObject.objects.filter(user=user_obj, obj_type='status').values_list('object_id', flat=True)
status_objs = Status.objects.filter(id__in=status_ids)
Am I correct? so What would be the best approach in terms of easy querying/inserting or performance, etc.
You are basically implementing your own Generic Object, only you limit your ContentType to your hard coded OBJECT_TYPE.
If you are only going to access the database as in your example (get all status objects liked by user x), or a couple specific queries, then your own implementation can be a little faster, of course. But obviously, if later you have to add more objects, or do other things, you may find yourself implementing your whole full generic solution. And like they say, why reinvent the wheel.
If you want better performance, and really only have those two Models to worry about, you may just want to have two different Like tables (StatusLike and ImageLike) and use inheritance to share functionality.
class LikedObject(models.Model):
common_field = ...
class Meta:
abstract = True
def some_share_function():
...
class StatusLikeObject(LikedObject):
user = models.ForeignKey(User, related_name="status_liked_objects")
status = models.ForeignKey(Status, related_name="liked_objects")
class ImageLikeObject(LikedObject):
user = models.ForeignKey(User, related_name="image_liked_objects")
image = models.ForeignKey(Image, related_name="liked_objects")
Basically, either you have a lot of Models to worry about, and then you probably want to use the more Django generic object implementation, or you only have two models, and why even bother with a half generic solution. Just use two tables.
In this case, I would check if your data objects Status and Photo may have many common data fields, e.g. Status.user and Photo.user, Status.title and Photo.title, Status.pub_date and Photo.pub_date, Status.text and Photo.caption, etc.
Could you combine them into an Item object maybe? That Item would have a Item.type field, either "photo" or "status"? Then you would only have a single table and a single object type a user can "like". Much simpler at basically no cost.
Edit:
from django.db import models
from django.utils.timezone import now
class Item(models.Model):
data_type = models.SmallIntegerField(
choices=((1, 'Status'), (2, 'Photo')), default=1)
user = models.ForeignKey(User)
title = models.CharField(max_length=100)
pub_date = models.DateTimeField(default=now)
...etc...
class Like(models.Model):
user = models.ForeignKey(User, related_name="liked_objects")
item = models.ForeignKey(Item)

Django - Add rows to MySQL database

So I already have a database setup with a few columns and a few rows already inserted in. I'm trying to create a view that you would just input information into a form and press Submit, then a row would be added to the MySQL database with the information you just typed in.
I believe you can do this with admin, but I would like to try without admin and I'm not sure if this is possible? I've been using the MySQL commandline to add rows as of now..
Of coures this is possible this is a building block for data driven websites. You can use a ModelForm as Daniel suggested (they offer built in validation and HTML markup for FREE) to easily map your model to a front end form. It would probably be beneficial to start with django tutorial or documentation first.
At the the very basic, all you have to do is instantiate your model
new_entry = YourModel(name='me', age='222', about='stackoverflow')
then save it
new_entry.save()
This adds it as a new row to your db.
https://docs.djangoproject.com/en/dev/topics/db/models/
Why would it not be possible?
You probably want a modelform (but see the general form introduction first).
Try out this example of Generic Views: http://postneo.com/2005/08/17/django-generic-views-crud (assumes a model named Task)
With Generic Views you get Insert, Update and Delete for free without any real work. give it a try and let me know what you think.
from django.conf.urls.defaults import *
info_dict = {
'app_label': 'tasks',
'module_name': 'tasks',
}
urlpatterns = patterns('',
(r'^tasks/create/?$', 'django.views.generic.create_update.create_object', info_dict ),
(r'^tasks/update/(?P<object_id>\d+)/?$', 'django.views.generic.create_update.update_object', info_dict),
(r'^tasks/delete/(?P<object_id>\d+)/?$', 'django.views.generic.create_update.delete_object', info_dict ),
)
Django Docs: https://docs.djangoproject.com/en/1.2/ref/generic-views/#create-update-delete-generic-views

Can I create sperate queries for different views?

I'm learning sqlalchemy and not sure if I grasp it fully yet(I'm more used to writing queries by hand but I like the idea of abstracting the queries and getting objects). I'm going through the tutorial and trying to apply it to my code and ran into this part when defining a model:
def __repr__(self):
return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password)
Its useful because I can just search for a username and get only the info about the user that I want but is there a way to either have multiple of these type of views that I can call? or am I using it wrong and should be writing a specific query for getting different data for different views?
Some context to why I'm asking my site has different templates, and most pages will just need the usersname, first/last name but some pages will require things like twitter or Facebook urls(also fields in the model).
First of all, __repr__ is not a view, so if you have a simple model User with defined columns, and you query for a User, all the columns will get loaded from the database, and not only those used in __repr__.
Lets take model Book (from the example refered to later) as a basis:
class Book(Base):
book_id = Column(Integer, primary_key=True)
title = Column(String(200), nullable=False)
summary = Column(String(2000))
excerpt = Column(Text)
photo = Column(Binary)
The first option to skip loading some columns is to use Deferred Column Loading:
class Book(Base):
# ...
excerpt = deferred(Column(Text))
photo = deferred(Column(Binary))
In this case when you execute query session.query(Book).get(1), the photo and excerpt columns will not be loaded until accessed from the code, at which point another query against the database will be executed to load the missing data.
But if you know before you query for the Book that you need the column photo immediately, you can still override the deferred behavior with undefer option: query = session.query(Book).options(undefer('photo')).get(1).
Basically, the suggestion here is to defer all the columns (in your case: except username, password etc) and in each use case (view) override with undefer those you know you need for that particular view. Please also see the group parameter of deferred, so that you can group the attributes by use case (view).
Another way would be to query only some columns, but in this case you are getting the tuple instance instead of the model instance (in your case User), so it is potentially OK for form filling, but not so good for model validation: session.query(Book.id, Book.title).all()

Create Active/Archive Models in a DRY way (Django)

I have a model like the following, which is growing too large and needs to be split into a separate active table. At the end of the day, one table will contain all objects and the other will only contain active objects.
class Tickets(models.Model):
price = ....
number = .....
date = ....
active = ....
parent = models.ForeignKey('self', related_name='children')
ManyMoreFields
There are two sources of complexity:
1) The parent field on the ActiveTickets table is going to point to the Tickets table. The related_name should not change.
2) The ActiveTickets and Tickets table both have proxy Models that inherit from them.
class CityTickets(Tickets):
class Meta:
proxy = True
class ActiveCityTickets(ActiveTickets):
class Meta:
proxy = True
Obviously, I could just copy and paste all of the fields in Ticket (there are many), but that is not the right way of doing it. I've tried to use Abstract inheritance and Mixins (defining the fields in a separate class that is inherited by both Tickets and ActiveTickets).
One issue with abstract inheritance is that the ForeignKey field, parent, is causing issues since it's duplicative and the related_name is the same. Generally, my attempts have caused my unit and functional tests to fail.
What are some elegant approaches here? Should I think about creating two separate MySQL tables and then just using a single Model with multiple managers (and db routers)? Is that reasonable?
Maybe this helps:
class Base(models.Model):
m2m = models.ManyToManyField(OtherModel, related_name="%(app_label)s_%(class)s_related")
class Meta:
abstract = True
https://docs.djangoproject.com/en/dev/topics/db/models/#be-careful-with-related-name

Multilingual text fields with SQLAlchemy

I am currently evaluating SQLAlchemy for a project. Here is my schema:
a LANGUAGE table, with a row for each language supported
a TRANSLATION table with (ID, LANGUAGE_ID, STR)
various tables will, instead of storing text, store TRANSLATION_IDs, for example, BOOK(ID, TITLE_TRANSLATION_ID, ABSTRACT_TRANSLATION_ID)
Now, assuming each request has the current language ID available (for example, through a thread variable...), I would need SQLAlchemy to automatically join the TRANSLATION table, and thus have text fields in the current language. Something like:
class Book(Base):
id = Column(Integer, primary_key=True)
title = TranslatableText()
abstract = TranslatableText()
When retrieving, the ORM would automatically join to the TRANSLATION table with the current language ID, and my_book.title would give me the title in the current language.
I also need this to work across relations: if a class contains foreign keys to other classes that also contain translatable text fields, I would ideally like those to be retrieved too.
Lastly, I would also need to be able to get to the TRANSLATION_ID for each field, for example through my_book.title_translation_id.
I am not expecting a complete solution, but I'd like to know if something like this is feasible, and where to start.
You have to use the concept of http://docs.sqlalchemy.org/en/latest/orm/extensions/declarative.html#mixin-and-custom-base-classes
Create one top level class and write some funciton like read, write and create. Always call that function to create or read data from the database.
If you dont want to implement the mixin classes then also you can use event http://docs.sqlalchemy.org/en/latest/orm/events.html#sqlalchemy.orm.events.MapperEvents.translate_row