I have two models and want to set a relation to them.
class ModelA(models.Model):
id = models.IntegerField(primary_key=True) # DB => PK, AI, NN
name = models.CharField(max_length=50)
...
class ModelB(models.Model):
modelA = models.OneToOneField("ModelA", primary_key=True)
description = models.CharField(max_length=255)
...
So I have a relationship between the two models. Is it possible to add a member to ModelA which stores the relation to ModelB without saving this relation to the database?
I would call it a dynamically created relation or something. Any hints oder suggestions how to let both models know each other?
I think it would be benefiting if the relation on one model can be done dynamically. Otherwise I'll get some trouble storing the models because one of the IDs won't be stored if I save one of the models.
I want to have the relation on both models so I can easily use the models as inline in django-admin.
regards
The reverse relation in Django is created by default.
To get the ModelA you will use:
ModelA.objects.filter(modelb__pk = 1)
You will find more details here:
https://docs.djangoproject.com/en/dev/topics/db/queries/
Django ORM will save ModelA first, then ModelB, in order to maintain data integrity in the DB.
Django can try saving multiple items in one transaction, and this way, if you cancel it, nothing will be saved, but this is possible in shell or in Python code. Over HTTP you can't maintain a transaction over several queries so far.
If you need to show model A as inline of model B, you need a custom admin interface, not new fields/models. I can't tell how to write custom admin widgets. I did do a similar thing with custom editor views & templates & Javascript. I stored the unsaved models in request.session.
Related
Let's say we have the following pseudo database structure:
models.py
class Order(models.Model):
...
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
...
So each Order may contain one or more OrderItems.
By default, if I render the default form for these models, we will end up with two separate forms, where the user will have to create the Order first in one form, and then navigate to another form for OrderItem to start creating OrderItems for that Order.
Unless I create my own custom form from scratch (which is not integrated with any models) and then write the code to connect it with data models in the server-side. However, this is a very common use case so there has to be a way to handle such a scenario without having to rebuild so much from scratch.
Django already has a ManyToManyField which allows us to handle a similar kind of operation where what the user sees in the auto-generated form is simple, yet it involves interaction with multiple data models. How come there's no way to handle such form representation of data without having to do so much from scratch?
For example, in Django Rest Framework we can use Nested Relationships to define one model serializer as a field of another model serializer. But for Django models, I couldn't find any documentation for anything similar.
I have CustomUser model and Post model. I consider adding a lightweight like mechanism to the posts.
What comes to my mind is defining a Like model in such fashion to connect the models to each other:
class LikeFeedback(models.Model):
likingUser = models.ForeignKey(CustomUser)
post_liked = models.ManyToManyField(Post)
But this design produces a new row in the database with each like.
Another option is to define CustomUser and Post models in a way that:
class Post(models.Model):
...
users_liked = models.ManyToManyField(CustomUser)
class CustomUser(models.Model):
...
posts_liked = models.ManyToManyField(Post)
I am not sure if this approach creates a new row or uses a different indexing mechanism, but it looks tidier.
In terms of DB performance what approach is the fastest? Do I need to define the ManyToMany connection in both models to speed up DB processes? Because 15 posts are to be displayed on the webpage at once and and with every post it is necessary to check if the visitor already liked the note. Also, with each like and takeback a write operation is to be performed on the DB.
I am not sure if this approach creates a new row or uses a different indexing mechanism, but it looks tidier.
A ManyToManyField will create an extra table called a junction table [wiki] with ForeignKeys to the model where you define the ManyToManyField, and the model that you target with the ManyToManyField.
You furthermore only need one ManyToManyField, otherwise you make two relations that act indepdently. You thus model this as:
from django.conf import settings
class Post(models.Model):
# ...
likes = models.ManyToManyField(
settings.AUTH_USER_MODEL,
related_name='liked_posts'
)
class CustomUser(models.Model):
# ...
# no ManyToManyField to Post
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
I have a model with two integer fields which are supposed to be foreign keys. In my admin view, those two fields are editable but I would like to display a search icon next to the field, so I can retrieve the id of another model and append to the field. Does django have this feature?
class Linkage(models.Model):
user_id = models.IntegerField(default=1)
parent_id = models.IntegerField(default=0)
If your model has 2 fields that should actually be foreign keys, then you need to use ForeignKey instead of IntegerField as so:
from django.db import Models
from app.models import yourModel
class Linkage(models.Model):
user_id = models.ForeignKey(yourModel)
parent_id = models.ForeignKey(yourModel)
This Django feature will take care of linking your Linkage to your other model of choice automatically. In the admin, you will no longer need to set an integer with the id of the foreign key, you will be able to simply select an instance of the linked model.
You can read more about Django fields references here.
EDIT: In the way you designed yoour models, there might for example not be a parent_id, so you can add options such as null=True to the parent_id field as so:
parent_id = models.ForeignKey(yourModel, null=True)
I strongly recommend that you read the Django documentation, it is really good for beginners as it is very detailed and clear. You can access the documentation here.
They also have a set of tutorials to get you through the steps and introduce you to the different basics you need to know to get started with Django here.
I want to insert a many-to-many relationship into some models, without having to completely rewrite the models.
For example, consider the django User model and a model Foo from a third-party module I've installed.
If I 'owned' Foo I could just do:
class Foo(models.Model):
users = models.ManyToMany(User)
Then, if I wanted to add a Foo to user, or vice versa I could do:
my_user.foo_set.add(my_foo)
my_foo.users.add(my_user)
But I don't 'own' either code, and I want to inject this relationship, so I can do the above.
Now, if I wanted I could even do a through relationship through a model I made and and put that on either side, but that still requires altering the models.
Now, behind the scenes it looks like django many-to-many relationships are models (they definitely have tables), is it possible to make this code:
class FooUserRelationship(models.Model):
foo = ForeignKey(Foo)
user = ForeignKey(User)
Act just like a many-to-many relationship?
you can use proxy models. Here person is a 3rd party model and Myperson is a your model modifying extra attributes to the main models. for more details https://docs.djangoproject.com/en/1.9/topics/db/models/#proxy-models
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class MyPerson(Person):
users = models.ManyToMany(User)
class Meta:
proxy = True
The cleanest way i can think of is to provide a middle class (or you could subclass which would provide the almost the same queries) with a onetoone to one side and then many to many
class FooUser(models.Model):
user = OneToOneField(AUTH_USER_MODEL)
foo = ManyToMany(Foo)
my_user.foouser.foo_set.add(my_foo)
my_foo.foousers.add(my_user.foouser)
Now I admit that this isn't the cleanest way of doing things since it would involve a further SQL join when retrieving results, but it does keep in tact your link and provides a way to modify as you please.
I have been dealing for a while with Django's authentication system and I just cannot understand why I have to go through this process Django doc! :
from django.contrib.auth.models import User
class Employee(models.Model):
user = models.OneToOneField(User)
department = models.CharField(max_length=100)
... rather than simply extending the "User" class like this:
class Employee(User):
....
... and re-using all the code contained within. I have taken a look at articles like: b-list.org! , and I understand that the problem may be related with the automatic Django database management.
Is there a way in which I can automatically extend the User model without having to create an additional table in the database, so that Django modifies the current database table for me?
I tend to obey the fellas of the django
https://docs.djangoproject.com/en/1.5/topics/auth/customizing/#extending-the-existing-user-model
Because only abstract models don't create tables in django and built-in user model is not