Display User's 'is_active' status in TabularInline Django - django

I have a Client object that has a User and a Company objects as FKs
class Client(models.Model):
user = models.OneToOneField(User)
company = models.ForeignKey(Company, blank=True, null=True)
In my CompanyAdmin, I want a list of all clients as a TabularInline, including the active status of each client (based on user object)
class CompanyClients(admin.TabularInline):
model = Client
fields = ('user', 'master')
class CompanyAdmin(admin.ModelAdmin):
inlines = [CompanyClients]
I want to add a column in my TabularInline to indicate that that user is active or not. I tried using 'user__is_active' to my fields but I get this error:
Unknown field(s) (user__is_active) specified for Client
I just want an indication even if read-only (which I tried by putting a readonly_fields and it didn't work too), not looking to save/edit each client user's active status value from the Tabular form.
How can I approach this? Thanks in advance.

class CompanyClients(admin.TabularInline):
model = Client
fields = ('user', 'master','user__active)
user__active

Related

How to make a model parameter unique by a other parameter in Django?

I want my id field to be unique per each customer field. Just like the option unique_for_date from Django (https://docs.djangoproject.com/en/1.11/ref/models/fields/#unique) but in this case, not date but customer.
class Sample(NGObject):
id = models.CharField(max_length=128, null=True, blank=False)
customer = models.ForeignKey(Customer, related_name="blood_samples", on_delete=models.SET(get_default_customer))
I believe this should be done, before the save() method?
When a User writes the wrong ID (that already exists) I would also like to present the information in the Admin Form just like it would for normal unique error.
class Meta:
unique_together = ('sample_id', 'customer',)
This has done the trick :)

Change the extra field data in Many-to-many relationship in Django

I have a Many-to-many relationship with additional fields and I want to be able to change data in these fields (e.g. the status of friendship). How can I do that? All the info I found is about how to just read these data.
class Profile(models.Model):
# other fields
friends = models.ManyToManyField("self", blank=True, through='Friendship',
through_fields=('user', 'friend'),
symmetrical=False,
related_name='user_friends')
class Friendship(models.Model):
user = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='friendships1')
friend = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name='friendships2')
status = models.PositiveSmallIntegerField(default=0)
class Meta:
unique_together = [['user', 'friend']]
I tried this and that didn't work, though no error was shown:
user = User.objects.get(username=request.user)
watched_user = User.objects.get(id=watched_user_id)
Friendship.objects.filter(user=user.profile, friend=watched_user.profile).status = 5
user.save()
I can't call Friendship.save() as it has no self.
And also I tried this and again no effect and no error:
user.profile.friends.set([watched_user.profile], through_defaults={'status': 5})
user.save()
And this gives me an error that there's no friend field and shows me the fields of Profile, not Friendship:
user.profile.user_friends.get(user=user.profile, friend=watched_user.profile).status=5
Please help me!
Upd: the answer helped and it works now! Thanks!
Though I still wonder if this is the only way or it can also be done from the user.profile side.
You can work with:
friendship = Friendship.objects.get(
user=user.profile,
friend=watched_user.profile
)
friendship.status = 5
friendship.save()
Here however there can be multiple Friendships between the same two users.
We can update all these friendships in bulk with:
Friendship.objects.filter(
user=user.profile,
friend=watched_user.profile
).update(status=5)

REST Framework: Update field in one model and track changes in another model

I have two models:
class CustomUser(models.Model):
...
act = models.CharField(max_length=10)
class ActHistory(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
last_act = models.CharField(max_length=10)
act_time = models.DateTimeField(auto_now_add=True)
I would like to create a single API endpoint /update/ with DRF that does this:
If value vs existing act value in the model is the same, do nothing.
If the values are different, update the CustomUser for the authenticated user with the value
Then insert a record row in ActHistory with user=authenticated user, last_act =
All the docs I managed to find only support doing either the update or create actions with each API point.
Thanks in advance!

Entry Unique to User

I have a model that keeps track of websites, and want it to be unique to that user. For example if the site is google.com, the user can only enter it once, however still allow multiple users can enter google.com. To give you a better idea here is my models.py:
class Site(models.Model):
url = models.CharField(max_length=500)
tag = models.ForeignKey(Tag)
user = models.ForeignKey('customauth.UserProfile')
Is there anyway to make the url field unique to users?
You could use unique_together constraint,
class Site(models.Model):
url = models.CharField(max_length=500)
tag = models.ForeignKey(Tag)
user = models.ForeignKey('customauth.UserProfile')
class Meta:
unique_together = ('url', 'user')
This option allows a user to create a unique url, else django raises an error. A single user cannot create two objects with same url.
The ValidationError raised during model validation when the constraint is violated has the unique_together error code.

Django query using related_name through another related_name

I have several models that have a ForeignKey back to a model which has a ForeignKey back to auth User in Django.
models.py
class UserDetails(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
related_name='userdetail_related')
details = models.CharField(max_length=100)
email = models.EmailField(unique=True)
class UserInformation(models.Model):
user = models.ForeignKey(
UserDetails,
related_name='userinfo_related')
info = models.CharField(max_length=100, default='this')
EDIT
My actual code for related_name as per Django Documentation is: related_name='%(app_label)s_%(class)s_related'. I put 'userdetail_related' for ease of explanation here.
Only one UserDetail per User, but many UserInformation per UserDetail.
Where there is an unregistered user and we have captured their email, the email can have UserDetail and UserInformation associated with it for a shopping cart guest checkout system.
In my View I want to access the UserInformation model from self.request.user.
I can access UserDetails in my view via:
details = self.request.user.userdetail_related.filter(
user=self.request.user).first()
But I can't seem to access UserInformation via:
info = self.request.user.userdetail_related.filter(
user=self.request.user).first().userinfo_related.filter(
info='this').first()
The only way I can get this to work is:
details = self.request.user.userdetail_related.filter(
user=self.request.user).first()
info = details.userinfo_related.filter(
info='this').first()
But this surely hits the database twice which I don't want.
Does anyone have a better way of getting the info from UserInformation using the session user 'through' UserDetails?
You can use following:
user_info = UserInformation.objects.filter(user__user=self.request.user).first()
Additionally, when you access UserDetails you don't really need the filter since you are trying to access the related objects from the user itself. So following would work as well.
details = self.request.user.userdetail_related.first()
And as a side note, I think you need OneToOneField here since one user should have only one UserDetails.
As it suggested by #AKS you should use OneToOneField to connect your models to the User. You can do it like this:
class UserDetails(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
related_name='userdetail_related')
details = models.CharField(max_length=100)
class UserInformation(models.Model):
user = models.OneToOneField(
UserDetails,
related_name='userinfo_related')
info = models.CharField(max_length=100, default='this')
Then you can access UserInformation and UserDetails like this:
details = self.request.user.userdetail_related.details
info = self.request.user.userinfo_related.info
To add to the other answers, a few remarks about the layout.
For Model names, best to always use singular (UserDetails -> UserDetail), not plural. Then, for the related name of a ForeignKey, use the plural (because the reverse lookup may find more than one item that have the backwards relationship).
class UserDetail(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='details')
details = models.CharField(max_length=100)
class UserInformation(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='info')
info = models.CharField(max_length=100, default='this')
Makes it much simpler to access in the views
request.user.infos.all().first()
request.user.details.filter(info__startswith="something")
Also, if practical, add both onto the User object, because "flat is better than nested" .
If every User only has one UserDetail and one UserInformation then its best to use OneToOneFields instead.