How to specify data in models.ManyToManyField(Foo,Bar) - python

I'm working on an application were I want the user roles to be entered into a table in the database.
class Role(models.Model):
name = models.CharField(max_length = 40)
details = models.TextField()
class Foo(models.Model):
name = models.CharField(max_length = 40)
details = models.TextField()
class Bar(models.Model):
name = models.CharField(max_length = 40)
detauls = models.TextField()
foos = models.ManyToMany(Foo,related_name="foo_binding_and_roles")
I want the schema of the table foo_binding_and_roles to resemble:
{|id|Foo_id|Bar_id|Role_id|}
I'm still scratching my head on this, wondering if it's even possible. I know if I write a custom manager I could pull it off but I want to avoid that.
The idea behind this scheme, is to assign users permissions on a relational basis when bar meets foo and foo meets bar.

I don't understand what exactly you are trying to do, but reading this line: {|id|Foo_id|Bar_id|Role_id|}
makes me think you could either define a model with those fields, or set up a through model with that extra field.

To simplify this so you can think of it more clearly, don't use many-to-many associations, and build your entire scheme using many-to-one associations. If I understood you right, I think what you're looking for is possible using a three-way association class.

Related

Django models queries

I have 3 tables person(id, email,password,type), user_location(id,location,u_id) and reviews(id,review,from_id,to_id). The user_location(u_id) is the foreignkey to person(id). The review(from_id,to_id) is also foreignkey to person(id). So how can i filter out a person with type 'a' and location 'b' and the reviews he got with the reviewers name?
models.py
class Person(models.Model):
email = models.CharField(max_length=30)
pwd = models.CharField(max_length=30)
type = models.CharField(max_length=30)
class User_locations(models.Model):
location = models.CharField(max_length=30)
u_id = models.ForeignKey('Person', on_delete=models.CASCADE)
Not sure if I really understand what you're trying to do but this should point you in the right direction. Don't forget to refer to the doc for Many-to-one relationships and Lookups that span relationships. It says there:
To refer to a “reverse” relationship, use the lowercase name of the model.
And then use the normal __ to access attributes.
a_and_b = Person.objects.filter(type='a', user_locations__location='b')
reviewers = Person.objects.filter(to_id__in=a_and_b)
The first query selects all users with type a and location b. The second query filters on those results. This is all untested so you might need to tweak a little. Bottom line: follow the relationships. As a side note, you might want to read up on Django model naming conventions.

django circular import solutions

Please help me. There is a Django project with circular import. Project's applications are connected only one side. But there are functions that use other models without params (for using in template) and that makes it impossible to move the function.
I have found two solutions:
First way is to import model inside function.
And another way it to move two models into one file.
Both solutions work without problem, but which one is better?
class InitialArticle(models.Model):
by = models.ForeignKey(get_user_model(), null=True, on_delete = models.SET_NULL)
category = models.ForeignKey(ArticleCategory, null=True, on_delete=models.CASCADE)
keywords = models.CharField(max_length = 110, unique = True)
def get_articles_of_initialarticle(self):
from article.models import Article
return Article.objects.filter(initial = self)
Please help me find a better way. Maybe there is another solution?
You can add related_name in Article.initial like so:
class Article(...):
initial = models.ForeignKey(to='InitialArticle', related_name='articles')
After that you can use it like so:
initial_article = InitialArticle.objects.filter(...).first()
initial_article.articles.all() # return all articles which have foreign key to this article
Also in models.ForeignKey you can use string instead of importing the model like I have written
Or you can do it without adding related_name.
Default related name will be like so: article_set
And if you do not set related_name you can write like so:
initial_article = InitialArticle.objects.filter(...).first()
initial_article.article_set.all() # return all articles which have foreign key to this article

Django/Python: Best Practice/Advice on handling external IDs for Multiple Multi-directional External APIs

So this is more of a conceptual question, and I am really looking for someone to just help point me in the right direction. I am building a middleware platform where I will be pull data in from inbound channels, manipulating it, and then pushing it out the other door to outbound channels. I will need to store the external id for each of these records, but the kicker is, records will be pulled from multiple sources, and then pushed to multiple sources. A single record in my system will need to be tied to any number of external ids.
a quick model to work with:
class record(models.Model):
#id
Name = models.CharField(max_length=255, help_text="")
Description = models.CharField(max_length=255, help_text="")
category_id = model.ForeignKey(category)
class category(models.Model):
#id
name = models.CharField(max_length=255, help_text="")
description = models.CharField(max_length=255, help_text="")
class channel(models.Model):
#id
name = models.CharField(max_length=255, help_text="")
inbound = models.BooleanField()
outbound = models.BooleanField()
Obviously, I cannot add a new field to every model every time I add a new integration, that would be soooo 90s. The obvious would be to create another model to simply store the channel and record id with the unique id, and maybe this is the answer.
class external_ref(models.Model):
model_name = models.CharfieldField()
internal_id = models.IntegerField()
external_id = models.IntegerField()
channel_id = models.IntegerField()
class Meta:
unique_together = ('model', 'internal_id',)
While my example holds simply 4 models, I will be integrating records from 10-20 different models, so something I could implement an a global level would be optimal. Other things I have considered:
Overwriting the base model class to create a new "parent" class that also holds an alpha-numberic representation of every record in the db as unique.
Creating an abstract model to do the same.
Possibly storing a json reference with channel : external_id that I could ping on every record to see if it has an external reference.
I'm really an open book on this, and the internet has become increasingly overwhelming to sift through. Any best practices or advice would be much appreciated. Thanks in advance.
I have this exact issue and yes there is not much information on the web in using Django this way. Heres what Im doing - haven't used it long enough to determine if its "the best" way.
I have a class IngestedModel which tracks the source of the incoming objects as well as their external ids. This is also where you would put a unique_together constraint (on external_id and source)
class RawObject(TimeStampedModel):
"""
A Table to keep track of all objects ingested into the database and where they came from
"""
data = models.JSONField()
source = models.ForeignKey(Source,on_delete=models.PROTECT)
class IngestedModel(models.Model):
external_id = models.CharField(max_length=50)
source = models.ForeignKey(Source,on_delete=models.CASCADE)# 1 or 0
raw_objects = models.ManyToManyField(RawObject,blank=True)
class Meta:
abstract = True
then every model that is created from ingested data inherits from this IngestedModel. That way you know its source and you can use each external object for more than 1 internal object and vise versa.
class Customer(IngesteModel):
class Order(IngestedModel):
...
etc.
Now this means there is no "IngestedModel" table but that every model has a field for source, external_id and a reference to a raw object (many to many). This feels more compositional rather than inherited - no child tables which seems better to me. I would also love to hear feedback on the "right" way to do this.

Embedding Vs Linking in MongoDB.when to embed and when to link?

I read this page but didn't get when to use embedding feature and when to use linking.I have a project in django for which I am using MongoDB.In my models.py file I have following models:
class Projects(models.Model):
projectName =models.CharField(max_length = 100,unique=True,db_index=True)
projectManager = EmbeddedModelField('Users')
class Teams(models.Model):
teamType = models.CharField(max_length =100)
teamLeader = EmbeddedModelField('Users')
teamProject = EmbeddedModelField('Projects')
objects = MongoDBManager()
class Users(models.Model):
name = models.CharField(max_length = 100,unique=True)
designation = models.CharField(max_length =100 )
teams = ListField(EmbeddedModelField('Teams'))
class Tasks(models.Model):
title = models.CharField(max_length = 150)
description = models.CharField(max_length=1000)
priority = models.CharField(max_length=20)
Status = models.CharField(max_length=20)
assigned_to = EmbeddedModelField('Users')
assigned_by = EmbeddedModelField('Users')
child_tasks = ListField()
parent_task = models.CharField(max_length = 150)
My question is if we do embedding do we have to update the object in all models.Like if I want to update the name of a 'user' ,I would have to run update for models:Projects, Teams, Users and Tasks or linking would be better in my case?
In your example, yes, changing the name of a user implies that if you use embedding then you must update all other documents with an extra step. What is more appropriate in your situation is linking (referencing). This involves an extra step at query time, but because of your particular "business logic", it is better.
Generally, if a given document needs to be accessed from a number of different places then it makes sense to make it a reference rather than embedded. The same applies in situations when a document changes frequently.
First, conceptually, name your model classes as singular objects.
Users should be User, Teams should be Team...
Think of the model as the mold from which multiple objects will be made. User model will product Users and be stored in a table called Users where each document/row is a User object.
Now, regarding your question, hymloth is exactly right. The way to make it a reference to a document instead of an embedded one is to change those particular fields to reference the id of a user in the user's collection. That way you are just storing an id to lookup instead of a copy of the user document. When you change the reference document, it will be changed in all of the places it is referenced as well. (Typical relational association)
I didn't see a field for that in Django-mongoDB either but maybe you can use the traditional django ForeignKey field for this purpose. I don't know if you can mix and match so give it a shot.
for example, your Teams class would have a field like this:
teamLeader = ForeignKey(User)
Let me know if that works.

Creating "classes" with Django

I'm just learning Django so feel free to correct me in any of my assumptions. I probably just need my mindset adjusted.
What I'm trying to do is creating a "class" in an OOP style. For example, let's say we're designing a bunch of Rooms. Each Room has Furniture. And each piece of Furniture has a Type and a Color. What I can see so far is that I can have
class FurnitureType(models.Model):
name = models.CharField(max_length=200)
class FurnitureColor(models.Model):
name = models.CharField(max_length=50)
class FurniturePiece(models.Model):
type = models.ForeignKey(FurnitureType)
color = models.ForeignKey(FurnitureColor)
sqft = models.IntegerField()
name = models.CharField(max_length=200)
class Room(models.Model):
name = models.CharField(max_length=200)
furnitures = models.ManyToManyField(FurniturePiece)
The problem is that each FurniturePiece has to have a unique name if I'm picking it out of the Django admin interface. If one person creates "Green Couch" then no one else can have a "Green Couch". What I'm wondering is if a) I need to learn more about Django UI and this is the right way to design this in Django or b) I have a bad design for this domain
The reason I want Furniture name to be unique is because 10 people could create a "Green Couch" each with a different sqft.
I don't get the problem with unique name. You can just specify it to be unique:
class FurniturePiece(models.Model):
type = models.ForeignKey(FurnitureType)
color = models.ForeignKey(FurnitureColor)
sqft = models.IntegerField()
name = models.CharField(max_length=200, unique=True)
I don't know whether you have to learn about Django UI or not. I guess you have to learn how to define models. The admin interface is just a generated interface based on your models. You can change the interface in certain aspects without changing the models, but besides that, there is less to learn about the admin interface.
I suggest you follow a tutorial like the djangobook, to get a good start with Django.
I think, the problem that you have is not how to use Django but more that you don't know how to model your application in general.
First you have to think about which entities do yo have (like Room, Furniture, etc.).
Then think about what relations they have.
Afterwards you can model them in Django. Of course in order to do this you have to know how to model the relations. The syntax might be Django specific but the logical relations are not. E.g. a many-to-many relation is not something Django specific, this is a term used in databases to express a certain relationship.
Djangos models are just abstraction of the database design below.
E.g you specified a many-to-many relationship between Room and FurniturePiece.
Now the question: Is this what you want? It means that a piece of furniture can belong to more than one room. This sounds strange. So maybe you want to model it that a piece of furniture only belongs to one room. But a room should still have several pieces of furniture. We therefore define a relationship from FurniturePiece to Room.
In Django, we can express this with:
class FurniturePiece(models.Model):
room = models.ForeignKey(Room)
type = models.ForeignKey(FurnitureType)
color = models.ForeignKey(FurnitureColor)
sqft = models.IntegerField()
name = models.CharField(max_length=200)
Maybe you should first learn about relational databases to get the basics before you model your application with Django.
It might be that this not necessary in order to create an application in Django. But it will definitely help you to understand whats going on, for every ORM not just Django's.
Why does each FurniturePiece need to have a unique name? It seems to me that if you remove that constraint everything just works.
(as an aside you seem to have accidentally dropped the models.Model base class for all but the Room model).
This is how I would do it:
class Room(models.Model):
name = models.CharField(max_length=255)
pieces = models.ManyToManyField('FurniturePiece')
class FurniturePiece(models.Model):
itemid = models.CharField(max_length=20, unique=True) # This is what I would require to be unique.
name = models.CharField(max_length=255)
type = models.ForeignKey('FurnitureType') # Note I put 'FurnitureType' in quotes because it hasn't been written yet (coming next).
color = models.ForeignKey('FurnitureColor') # Same here.
width_in_inches = models.PositiveIntegerField()
length_in_inches = models.PositiveIntegerField()
# Next is the property decorator which allows a method to be called without using ()
#property
def sqft(self):
return (self.length_in_inches * self.width_in_inches) / 144 # Obviously this is rough.
class FurnitureType(models.Model):
name = models.CharField(max_length=255)
class FurnitureColor(models.Model):
name = models.CharField(max_length=255)
Envision objects as real life objects, and you'll have a deeper understanding of the code as well. The reason for my sqft method is that data is best when normalized as much as possible. If you have a width and length, then when somebody asks, you have length, width, sqft, and if you add height, volume as well.

Categories

Resources