I'm developing a system based on Django admin. So all models could be edited also only from admin site. Model has a char field 'user'. I want to set current logged in admin username (or firstname, or lastname) as default value to 'user' field. How could I implement this?
Default values are set as parameters when defining model fields, so I guess no request object could be recieved? Maybe I should set the value when creating instance of model (inside init method), but how I could achieve this?
I found this recipe helpful: http://code.djangoproject.com/wiki/CookBookNewformsAdminAndUser
This is how you do it on the form level and not the save http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield%5Ffor%5Fforeignkey
Related
When showing {{ user }} in a Django template, the default behavior is to show the username, i.e. user.username.
I'm changing this to show the user's initials instead, which are stored in a separate (OneToOneField) UserProfile model.
So in customsignup/models.py I've overridden the __unicode__ function successfully, with the desired result:
# __unicode__-function overridden.
def show_userprofile_initials(self):
return self.userprofile.initials
User.__unicode__ = show_userprofile_initials
But of course, the database is hit again because it needs to independently select the UserProfile model every time a user object is asked to show itself as a string. So even though this works, it escalates the number of database hits quite a bit.
So what I'd like to do, is to automatically use select_related('userprofile') whenever a User model is called from the database, seeing that I will essentially always want the profile when dealing with the user in the first place.
In more technical terms, I'm attempting to override the model manager of an existing model. So I'm in no control over the User model definition itself, since that's in an imported library.
So I've tried overriding the objects member of the User model in the same way that I overrode the __unicode__ function, like so:
# A model manager for automatically selecting the related userprofile-table
# when selecting from user-table.
class UserManager(models.Manager):
def get_queryset(self):
# Testing indicates that code here will NOT run.
return super(UserManager, self).get_queryset().select_related('userprofile')
User.objects = UserManager()
Is this supposed to work? If so, what am I getting wrong?
(I will mark an answer as correct if it can show that this is not supposed to work in the first place.)
A similar question I've found is here, but it's approached from the other end:
Automatically select related for OneToOne field
No, User.objects = MyManger() is not supposed to work. According to the docs, there are just two supported methods for extending the provided auth User model, either a profile model, as you are doing, or a proxy model, which probably doesn't fit your case. From the docs (emphasis added):
There are two ways to extend the default User model without substituting your own model. If the changes you need are purely behavioral, and don’t require any change to what is stored in the database, you can create a proxy model based on User. This allows for any of the features offered by proxy models including default ordering, custom managers, or custom model methods.
If you wish to store information related to User, you can use a OneToOneField to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user.
As an alternative to extending the provided auth User model, you can provide your own custom User model. Then you will have complete control over its managers.
Instead, consider simply replacing {{ user }} with {{ user.profile.initials }}. Creating the OneToOne field on your profile model also creates a reverse accessor for instances of the related model. You can specify the reverse accessor name by the related_name keyword argument on the profile model field. For example...
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model)
user = models.OneToOneField('auth.User', related_name='profile')
initials = models.CharField(max_length=6)
some_user = User.objects.first()
# assuming there is already a profile related to this user
some_user.profile.initials = 'S.P.Y.'
You could also make a __str__ method for your profile model like
def __str__(self):
return self.initials
Then when you do {{ user.profile }} in a template, the initials will be shown.
I have a model where I didn't specify a primary key and Django generated one for me. Now I create a ModelForm for the model and I have specified id in the fields section of ModelForm. However, in my ModelForm object, the id field is not present.
Are only the model fields explicitly declared visible in the ModelForm?
Are only the model fields explicitly declared visible in the
ModelForm?
Yes, generally you don't want to mess with this field, if the user inputs a value for the id field it's very likely to be duplicated so this is something you want django to take care of for you.
My Django project always sorts Users by their first name, and I'd like to create an index on the field, but since it's a Django-defined model, I can't add it into the built-in code. First, does Django already have an index on the first name field? If not, can I add an index somehow? I know I could subclass the User model and handle all of the intricacies with that, but is there another way?
Based on the source code https://github.com/django/django/blob/master/django/contrib/auth/models.py#L320 , There's no db_index on the first name field.
You should Extending Django’s default User to have your own db_index
https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#extending-django-s-default-user
I have a model which has a ForeignKey field, and I wish to change its value in a model instance, I tried something like this:
#object and user are model instances, owner is a FK field
object.owner = user
This raises a ValueError : "object.owner is not an instance of User"
Is there a workaround for this?
user should be a correct instance of User, and if you just created it instead of retrieved it from the database, it should be save()-d before you save object.
Make sure that user is an instance of the same User that was used in defining the ForeignKey.
I'm trying to filter the User list in Django using a UserProfile Field... I need to implement a queue system where new users are put in a queue until an Admin approves them.
I simply added a is_in_queue boolean field to my UserProfile model... However, when displaying the user list in my Admin area, I realized that you can't filter the list using a Model's foreign key field (in this case, a field of UserProfile)
Apparently, list_display items can be callables but list_filter can't, so I can list IF a user is in the queue without a problem, but the admin would have to scroll through the whole user list to spot which ones are in the queue which makes no sense... Filtering only users that are in the queue (using userprofile.in_queue) would be much more practical...
Finally, I thought about adding a custom view to my admin area that would list only the user in the queue, but that custom view does not show up on the Admin area Index page, and putting together a whole new AdminSite only for a new filtering option seems a bit over the top...
So basically to sum it up: Can I filter my User list based on a
UserProfile field? If not, can I add a custom view that's accessible
from the front page without having to create a completely new
AdminSite only for that?
Django 1.3 fixed that - list_filter now allows to span relations:
https://docs.djangoproject.com/en/1.3/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter
You may want to take a look in to using a custom manager for the admin_objects of your model.
class UserAdminManager(models.AdminManager):
"""
Custom manager for the User model.
"""
def get_query_set(self):
"""
Overwrites the get_query_set to only return Users in the queue.
"""
return super(UserAdminManager, self).get_query_set().filter(userprofile__queue=True)
By overwriting the get_query_set method you can filter the results. Then just assign this to the admin_objects property of your User model.
admin_objects = UserAdminManager()
Some of the property names in my example may be wrong, as I don't know your model setup, but hopefully you get the idea.
You can research this further by checking out the django docs and searching for "custom managers".
It sounds to me like the quickest and easiest option is to add a new admin view to your application, specifically for your custom user model. See the Django admin docs for details, though it sounds like you know how to use Admin already.
Once the admin page is specific to your model, all your custom fields will no longer be foreign keys. This would make filtering easy.