How to check if `MultiSelectField` is empty or not in Django? - django

In my model I have a field department which is a MultiSelectField and I give the blank=True to that field for some reasons. Now I want to check if user fills the field or not. I have tried to get data from request.POST and gave it a condition using len() function like this if len(field) == 0: but I got an error. Everything works just fine until I added teacher_year = request.POST['teacher_year']
models.py
class CustomUser(AbstractUser):
teacher_department = MultiSelectField(choices=department_choice, blank=True)
forms.py
class TeacherRegisterForm(UserCreationForm):
class Meta(UserCreationForm):
model = CustomUser
fields = ['teacher_year', ...]
views.py
def teacherRegisterView(request):
form = TeacherRegisterForm()
template_name = "attendance/login-register/teacher_register.html"
if request.method == "POST":
form = TeacherRegisterForm(request.POST)
teacher_year = request.POST['teacher_year']
if len(teacher_year) == 0:
messages.warning(request, "Just a remind! You didn't select deparment!")
return redirect('teacher_register')
elif form.is_valid():
form.save()
messages.success(request, "Your account was created! You can log in now.")
return redirect('/')
return render(request, template_name, {'form': form})
the error I got
django.utils.datastructures.MultiValueDictKeyError: 'teacher_year'

MultiValueDict is inherited from normal dict. So you can use get() method with it:
teacher_year = request.POST.get('teacher_year') # if request.POST doesn't contain teacher_year it returns None
if teacher_year:
...

Related

I have some problem with clean method in Django

Here is
my form.py
class DepartamentForm(forms.ModelForm):
class Meta:
model = Department
fields = ['name','company','city', 'special_id','active']
def clean_code(self):
code = self.cleaned_data.get('special_id')
qm = Department.objects.filter(special_id=code)
if qm.exists():
raise forms.ValidationError("Email jest już używany!!" )
return code
my view.py
def dictionary_department_add(request):
current_user = request.user
if request.method == "POST":
form = DepartamentForm(request.POST)
if form.is_valid():
x_form = form.save(commit=False)
x_form.date_add = now.strftime("%Y-%m-%d %H:%M")
x_form.user_add = current_user.username
x_form.save()
return redirect('/dictionaries/dictionary_department/')
else:
return render(request, 'add_department.html',{form': form})
else:
form = DepartamentForm()
return render(request, 'add_department.html', {'form': form})
If I try to add a new position department using this code, the error isn't showed, and submit works for some reason.
I want that before submit form, method check if field special_id exists in database, and if exists than show message in form and stop submit

Conditional checks not working while processing form in Django

I have a ModelForm (EditGoalForm) which I use to edit an instance of a model (Goal). Some conditions must be met before saving form data. I used if statements to check these conditions and it still saves, instead of giving an error - like the if statement does nothing.
I have the following:
models.py
class Goal(models.Model):
goal_name = models.CharField(max_length=250)
goal_status = models.ForeignKey(GoalStatus, on_delete=models.CASCADE, related_name='goal_status')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='scrumy_goal_user')
class GoalStatus(models.Model):
status_name = models.CharField(max_length=250)
forms.py
class EditGoalForm(forms.ModelForm):
goal_status = forms.ModelChoiceField(queryset=GoalStatus.objects.all(), empty_label="Select Goal Status")
class Meta:
model = Goal
fields = ('goal_status',)
views.py
def move_goal(request, goal_id):
goal_instance = Goal.objects.get(goal_id=goal_id)
ERROR_MESSAGE = '''BlahBlahBlah'''
has_perm_cannot_move_to_done = request.user.has_perm('application.cannot_move_to_done')
has_perm_can_move_goal_anywhere = request.user.has_perm('application.can_move_goal_anywhere')
has_perm_can_move_someones_goal_from_verify_to_done = request.user.has_perm('application.can_move_someones_goal_from_verify_to_done')
has_perm_can_move_anybodys_goal_to_any_column = request.user.has_perm('application.can_move_anybodys_goal_to_any_column')
if request.method == 'POST':
form = EditGoalForm(request.POST, instance=goal_instance)
if form.is_valid():
if (has_perm_cannot_move_to_done and form.cleaned_data['goal_status'] != 'Done Goal'):
form.save()
messages.success(request, 'Goal Update Successful')
return redirect('home')
else:
messages.error(request, ERROR_MESSAGE)
else:
form = EditGoalForm(instance=goal_instance)
return render(request, 'move_goal.html', {'form': form})
After if form.is_valid, I checked if the authenticated user has the permission and if the goal_status field was not set to Done Goal. If both are True, then save. However, if I set the goal_status field to Done Goal, it still saves instead of displaying an error message. What could be wrong?
form.cleaned_data['goal_status'] is an instance of GoalStatus. It can never be equal to the string 'Goal Done' unless you either:
Implement __eq__ (and/or) __ne__:
def __eq__(self, other):
return self.status_name == other
Just compare what you really want to compare:
form.cleaned_data['goal_status'].status_name != 'Done Goal'

Override Django ModelForm's Clean_unique method

I am working on a django app where i have a model which have a field with attribute unique=True. I am trying to save data in this model using ModelForm. My model and Model form is like this.
My models.py
class MyModel(models.Model):
field1 = models.CharField(max_length=40, unique=True)
def __unicode__(self):
return self.field1
class DuplicateFields(models.Model):
field1 = models.CharField(max_length=30)
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
def clean_field1(self):
value = self.cleaned_data['field1']
if value :
if MyModel.objects.filter(field1=value).count() > 0:
DuplicateFields.objects.create(field1=value)
return Value
raise forms.ValidationError('this field is required')
**I tried below given code also but it also raise Unique field Exception or error **
def clean_unique(form, field, exclude_initial=True,
value = form.cleaned_data.get(field)
if value:
objs = MyModel.objects.filter(field1=value)
if objs.count() > 0:
DuplicateFields.objects.create(field1=value)
return value
def clean_field1(self):
value=clean_unique(self,'field1')
**My Views.py is **
if request.method=='POST':
form = MyModelForm(request.POST)
if form.is_valid():
cleaned_data = form.cleaned_data
field = cleaned_data['field1']
form.save()
return HttpResponse('form has been saved successfully')
else:
print 'form is invalid'
print form._errors
return render_to_response(template_name, {'form':form}, ci)
else:
return render_to_response(template_name, {'form':form}, ci)
What i want to do is while saving the data or calling form.is_valid() method if i found that the data i am trying to store already exists in model then instead of raising a validation error i want to perform some other logic like will store it in some other model.
But in my view when i am calling 'form.is_valid()` it is returning False. Give me some suggestions. Help will be appreciated
To stop giving validate unique modelform exception what you can do is just override the django ModelForm's validate_unique method. like
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
def validate_unique(self):
exclude = self._get_validation_exclusions()
try:
self.instance.validate_unique(exclude=exclude)
except forms.ValidationError as e:
try:
del e.error_dict['field1'] #if field1 unique validation occurs it will be omitted and form.is_valid() method pass
except:
pass
self._update_errors(e) #if there are other errors in the form those will be returned to views and is_valid() method will fail.
and in your view check
if form.is_valid():
field1=form.cleaned_data['form1']
try:
MyModel.objects.get(field1=field1)
#write your logic here for duplicate entry
except:
MyModel.objects.create(field1=field1)
return render_to_response('template.html')
else:
return render_to_response('template.html')

Django model doesn't relate itself to User through ForeignKey

my question is about modelforms, models and instances. After doing some troubleshooting I think my problem is that either the user field from UserFile doesn't associate itself to the auth.User or that the modelform doesn't pass the instance of auth.User. The error is at the dynamic pathing - file_destination - when I try self.user it can't find the user :/
# Model
class UserFile(models.Model):
user = models.ForeignKey('auth.User', related_name='user_file', primary_key=True, unique=True)
user_file = models.FileField(upload_to=file_destination, null=True)
def __unicode__(self):
return self.user_file.name
# View
def login_index(request):
template = 'loginIndex.html'
context = Context()
if request.user.is_authenticated():
if request.method == 'POST':
form = UserUpload(request.POST, request.FILES, instance=request.user)
context.update({'form': form})
if form.is_valid() and form.is_multipart():
instance = UserFile(user_file=request.FILES.get('user_file'))
instance.save()
else:
form = UserUpload()
context.update({'form': form})
return render(request, template, context)
else:
return render(request, template, context)
# Form
class UserUpload(ModelForm):
user_file = forms.FileField(required=False, widget=forms.ClearableFileInput, label='Upload')
class Meta:
model = UserFile
fields = ['user_file']
def clean_user_file(self):
check_user_file = self.cleaned_data.get('user_file')
if check_user_file:
if check_user_file.size > 5120000:
raise ValueError('File is too big for upload')
return check_user_file
# The problem arises when I submit the instance, which saves the file from the form to upload_to=file_destination
# In file_destination I get an error on self.user.username saying || DoesNotExist at "" UserFile has no user.
# My self.user is an None object.
def file_destination(self, filename):
filename = name_generator()
url = "%s/%s/%s" % (self.user.username, 'uploads' ,filename)
return url
You need to manually set the user field on your UserFile instance:
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instanve.save()
form.save_m2m() # add this if you add m2m relationships to `UserFile`
Also, it is a good idea to redirect after the form handling succeeds:
from django.shortcuts import redirect
# ...
return redirect("view-name")

Django ModelForms: Trying to save a form with a foreign key

Django will just go to the else condition.
here's the code:
models.py
class StakeholderProfile(models.Model):
types = models.ForeignKey(Stakeholder)
name = models.CharField(blank=False, max_length=50)
forms.py
class SPForm(forms.ModelForm):
class Meta:
model = StakeholderProfile
exclude = ('key_contact_person',)
views.py
def profile(request):
stakeholderprofile = StakeholderProfile.objects.all()
if request.method == 'POST':
form = SPForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/profile/')
else:
form = SPForm()
return render_to_response('profile.html',{'form':form,'sp':stakeholderprofile})
I really need your help sir/maam.
You are excluding a field that doesn't exist in StakeHolderProfile.
Also be sure you added method='POST' in your form tag.