Models.py
class user(AbstractUser):
salary_number = models.IntegerField(unique=True, null=True, blank=True)
Admin.py
def save_model(self, request, obj, form, change):
if obj.salary_number == None:
raise ValidationError("ERROR salary number!")
....
obj.save()
I'm trying to show error for user if they forget to fill salary number, but I got error ValidationError at /admin/information/user/add/. How can I fixed that?
I have a reason to not set salary_number null & blank = False.
The simplest way is probably to make a small ModelForm:
from django import forms
from django.core.exceptions import ValidationError
class UserModelForm(forms.ModelForm):
def clean_salary_number(self):
data = self.cleaned_data['salary_number']
if data is None:
raise ValidationError('ERROR salary number!')
return data
and then plug this in in the ModelAdmin:
from django.contrib import admin
class MyModelAdmin(admin.ModelAdmin):
# …
form = UserModelForm
Related
in django i have inlineadmin with some checkboxes, i want one of them to be ignored from saving if some condition applies.
I tried modifying request.POST['mykey'] or form.data['mykey'] in save_model() of main class with request.POST._mutable = True, but django save all anyway and for form.data it say is immutable.
I know i can set value for obj.mykey but how to save others and ignore one?
Many many thanks to all.
UPDATE
I build few lines of codes to explain better:
models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
admin.py:
from django.contrib import admin
from testB.models import Book, Author
class BookInLine(admin.TabularInline):
model = Book
fields = ['author', 'title']
class AuthorAdmin(admin.ModelAdmin):
inlines = [BookInLine]
def save_model(self, request, obj, form, change):
if request.user.is_superuser:
#do not save first title and do not change existing value
# does not work
# request.POST._mutable = True
# request.POST['id_book_set-0-id']=''
# does not owrk: querydict immutable
# form.data['id_book_set-0-id']=''
pass
super().save_model(request, obj, form, change)
admin.site.register(Author, AuthorAdmin)
Using has_change_permission is not the way, because user should be able to change other title lines, this is a backend check.
Solved! Use save_formset() instead of save_model():
class AuthorAdmin(admin.ModelAdmin):
inlines = [BookInLine]
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for obj in formset.deleted_objects:
obj.delete()
for instance in instances:
if request.user.is_superuser and instance.title != 'my title':
instance.save()
formset.save_m2m()
admin.site.register(Author, AuthorAdmin)
I've been trying creating a user profile form using built-in User of django.contrib.auth.models. Everything is working fine but after filling the fields into the form(which is displaying), I am encountering an INTEGRITY ERROR AT / saying NOT NULL CONSTRAINT failed.
You can see this image using this link to know exactly what the error is showing.
This is my models.py file
from django.db import models
from django.contrib.auth.models import User
from django.core.validators import MaxValueValidator
# Create your models here.
class UserProfileInfo(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE, null=True)
phone_number = models.PositiveIntegerField(validators=
[MaxValueValidator(9999999999)],blank=True)
def __str__(self): #This will print out this model
return self.user.username
This is my forms.py file.
from django import forms
from django.contrib.auth.models import User
from Login_Signup_Form.models import UserProfileInfo
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model=User
fields=('first_name','last_name','username','email','password',)
class UserProfileForm(forms.ModelForm):
class Meta:
model=UserProfileInfo #this is model
fields=('phone_number',)
This is my views.py file.
from django.shortcuts import render
from Login_Signup_Form.forms import UserForm,UserProfileForm
from Login_Signup_Form.models import UserProfileInfo
# Create your views here.
def index(request):
return render(request,'base.html')
def register(request):
registered=False
if request.method == 'POST':
user_form = UserForm(data=request.POST)
user_phone_number=UserProfileForm(data=request.POST)
if user_form.is_valid() and user_phone_number.is_valid():
user=user_form.save()
user.set_password(user.password)
user.save()
phone = user_phone_number.save()
phone.user=user
else:
#Printing the errors
print(user_form.errors,user_phone_number.errors)
else:
user_form = UserForm()
user_phone_number = UserProfileForm()
return render(request, 'base.html',{'user_form':user_form, '
phone_number':user_phone_number})
The error probably comes from an empty phone number in your form. You allow an empty phone_number in your form with blank=True but you don't allow it on the database level, you need to add null=True as well:
phone_number = models.PositiveIntegerField(validators=
[MaxValueValidator(9999999999)], blank=True, null=True)
See this great answer.
With blank=True the field is not required and the form will validate but it will raise the integrity error because null=True is not here. That wouldn't happen with a CharField though, the blank value would be stored as empty string. This only happens because of the PositiveIntegerField.
I want to make changes to the data that is being saved in the admin page.
I've tried save_model. The only difficulty is that I'm using an inlined model as shown below:
# models.py
from django.db import models
class Material(models.Model):
type = models.CharField(max_length=20, primary_key=True)
def __unicode__(self):
return self.type
class Prop(models.Model):
color = models.CharField(max_length=20)
material = models.ForeignKey(Material)
def __unicode__(self):
return "%s_%s" % (self.color, str(self.material))
class Pen(models.Model):
label = models.CharField(max_length=20)
prop = models.ForeignKey(Prop)
def __unicode__(self):
return "%s: %s" % (self.label, str(self.prop))
#admin.py
from django.contrib import admin
from django.conf.urls import url
from .models import Material, Prop, Pen
class PropInlineAdmin(admin.TabularInline):
model = Prop
extra = 1
class MaterialAdmin(admin.ModelAdmin):
inlines = [PropInlineAdmin,]
def save_model(self, request, obj, form, change):
print obj.prop_set.values()
obj.prop_set.color = 'Red'
obj.save()
admin.site.register(Pen)
admin.site.register(Prop)
admin.site.register(Material, MaterialAdmin)
Let's say the user is creating a Material object with black color.
As an example, what I'm trying to do is to change that to be "Black" with first letter capitalized.
One problem is that prop_set does not have the color property until after it is saved.
Another problem is that the change above is not taking effect.
How can I manipulate the inlined values that are being saved?
I got it!
from django.contrib import admin
from django.conf.urls import url
from .models import Material, Prop, Pen
class PropInlineAdmin(admin.TabularInline):
model = Prop
extra = 1
class MaterialAdmin(admin.ModelAdmin):
inlines = [PropInlineAdmin,]
def save_formset(self, request, form, formset, change):
for f in formset.forms:
obj = f.instance
obj.color = obj.color.upper() # or whatever change you'd like
formset.save()
admin.site.register(Pen)
admin.site.register(Prop)
admin.site.register(Material, MaterialAdmin)
Need help for Django model save() method.
i need a redirection back to Person list page or to Person form if some conditions false on my model save() method .
Currently i used a validation error but i am looking for redirection back to list page or form. And if i use a return statement, always get added successfully without saving.
Here i need a redirection instead of "raise ValidationError(u"Enter a valid name").
Thanks in Advance
Justin
#Models.py
from django.db import models
from django.core.exceptions import ValidationError
class Person(models.Model):
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=30, blank=True)
address = models.TextField(max_length=300, blank=True)
def save(self, *args, **kwargs):
if self.first_name == "": #(Some condition check, not a simple field value )
raise ValidationError(u"Enter a valid name")
# Need a redirection back to Django Admin Persons list page or to Add Person Page with error message
# But always showing added successfully, if i use a return or redirection.
else:
super(Person,self).save(*args, **kwargs)
#admin.py
from django.contrib import admin
from testapp.models import Person
from testapp.forms import PersonAdminForm
from django.contrib import messages
# Register your models here.
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name')
#form = PersonAdminForm
#def save_model(self, request, obj, form, change):
# obj.user = request.user
# obj.save()
# messages.add_message(request, messages.INFO, 'Text of message')
admin.site.register(Person, PersonAdmin)
#forms.py
from testapp.models import Person
from django import forms
class PersonAdminForm(forms.ModelForm):
class Meta:
model = Person
Thanks friends for the reply,
I adding my actual model class here. actually i am not using any custom form or custom validation. i used only django admin interface. But i added a custom save() method in model class. And in that save() method i did some conditions on edit and add cases.
Addind data and editing data working with save() method correctly. But condition false case we have no option redirect back to admin model class listing or admin form with error message?
Here in my example can i use any other code instead of raise ValidationError("error test message")?. raise ValidationError gives django error page. if i use redirect or return give "... added successfully" message on no data saving also.
Any chance?
my code ...
class Asset(models.Model):
-----code--------
class Meta:
verbose_name_plural= "Employees Assets"
def save(self, *args, **kwargs):
----- code------
if self.pk is not None:
++++++++++ some code +++++++++++
if self.hardware.hardware_status == 0 and edit_flag == 2:
++++++++++ some code +++++++++++
elif self.hardware.hardware_status == 1 and edit_flag == 1:
++++++++++ some code +++++++++++
elif (self.hardware.hardware_status == 0 or self.hardware.hardware_status == -1) and edit_flag == 1:
++++++++++ some code +++++++++++
elif self.hardware.hardware_status == -1 and edit_flag == 2:
raise ValidationError('Cant modify Hardware, Hardware status is Lost ')
else:
raise ValidationError('Cant modify Hardware, Hardware already assigned to other staff')
self.hardware.save()
super(Asset, self).save(*args, **kwargs)
else:
if self.hardware.hardware_status == 0:
++++++++++ some code +++++++++++
else:
raise ValidationError(u'Can't assign, Hardware not available(Lost/Alreday Assigned) for assignment')
self.hardware.save()
super(Asset, self).save(*args, **kwargs)
def __unicode__(self):
return u'%s Hardware information for %s' % (self.hardware, self.employee)
That is completely the wrong place to do it. Models, deliberately, do not know anything about the request. There's no way to redirect from a save method, and you should not try to implement one. Your view is responsible for running validation and redirecting as approrpriate.
try to custom validation in admin:
forms.py:
class PersonAdminForm(forms.Form):
class Meta:
model = Person
def clean_first_name(self):
if self.first_name == "":value )
raise ValidationError(u"Enter a valid name")
else
return self.clean_first_name["first_name"]
admin.py:
class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name')]
form = PersonAdminForm
check this linkvalidation
The model doesn't do redirection. Which means, overriding your model save method is of little use here. This is a very direct case of form validation, therefore, you must use the below in forms.py
Your view is taking care of the form redirection for you, therefore, just write your code in the form.
I have a very complex situation.
from types import *
from django import forms
from django.db.models import Q
from django.core.exceptions import ValidationError
from schdeules.models import tbmsttemplate,tbmstreviewsched,tbtrnrevdepartments,tbtrnrevdesignations,tbmstappraisalsched,tbtrnappraisalreview,tbmstdepartment,tbmstpart,tbmstsection,tbtrnappraisalquestion
class tbmstappraisalschedForm(forms.ModelForm):
def clean(self):
"""
Override the default clean method to check whether this course has been already inputted.
"""
cleaned_data = super(tbmstappraisalschedForm, self).clean()
depart_id = self.cleaned_data.get('intDeptID')
fromdate = str(self.cleaned_data.get('sdtFromDate'))
todate = str(self.cleaned_data.get('sdtToDate'))
pk=self.instance.pk
res = tbmstappraisalsched.objects.filter(
Q(sdtFromDate__lte=fromdate,sdtToDate__gte=fromdate) | \
Q(sdtFromDate__lte=todate,sdtToDate__gte=todate), ~Q(intAppSchedID=pk),
intDeptID=depart_id.pk,
)
if(res).exists():
raise ValidationError('The slot is present for selected dates and selected department')
else:
res_revs = tbmstreviewsched.objects.filter(
Q(sdtFromDate__lte=fromdate,sdtToDate__gte=fromdate) | \
Q(sdtFromDate__lte=todate,sdtToDate__gte=todate),
tbtrnrevdepartments__intDeptID=depart_id.pk,
)
if(res_revs).exists():
show review scheds such that user can select needed review scheds and save data in two models at once i.e; tbmstappraisalsched,tbtrnappraisalreview
return self.cleaned_data
else:
raise ValidationError('Reviewschedule slots are not present for the selected dates and selected department')
class Meta:
model = tbmstappraisalsched
in above code i have to get review scheds from tbmstreviewsched and show to user such that he can select required review sched and save the data in two models at once in such a way the data has to be saved in tbmstappraisalsched which returns intappschedid(autoincrement value) and then the data has to be saved in tbtrnappraisalreview with new intappschedid and selected review sched ids.
and my admin.py code is
from schdeules.models import tbmsttemplate,tbmstreviewsched,tbtrnrevdepartments,tbtrnrevdesignations,tbmstappraisalsched,tbtrnappraisalreview,tbmstpart,tbmstsection,tbtrnappraisalquestion
from django.core.exceptions import ValidationError
from forms import tbmstappraisalschedForm
class QuestionsInline(admin.StackedInline):
model = tbtrnappraisalquestion
extra = 0
class TemplatesAdmin(admin.ModelAdmin):
readonly_fields = ("intUpdatedBy",)
inlines = [QuestionsInline]
def save_model(self, request, obj, form, change):
obj.intUpdatedBy = request.user.id
obj.save()
class ReviewDesignationInline(admin.StackedInline):
model = tbtrnrevdesignations
extra = 1
class ReviewDepartmentInline(admin.StackedInline):
model = tbtrnrevdepartments
exclude = ['intUpdatedBy']
extra = 1
class ReviewScheduleAdmin(admin.ModelAdmin):
inlines = [ReviewDepartmentInline,ReviewDesignationInline]
exclude = ['intUpdatedBy']
def save_model(self, request, obj, form, change):
obj.intUpdatedBy = request.user.id
obj.save()
class AppraisalScheduleAdmin(admin.ModelAdmin):
exclude = ['intUpdatedBy']
form = tbmstappraisalschedForm
def save_model(self, request, obj, form, change):
obj.intUpdatedBy = request.user.id
obj.save()
class AppraisalReviewAdmin(admin.ModelAdmin):
exclude = ['intUpdatedBy']
def save_model(self, request, obj, form, change):
obj.intUpdatedBy = request.user.id
obj.save()
admin.site.register(tbmstpart)
admin.site.register(tbmstsection)
admin.site.register(tbmsttemplate,TemplatesAdmin)
admin.site.register(tbmstreviewsched,ReviewScheduleAdmin)
admin.site.register(tbmstappraisalsched,AppraisalScheduleAdmin)
admin.site.register(tbtrnappraisalreview,AppraisalReviewAdmin)