I am attempting to add the fields from a OneToOneField into my admin view. Here is an example of how my models look.
class Customer(BaseUser):
name = CharField()
address = CharField()
secondary_information = OneToOneField("SecondaryCustomerInfo", on_delete=SET_NULL, null=True)
class SecondaryCustomerInfo(models.Model):
email = EmailField()
And I tried adding in the fields as an inline like this.
class SecondaryCustomerInfoInline(admin.StackedInline):
model = SecondaryCustomerInfo
class CustomerAdmin(admin.ModelAdmin):
inlines = [SecondaryCustomerInfoInline]
But I get the error
<class 'user.admin.SecondaryCustomerInfoInline'>: (admin.E202) 'user.SecondaryCustomerInfo' has no ForeignKey to 'user.Customer'.
I'm used to putting the OneToOneField on the secondary model but my coworker asked that I put it on the main Customer model since we will be accessing that information more often. I think switching things around is what is tripping me up. How would I include the fields from SecondaryCustomerInfo on the admin view for Customer?
The answer would be to use Django Reverse Admin
From its documentation:
Module that makes django admin handle OneToOneFields in a better way. A common use case for one-to-one relationships is to "embed" a model inside another one. For example, a Person may have multiple foreign keys pointing to an Address entity, one home address, one business address and so on. Django admin displays those relations using select boxes, letting the user choose which address entity to connect to a person. A more natural way to handle the relationship is using inlines. However, since the foreign key is placed on the owning entity, django admins standard inline classes can't be used.
class CustomerAdmin(ReverseModelAdmin):
inline_type = 'stacked'
inline_reverse = ['secondary_information']
Related
I've been looking for a good database design for a twitter like social network site in my django project and I found two possibilities:
This one down here
class Following(models.Model):
follower = models.ForeignKey(User, on_delete=models.CASCADE,
related_name='following')
following = models.ForeignKey(User, on_delete=models.CASCADE,
related_name='followers')
And this other one
class User(AbstractUser):
follows = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='followed_by')
pass
Are these the same? Is there any difference here? Which one should I choose? I'm kind of new to this so I can`t figure out which one is the best option. I find the first one easier to understand.
If I add this to my user model
following = models.ManyToManyField('self', related_name="followers")
and run (assuming auth is the app where your user model is, and replacing 000X by the number of the generated migration)
python manage.py makemigrations auth
python manage.py sqlmigrate auth 000X
this is what I get:
CREATE TABLE `auth_user_following` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`from_user_id` integer NOT NULL, `to_user_id` integer NOT NULL);
ALTER TABLE `auth_user_following` ADD CONSTRAINT `auth_user__from_user_id_b9318b74_fk_auth_`
FOREIGN KEY (`from_user_id`) REFERENCES `auth_user` (`id`);
ALTER TABLE `auth_user_following` ADD CONSTRAINT `auth_user__to_user_id_b51bc961_fk_auth_`
FOREIGN KEY (`to_user_id`) REFERENCES `auth_user` (`id`);
ALTER TABLE `auth_user_following` ADD CONSTRAINT `auth_user_foll_from_user_id_to_au_88cd5a29_uniq`
UNIQUE (`from_user_id`, `to_user_id`);
So it creates a table with an auto-generated id and two foreign key columns, just as it would do with the explicit relation-only model, i.e. on the database side, there is no structural difference.
For code readability, I would much prefer to keep the relation in the model and not define it in a different class. However, if you want to add additional data to the relation (e.g. date_started_following), you will need an explicit relation model. Then, you might still want to mention this many-to-many-relation in your user model and point to the explicit relation using the through argument:
However, sometimes you may need to associate data with the
relationship between two models.
[...]
Django allows you to specify the model that will
be used to govern the many-to-many relationship. You can then put
extra fields on the intermediate model. The intermediate model is
associated with the ManyToManyField using the through argument to
point to the model that will act as an intermediary.
One other reason for the first approach or an explicit through model is that it might facilitate some queries about the relationship, e.g. "find users who follow each other".
I would suggest both models code will work fine.
If you want to create custom user model with new fields then use below code format.
AbstractUser: Use existing fields in the user model
AbstractBaseUser:In case want to create your own user model from
scratch
class User(AbstractUser):
follows = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='followed_by')
pass
You want to segregate your app related changes then use below models code.
class Following(models.Model):
follower = models.ForeignKey(User, on_delete=models.CASCADE,
related_name='following')
following = models.ForeignKey(User, on_delete=models.CASCADE,
related_name='followers')
Hello Awesome People!
Such a question that I have made a lot of searches for it. I am done building a website two(2) months ago, but today The team decides to track every time an instance has been added to a Model in ManyToManyField() fields.
I was thinking using the through argument to point to the model that will act as an intermediary may work but not at all in my case (70%). Just Because I want to have a unique intermediary model that will record for all ManyToManyField()
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateTimeField(auto_now_add=True)
Ah! Something is required. I need to explicitly specify foreign keys to the models that are involved in the many-to-many relationship.
Django ContentType may anticipate for all my models, but it's not working, I wonder why? it also contains ForeignKey (the one required by an intermediary model).
Do I really need to edit all my ManyToManyField fields and create Model as much as ManytoManyField? is there a way to record date_joined without creating an intermediary model for each?
Are you perhaps looking for something like django admin's LogEntry model?
LogEntry contains the ContentType of the model instance that has changed, the id of the instance, the type of change and an abstract change message. With all of that you can retrace changes made to instances.
In django admin, the views take care of adding records to LogEntry via three methods log_change/addition/deletion: click.
I have a model with a foreignkey to another model
class Person(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
class Organisation(models.Model):
name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
contact = models.ForeignKey(Person)
I want to use a CreateView to be able to create a new Organisation, but be able to enter a new contact person details on the same page (i.e. when a new organisation is created, a new contact person must also be created).
What is the nicest (DRY) way to do this?
In the CreateView use the model that has the ForeignKey and since it inherits the FormMixin's form_class use the modelform_factory for that model with extra fields the fields of ForeignKey's model. Finally, overload either the validation or save methods with a get_or_create with the ForeignKey's model fields, passing the result to the ModelForm.
An alternative approach would be to chain two CreateViews. First with the Organization as the model, using the Contact's CreateView URL as its success_url. You can even use js to replace the first submit with the html of the second view.
Or you can try some hacks floating around utilizing formsets, though I prefer the first two methods in your case. The formset hacks are better suited for many-to-many relationships.
I've created a referral system on my website. Admittedly, it's late and this might not be the right sort of relationship.
class Referral(models.Model):
referred=models.ForeignKey(User, related_name="referred")
referrer=models.ForeignKey(User,related_name="referrer")
def __unicode__(self):
return self.user.first_name
What would others recommend to represent this relationship? If this is about right, is there a way for me to turn this into a pseudo inline for the User Admin? It's not allowed as currently constructed because there are two foreign keys to teh same table.
Thanks
Actually, this is a ManyToMany relationship between User and itself - the Referral class itself does not add anything to the relationship.
Normally, you can just add the ManyToManyField to the model and it will be displayed in the admin - but I'm guessing that the User class you reference is the built-in django.contrib.auth User, which you can't directly modify. So one way would be to define a UserProfile class which has a ForeignKey to User, and add the ManyToMany relationship there.
Edit in response to comment No, that's not quite what I meant. I'm saying you should drop the Referral class completely. A model which is just two FKs and nothing else - whether they're both to the same model or not - is the through table of a M2M relationship. That relationship, in your case, is between User and itself - but as I say, since you don't want to change User, it is between a new UserProfile model and itself.
I have a class UserProfile defined which takes the default user as a foreign key.
Now another class A has a foreign key to UserProfile.
So for saving any instance in class A, how do i give it the userprofile object.
Also, does making a class UserProfile mean that class user is still used and class UserProfile is just some other table?
I need to know this as I have to take care of the user profile creation, so I should know what gets stored where?
--
Confused
So for saving any instance in class A,
how do i give it the userprofile
object.
Create a app with a model which has a models.OneToOneField(User) or a models.ForeignKey(User, unique=True).
Make your project aware of your UserProfile by pointing to it from the settings.py file AUTH_PROFILE_MODULE = 'myapp.UserProfile'.
Read the documentation.
Also, does making a class UserProfile
mean that class user is still used and
class UserProfile is just some other
table?
Yes, your database will have both a auth_user and a user_profile table. This is due to the fact that using UserProfiles doesn't mean all user have to have profiles. Only the additional fields defined in the UserProfile model will be in the user_profile table.
I need to know this as I have to take
care of the user profile creation, so
I should know what gets stored where?
James Bennett created two nice apps which with a few hours of careful reading will be of great help especially when it comes to the user registration part. Go look at django-registration and django-profiles.
I assume your UserProfile model is intended to store additional information about your users. If so, there's documentation about the best approach to do this, which in brief is:
define a model with fields for the additional information you'd like to store, or additional methods you'd like to have available, and also add a OneToOneField from your model to the User model. This will ensure only one instance of your model can be created for each User.
Set AUTH_PROFILE_MODULE to myapp.MyModel, where myapp is the app containing the model MyModel which you want to use to store extra information about your users.