Varying embedded document - python

I am currently trying to connect my new Django rest API to my already existing mongodb database. Currently I am trying to copy the structure of my database objects as models. I ran into the problem, that I set up a structure like this in my db:
{
objects: { DE: [], US: [] }
}
The attributes DE and US can be anything here (Any geo for that matter). Is there any way I can incorporate this kind of pattern in my djongo model?

If by anything, you truly mean anything (or at least more than a few types of data), you could set up the model(s) as follows:
from djongo import models
...
ObjectDataModel(models.Model):
US = models.ListField()
DE = models.ListField()
class Meta:
abstract = True # Stops a database table from being made
...
YourModel(models.Model):
objects = models.ArrayModelField(model_container=ObjectDataModel)
You could also add custom validation if you want the ListFields to not just take anything under the sun; here's how to do that.
NOTE: This makes the objects field completely inaccessible via the Django Admin website; this is simply because the Admin site cannot possibly represent all possible input types that a ListField might be able to handle for the user (you can still submit values to the field via your forms/views, however).
You can also design a custom field, if you have the time to do so. I am (sadly) not terribly familiar with the geo field, so I'll instead point you here for instructions on how to go about that. You might also want to look at how Djongo's author went about implementing the ListField mentioned prior; it might give a hint on how to make list-like database entries. Here's the raw code for that.
Hope this helps!

Related

working with serializers in the Django-Rest Framework

I don't know is this a right platform to ask this question or not. I recently came across Django rest framework. I am using django for one of my projects.I want to use DRF as an api client for my project. I came across this term serializing the model instances and serializers. I went through DRF Tutorial , but I still have no idea of how it actually works.My questions are :
1.Why are serializers used? What purpose they serve?
2.What more can be done using serializers?
3.How do serializers work?
There may be lots of references on this present in the internet but I want a simple and easy-to-understand answer to this. Thanks!!
1.Why are serializers used? What purpose they serve?
In a very general way:
Imagine you want to invite your friend for a coffee. To inform your friend, you text "what: coffee, time: 12h, where: The fancy coffee bar on the corner". This text is your serialization of your idea.
The DRF does this for your Django models.
Imagine you have a JS client that doesn't (want to) know about your DB or Django models. You serialize your Django objects into JSON to have that data available in a JS compatible way:
data = {
"address": {
"street": "Fancy Street 1b"
}
};
DRF offers an easy way to translate Django model instances into JSON (or other formats). And that is what serializers do. They also offer to deserialize what your JS frontend sends back to your server.
2.What more can be done using serializers?
You can add more fields that are computed at serialization time. For example, instead of adding simple IDs for related objects you can also serialize the related objects and add them nested into the JSON (or XML or whatever format).
You can also add fields that you only need on the frontend side for some view, like things related to paging etc.
3.How do serializers work?
For python, the simplest serializer from python to JSON would be one that takes a python dictionary and simply creates string keys from the python keys, translates Django boolean into true and false strings, python None into null etc.
For more complex translations, you might want to add your own logic. E.g. like resolving related object references on Django models. Or formatting date objects into ISO standard strings (with timezone), localizing (decimal) numbers, localizing texts in general etc.

How to keep your code clean with denormalized data?

I'm going to ask this question in two parts: first the general question, and than the question for my specific use case.
The general question:
I'm building a podcast app, where, hopefully, we'll have users. Users have subscripitons, settings, ... , which I'd like to store on the User object, but subscriptions and settings don't belong in the same module in my code.
How do you structure your code so that all the relevant data about a user is stored together, but the code that defines and deals with specific properties can be separated?
My specific use case
I'm building the back end on Google App Engine. My user class looks something like this:
class User(ndb.Model):
username = ndb.StringProperty(required=True)
email = ndb.StringProperty(required=True)
...
Now I could just add another property for subscriptions, settings etc, but these definitions don't really belong in the users module. I've tried defining a SubscriptionsHolder and SettingsHolder class using ndb.PolyModel, but with multiple inheritance, only queries on the last superclass in the User definition supports querying.
I could just make the settings and other module query the User model directly, but this results in a circular dependency, where the User the users module depends on settings for subclassing, and settings depends on users for querying. I know I can resolve the circular dependency by moving the import statement around, but that just seems like a hack to me.
My approach was to treat User and Settings data as separate but related collections. Instead of subclassing or using PolyModel I simply introduced a way to imply a 1:1 relation between those data sets.
One way is to add a KeyProperty to Settings that links back to User. Another way is to create each Settings entity with the same id/name that is used by the related User entity. This second way allows a direct Settings.get_by_id() call once you have the User key.

App Engine: Structured Property vs Reference Property for one-to-many relationship

My background with designing data stores comes from Core Data on iOS, which supports properties having a one-to-many relationship with another entity.
I'm working on an App Engine project which currently has three entity types:
User, which represents a person using the app.
Project, which represents a project. A User may be associated with many projects.
Post, which is the main content behind a Project. A Project may have many posts.
Currently, User has a property, projects, that is a one-to-many relationship to Project entities. Project has a property, posts, that is a one-to-many relationship to Post entities.
In this case, is Datastore's Reference Property or NDB's Structured Property better for the job (and how are the two conceptually different)? Is there a better way to structure my data?
By reference property you probably mean Key Property. This is a reference to another datastore entity. It is present in both db and ndb APIs. Using these, you can model a many to one relationship by pointing many entities to the key of another entity.
Structured property is a completely different beast. It allows you to define a data structure, and then include it within another entity.
Here's an example from the docs where you include multiple addresses for a single contact:
class Address(ndb.Model):
type = ndb.StringProperty() # E.g., 'home', 'work'
street = ndb.StringProperty()
city = ndb.StringProperty()
class Contact(ndb.Model):
name = ndb.StringProperty()
addresses = ndb.StructuredProperty(Address, repeated=True)
guido = Contact(name='Guido',
addresses=[Address(type='home',
city='Amsterdam'),
Address(type='work',
street='Spear St',
city='SF')])
guido.put()
For your specific application I'd recommend using NDB (it's always best to use the latest version of the api available), with the following:
Post model included under Project model as a repeated structured property.
Users include a repeated KeyProperty that contains the keys of the Projects they have permissions to.
To make it a bit more complex, you can create a another model to represent projects and permissions/roles, and then include that as a repeated structured property within the user model.
The main reason you want to hang on to the keys, is to keep the data accessible in light of HRDs eventual consistency.
Let me know if you need any more help on this.
EDIT:
To clarify, here's the proposed structure:
Models:
User
User-Project-Mapping (optional, needed to handle permissions)
Project
Post
User model should contain User-Project-Mapping as repeated structured property.
Project model should contain Post as repeated structured property.
User-Project-Mapping only needs to contain Key reference to the Project and relevant permissions representation.
Since this sounds like a commercial project, if you'd like further help with this, I'll gladly consult for you. Hope you have enough to succeed!
There is another point that was not mentioned and might be relevant: entities inserted in a StructuredProperty "are not full-fledged entities", as mentioned in this part of the docs. Below is the complete quote (it refers to the same example mentioned in the answer by #Sologoub):
Although the Address instances are defined using the same
syntax as for model classes, they are not full-fledged entities. They
don't have their own keys in the Datastore. They cannot be retrieved
independently of the Contact entity to which they belong.
This may cast some limitations in the design given that you cannot reuse an entity's property without duplicating data. The KeyProperty, on the other side, refers to another entity's key and therefore represents entities relationship in a more "relational" way. And KeyProperties can also be repeated: just include the repeated=True parameter.

Specifying model Meta data through decorators (django)

The problem: I wish to use Postgres Schemas to separate the tables of different parts of my django app at database level.
Aside
You can skip this section, but I think it's helpful to add context to these things. My app is working on a database of existing data (stored in the public schema, helpfully), which it's very important I don't modify. As such, I want to separate "my" data into a separate schema (to which django will be given read/write/play in the sand access), while restricting access to the public schema to read-only. I originally tried to solve this by separating my data out into a separate database and using database routing, but it turns out (if I'd only read the documentation) that django doesn't support cross database dependencies (which is fair enough I suppose), and my models have foreign keys into the read-only data.
The meat
There exists a workaround for Django's lack of schema support (which you can read about here) which is to specify the db_table attribute in your model's meta, like so:
class MyModel(models.Model):
attribute1 = models.CharField()
#Fool django into using the schema
class Meta:
db_table = 'schema_name\".\"table_name'
This is great, but I didn't really want to have to write this for every single model in my app - for a start, it doesn't seem pythonic, and also there's every chance of me forgetting when I have to add a new model.
My solution was the following snippet:
def SchemaBasedModel(cls):
class Meta:
db_table = '%s\".\"%s' % (schema_name, cls.__name__)
cls.Meta = Meta
return cls
#SchemaBasedModel
class MyModel(models.Model):
attribute1 = models.CharField()
...
When I then run python manage.py shell I get the following:
>>> from myapp import models
>>> myModel = models.MyModel
>>> myModel.Meta.db_table
'myschema"."mymodel'
>>>
"Looks good to me," I thought. I then ran: python manage.py sqlall myapp. Sadly, this yielded the original table names - that is, the table names as they were before I applied this meta info. When I went back and applied the meta info "by hand" (i.e. by adding Meta inner classes to all my models), things were as expected (new table names).
I was hoping somebody could enlighten me as to what was going on here? Or, more usefully, what's the "right" way to do this? I thought the decorator pattern I've talked about here would be just the ticket for this problem, but apparently it's a non-starter. How can I quickly and easily apply this meta info to all my models, without typing it out every single time?
Edit: Perhaps I was a little unclear when I asked this - I'm as interested in know what's "actually going on" (i.e. why things aren't working the way I thought they would - what did I misunderstand here?) as how to solve my problem (clear separation of "my" data from legacy data, preferably on a schema level - but it's not the end of the world if I have to dump everything into the public schema and manage permissions on a per-table basis).
Second Edit: The accepted answer doesn't necessarily tell me what I really want to know, but it is probably the right solution for the actual problem. Short answer: don't do this.
I didn't really want to have to write this for every single model in my app -
for a start, it doesn't seem pythonic,
That's false. Some things have to be written down explicitly. "Explicit is better than Implicit".
and also there's every chance of me forgetting when I have to add a new model
That's false, also.
You won't "forget".
Bottom Line: Don't mess with this kind of thing. Simply include the 2 lines of code explicitly where necessary.
You don't have that many tables.
You won't forget.
Also, be sure to use DB permissions. Grant SELECT permission only on your "legacy" tables (the tables you don't want to write to). Then you can't write to them.

In Django, how can you change the User class to work with a different db table?

We're running django alongside - and sharing a database with - an existing application. And we want to use an existing "user" table (not Django's own) to store user information.
It looks like it's possible to change the name of the table that Django uses, in the Meta class of the User definition.
But we'd prefer not to change the Django core itself.
So we were thinking that we could sub-class the core auth.User class like this :
class OurUser(User) :
objects = UserManager()
class Meta:
db_table = u'our_user_table'
Here, the aim is not to add any extra fields to the customized User class. But just to use the alternative table.
However, this fails (likely because the ORM is assuming that the our_user_table should have a foreign key referring back to the original User table, which it doesn't).
So, is this sensible way to do what we want to do? Have I missed out on some easier way to map classes onto tables? Or, if not, can this be made to work?
Update :
I think I might be able to make the change I want just by "monkey-patching" the _meta of User in a local_settings.py
User._meta.db_table = 'our_user_table'
Can anyone think of anything bad that could happen if I do this? (Particularly in the context of a fairly typical Django / Pinax application?)
You might find it useful to set up your old table as an alternative authentication source and sidestep all these issues.
Another option is to subclass the user and have the subclass point to your user-model. Override the save function to ensure that everything you need to do to preserve your old functionality is there.
I haven't done either of these myself but hopefully they are useful pointers.
Update
What I mean by alternative authentication in this case is a small python script that says "Yes, this is a valid username / password" - It then creates an instance of model in the standard Django table, copies fields across from the legacy table and returns the new user to the caller.
If you need to keep the two tables in sync, you could decide to have your alternative authentication never create a standard django user and just say "Yes, this is a valid password and username"

Categories