Showing DateTimeField with editable=False in django admin - django

I have date field which is editable=False.
The field is populated with datetime.now() at creation time.
Since admin will not show editable=False fields, I created a custom admin.
The custom admin uses a form with this field:
date = forms.DateTimeField(widget=widgets.AdminSplitDateTime, required=False)
What I want to achieve is this:
users will not be able to touch this field (hence, editable=False)
Admin will be able to change the field's value but won't be forced to (this is why I have required=False)
Admin will be able to see the current value of the field.
I'm failing to achieve (3). I create an entry, and I see that it has a valid date when I look in the database. But when I open it from admin panel, the date widget is empty.
Any ideas how to make the date widget show the current value of the field?

First, models.DateTimeField uses widgets.AdminSplitDateTime by default in the Admin, you don't have to specify it explicitly.
For normal staff, use readonly_fields to prevent the date field from being changed.
For administrator, render a different changing form to allow the modification towards the date field. In Django 1.4, it can be easily done by overriding ModelAdmin.get_readonly_fields():
class YourModelAdmin(admin.ModelAdmin):
def get_readonly_fields(self, request, obj=None):
# we don't use self.readonly_fields anymore
if request.user.is_superuser:
return ()
return ['date']

Related

Date wont show in django admin panel

DateTimeField(auto_now_add=True, null=True) in my django model.py file and everything is working fine but the problem is it won't show data/time in django admin panel.
you need to add that field to list_display:
in admin.py:
class PostAdmin(admin.ModelAdmin): # "PostAdmin" is used for e.g purposes
[..]
list_display = (.., 'created_at',)
[..]
when you set:
DateTimeField(auto_now_add=True, null=True)
it will add your object that moment that you post the object, so if you want to select manually, you have to set:
DateTimeField(auto_now_add=False, null=True)
then it will show your Date field in your admin panel model.
Your date modified field may not display when editing an object since it is a read only value. In admin.py, try setting readonly_fields = ("date_modified",), replacing date_modified with whatever you named your DateTimeField

Django prevent superuser from seeing data in /change/ page

I'm using Django 2.1.5 and have been using the list_display in ModelAdmin-based classes to limit what our superusers can see in the admin pages. There is some sensitive data that only the user should have access to.
Say I have a app based on model SensitiveObject with id, name, secret, etc., I can simply exclude secret from the list_display and it will never show up in the Admin page. However, when I browse to /admin/full/myapp/sensitiveobject/ I will have a list of those object IDs and can simply go to /admin/.../sensitiveobject/<id>/change/ which will show all of the fields, including the ones that I excluded from list_display.
Is there a way to limit what I'm seeing in the /change/ endpoint, as well?
The fields attribute of your ModelAdmin is what defines the fields that are displayed on the change form for each object.
You can make this dynamic you can override the method get_fields:
def get_fields(request, obj=None):
fields = [] # Default list of fields
if request.user.passes_some_test():
fields.append() # The secret field
return fields

Django 1.11 admin form add search box to oneToOne field

I have a user, admin and employee models, both employee and admin are related to the user model with a oneToOne field what i would like to do is in the admin form i have one field "user"
instead of having a drop down field with all users i would like to have a search box so that when i search for a specific user i find him and choose him to be an admin.
how?
i also tried to add user's fields to admin's form but i couldn't
i tried the inline thing, the parent_link in the admin's model... but i couldn't find a solution
Now i would like to minimise the search through the long users list by adding a search box to the field
I have solved this type of problem using django-ajax-selects package. Hope this will help you.
app/admin.py:
from ajax_select import register, LookupChannel
#register('users')
class UsersLookup(LookupChannel):
model = User
def get_query(self, q, request):
return self.model.objects.filter(username__icontains=q)
class EmployeeAdminForm(forms.ModelForm):
user = AutoCompleteSelectField('users', required=False,
help_text=None)
class Meta:
model = Employee
fields = '__all__'
settings.py
AJAX_LOOKUP_CHANNELS = {
'users' : {'model': 'auth.user', 'search_field': 'username'},
}
Use django's raw_id_fields. With that you can declare a foreign key object searchable.

Hide Model Property from Django admin and set Its Value Manually

I want to hide a column from django admin and set its value from session.
In simple words i want to set a property of a model from session and don't want a field in admin for that column.
Can someone help me?
You can mark the field as read-only but still have it visible in the admin, or completely exclude it.
class MyModel(models.Model):
field1 = models.CharField(max_length=20) # this is editable
field2 = models.CharField(max_length=20, editable=False) # this is not
or
#admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
exclude = ['field2']
If you're using a custom model form in the admin, just don't include the field in the fields attribute.
As far as I remember there are a lot of ways to do this, with the fields attribute on Meta you can hide or select which fields to show.
check This example

Send an e-mail notification when a Django CharField is modified via the admin site

I have a CharField that is normally empty. I want to send out an e-mail notification to all managers (using mail_managers) when the field is set to a non-empty value. Changes to this field should only happen via the admin site.
I assumed this might be something I could do via signals but I do not see an appropriate signal listed in the documentation. Any ideas?
You will need to add some history to the field if you don't want updates if the field is changed again but just adding a save method to your model similar to should work:
from django.db import models
class Test(models.Model):
empty_field = models.CharField(max_length=20, blank=True)
def save(self):
if self.pk is not None:
orig = Test.objects.get(pk=self.pk)
if orig.empty_field != self.empty_field and len(self.empty_field) > 0:
mail_managers ...
super(Test, self).save() # Call the "real" save() method
See
http://www.djangoproject.com/documentation/models/save_delete_hooks/
and
Django: When saving, how can you check if a field has changed?