Auto-populating created_by and actionDate field with Django admin site - python

I have a model like this:
class Tour(models.Model):
Name=models.CharField(max_length=100)
Count=models.SmallIntegerField()
ActionDate=models.DateTimeField(editable=False)
ActionUser=models.ForeignKey(User,editable=False)
StatusType=models.ForeignKey(StatusType)
now I wanna auto populate current user in my Tour,so I used this code in admin.py:
def save_model(self, request, obj, form, change):
instance = form.save(commit=False)
instance.ActionUser = request.user
instance.save()
form.save_m2m()
return instance
admin.site.register(Tour,TourAdmin)
it work great and it auto polulate current User in my Tour Table,but now I can't save current date in ActionDate field,I added this code to save_model but it cause error:
self.ActionDate=datetime.datetime.today()
then I tryed to override save in my Tour Model :
def save(self,*args,**kwargs):
self.ActionDate=datetime.datetime.today()
super(Tour, self).save(*args,**kwargs)
but this cause error,too.
what should I do to auto populate both ActionUser and ActionDate?
tnx in advance

Why don't you use auto_now in the field definition?

Related

Setting current user on django vanilla CreateView

I would like to update my model with the currently logged in user. I am using django-vanilla-views. To store a new record I am trying to use CreateView. I don't want to display user on the form, just update it automatically.
Here is my model:
class Measurement(models.Model):
date = models.DateField()
user = models.ForeignKey(User)
And here is my view:
class CreateMeasurement(CreateView):
model = Measurement
fields = ['date']
success_url = reverse_lazy('list_measurements')
def get_form(self, data=None, files=None, **kwargs):
kwargs['user'] = self.request.user
return super(CreateMeasurement, self).get_form(data=data, files=files, **kwargs)
Unfortunately when accessing the view I get the following exception:
TypeError: __init__() got an unexpected keyword argument 'user'
I also tried to create a ModelForm for my model but got exactly the same error. Any ideas what I might be doing wrong?
You don't need to pass the user to the form, so don't override the get_form method. You have already excluded the user field from the model form by setting fields in your view, so you shouldn't need a custom model form either.
It should be enough to override the form_valid method, and set the user when the form is saved.
from django.http import HttpResponseRedirect
class CreateMeasurement(CreateView):
model = Measurement
fields = ['date']
success_url = reverse_lazy('list_measurements')
def form_valid(self, form):
obj = form.save(commit=False)
obj.user = self.request.user
obj.save()
return HttpResponseRedirect(self.get_success_url())

django many to many save admin

I have a model like :
class MyModel(models.Model):
name = models.CharField(max_length=100)
type = models.ManyToManyField(Type, blank=True)
Here from admin I am adding MyModel.
What I want is if the type is not provided while saving then I want the type to be as default like Teacher
type Teacher has not been created. If the type is not provided I want to create the type and assign it if the type is not provided
According to documentation's example, you can override save_model like this:
#admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
def save_related(self, request, form, formsets, change):
if not form.cleaned_data['type']:
type, created = Type.objects.get_or_create(name="Teacher")
form.cleaned_data['type'] = [type]
form.save_m2m()
for formset in formsets:
self.save_formset(request, form, formset, change=change)

Django Admin class to auto-populate user field

I am trying to populate the field 'owner' in the my NoteForm. I read in documentation that I need to use the Admin for that.But i still get this error : note_note.owner_id may not be NULL. Need help. Code:
forms.py:
class NoteForm(forms.ModelForm):
class Meta:
model = Note
fields = ('title','body')
models.py:
class Note(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
cr_date = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, blank=False)
admin.py
class NoteAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj = form.save(commit=False)
obj.owner = request.user
obj.save()
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for instance in instances:
instance.user = request.user
instance.save()
else:
fromset.save_m2m()
admin.site.register(Note, Noteadmin)
views.py:
def create(request):
if request.POST:
form = NoteForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponceRedirect('/notes/all')
else:
form = NoteForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('create_note.html', args)
I do not understand the point of Admin over here. From the code, what I understood is you creating a simple django form for your site and getting the error on form submission. If that's case, the solution is quiet easy. This error is generated because you are try to save a record in your Note model without any reference to User. As there's a db constraint on the foreign key field, it raises the error. Solution is easy, just add owner to the list of fields in the form or modify the save method to assign an owner to the note. If you'll use the first option, the user will be able to see and select the owner. And if you want to pre-populate that particular field, pass initial value to the form.

Current user in django admin

I've tried numerous methods of finding the current user ID in django's administration. I've tried pulling the user ID via SessionKey and request.user (HTTPRequest) to no avail. My latest incarnation is:
def save(self, request, obj, form, change):
if getattr(obj, 'submitter', None) is None:
obj.submitter = request.user
obj.save()
super(AppAdmin, self).save()
in admin.py and
submitter = models.ForeignKey(User, null=True, blank=True, related_name="submitter")
in models.py. I found this elsewhere on stack overflow, but it doesn't seem to work. Any help is appreciated.
Thanks!
From the looks of your snippet, you are trying to save the currently logged in user to your model field in a ModelAdmin
It looks like you meant to override save_model
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_model
class AppAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.submitter = request.user # no need to check for it.
obj.save()

Django InlineModelAdmin - set inline field from request on save (set user field automatically) (save_formset vs save_model)

I have two models, a MainModel and a related InlineModel that i'd like to show as an inline in the admin. This InlineModel can be used for, say, making notes about the model and should track the logged in admin user making changes. While this seems simple (and indeed, the docs show an example for this when the user field is part of the MainModel), I can't seem to grasp it when the field is on the Inline.
To be specific, my goal is:
User edits MainModel
User adds an InlineModel, not filling in the user field
User presses save
Code fills in the user field for newly created InlineModel instances
(Bonus! user field is readonly for existing instances and hidden for new inlines)
And my questions:
Is this correct? Its too bas save_model isn't called for InlineModelAdmin instances
Does doing it this way allow me to save without causing an error? (user is required, validation flags it)
How can I hide the user input field for new inlines, and have it readonly for existing inlines?
Here are my current ideas:
#models.py
class MainModel(models.Model):
some_info = models.IntegerField()
class InlineModel(models.Model):
main = models.ForeignKey(MainModel)
data = models.CharField(max_length=255)
user = models.ForeignKey('auth.User')
#admin.py
class InlineModelInline(admin.TabularInline):
model = InlineModel
fields = ('data', 'user')
#readonly_fields = ('data', 'user') #Bonus question later
class MainModelAdmin(admin.ModelAdmin):
list_display = ('id', 'some_info')
inlines = [InlineModelInline]
#def save_model(self, request, obj, form, change):
#http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_model
#Only called for MainModel, not for any of the inlines
#Otherwise, would be ideal
def save_formset(self, request, form, formset, change):
#http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_formset
#Experimenting showd this is called once per formset (where the formset is a group of inlines)
#See code block at http://code.djangoproject.com/browser/django/tags/releases/1.2.1/django/contrib/admin/options.py#L894
if not isinstance(formset.model, InlineModel):
return super(MainModelAdmin, self).save_formset(request, form, formset, change)
instances = formset.save(commit=False)
for instance in instances:
if not instance.pk:
instance.user = request.user
instance.save()
formset.save_m2m()
I have solved the first half of my question:
def save_formset(self, request, form, formset, change):
if formset.model != InlineModel:
return super(MainModelAdmin, self).save_formset(request, form, formset, change)
instances = formset.save(commit=False)
for instance in instances:
if not instance.pk:
instance.user = request.user
instance.save()
formset.save_m2m()
Now i'm interested in the bonus behavior:
I'm required to select a user when adding a new inline due to validation rules. My best guess is to not include the 'user' field in my InlineModelInline.fields tuple, but then this won't show the author for existing InlineModel instances. (Edit: adding 'user' to readonly_fields works here)
(Edit) How can I make the existing inlines render 'data' as readonly, but still be able to edit it when adding a new inline?
It worked for me. This approach won't allow me to delete Inline items.
def save_formset(self, request, form, formset, change):
for form in formset.forms:
form.instance.user = request.user
formset.save()
To answer the Bonus Question: "How can I make the existing inlines render 'data' as readonly, but still be able to edit it when adding a new inline?":
I use two inlines for the same model:
#admin.py
class InlineModelInline(admin.TabularInline):
model = InlineModel
extra = 1
max_num = 1
#admin.py
class InlineModelExistingInline(admin.TabularInline):
model = InlineModel
readonly_fields = ('data', 'user') #All Fields here except pk
can_delete = False
extra = 0
max_num = 0
class MainModelAdmin(admin.ModelAdmin):
...
inlines = [InlineModelInline, InlineModelExistingInline]
...

Categories

Resources