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
Related
I try to write testcase for one of my view that use a form.
views.py
def parametrage(request,pk):
parametrage = get_object_or_404(Parametrage, asp_par_cle = pk)
form = ParametrageForm(request, data=request.POST or None, instance = parametrage)
print('form.data',form.data)
if form.is_valid():
parametrage = form.save()
parametrage.opr_nom = request.user.username
parametrage.opr_dat = timezone.now()
form.save()
return redirect('pharmacy:dashboard')
return render(request, 'pharmacy/parametrage.html', {'form': form})
tests.py
class PharmacyParametrageTestCase(TestCase):
def setUp(self):
Parametrage.objects.create(asp_par_loc='TR',asp_par_ale=1,asp_par_con=8)
def test_email_alert(self):
instance = Parametrage.objects.get(asp_par_cle=1)
data = json.dumps({"asp_par_ale":2,})
response = self.client.post(reverse('pharmacy:parametrage', kwargs={'pk':1}),instance=instance, data=data, follow=True, content_type='application/json')
self.assertEqual(response.status_code,200)
self.assertEqual(Parametrage.objects.get(asp_par_cle=1).asp_par_ale,2)
The second assert failed because Parametrage instance is not updated.
form.is_valid() return False and form.errors do not return any error.
form.data is empty
obviously, I never change asp_par_ale value but don't know how to do that in tests.
I try to pass data but doesn't work neither
appreciate some help
i found i guess, when you said, object is not updated, you spoke only about opr_dat and opr_dat ? You called form.save() twice. You have to call isntance save function :
def parametrage(request,pk):
parametrage = get_object_or_404(Parametrage, asp_par_cle = pk)
form = ParametrageForm(request, data=request.POST or None, instance = parametrage)
print('form.data',form.data)
if form.is_valid():
parametrage = form.save(commit=False)
parametrage.opr_nom = request.user.username
parametrage.opr_dat = timezone.now()
parametrage.save()
return redirect('pharmacy:dashboard')
return render(request, 'pharmacy/parametrage.html', {'form': form})
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:
...
Currently, I have a basic FormWizard using ModelForm derived forms for its steps. When the user is done, it saves to the database. Instead of redirecting them back to an empty FormWizard, I'd like to render a new instance of the FormWizard, starting back on the first step, but pre-populate specific fields with the information they entered in the initial form.
Below is the base functionality:
class CustomWizardView(SessionWizardView):
file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'uploads'))
instance = None
def get_form_instance(self, step):
if not self.instance:
self.instance = Post()
return self.instance
def done(self, form_list, **kwargs):
self.instance.user = self.request.user
self.instance.save()
return HttpResponseRedirect('/session-form')
And here is how I did it before I realized how large my form needed to be, and that it required FormWizard:
class PostFormView(TemplateView):
template_name = 'form/form.html'
def get(self, request):
form = TestPostForm()
return render(request, self.template_name, {'form': form})
def post(self, request):
form = TestPostForm(request.POST, request.FILES)
building_floor_data = 0
department_data = ''
if form.is_valid():
post = form.save(commit=False)
post.user = request.user
building_floor_data = form.cleaned_data['building_floor']
department_data = form.cleaned_data['department']
post.save()
# return redirect('form')
form = TestPostForm()
form.fields['building_floor'].initial = building_floor_data
form.fields['department'].initial = department_data
return render(request, self.template_name, {'form': form})
I'm very new to Django, so this may be a very obvious leap to make. I'm just not getting it.
Ended up figuring it out. You have to overwrite the SessionWizardView's get_form_initial function. You're looking to build a dictionary, the initial dict, inside should be the key value pairs of field name and desired value. For me, the way to retrieve the value was getting the users last entered value in the database using a filtered query. Example below:
def get_form_initial(self, step):
initial = {}
user = self.request.user.username
if step == '0':
main_db_query = Post.objects.filter(user__username__exact=user).last()
if main_db_query:
initial = {'site': main_db_query.site,
'floor': main_db_query.floor,
'room_number': main_db_query.room_number,
'department': main_db_query.department}
return self.initial_dict.get(step, initial)
I am following a tutorial and I want to create an edit button for my input but when I click the edit button it returns the form but empty:
forms.py
class RecordingForm(forms.ModelForm):
class Meta:
model = Recording
fields = ['component', 'group', 'failure', 'degree_of_failure']
views.py
def edit_recording(request,slug, recording_id):
recording = get_object_or_404(Recording, pk=recording_id)
if request.method == "POST":
form = RecordingForm(request.POST, instance=recording)
if form.is_valid():
recording = form.save(commit=False)
recording.save()
return redirect('data:detail')
else:
form = RecordingForm(instance=recording)
template = 'data/create_recording.html'
context = {'form': form}
return render(request, template, context)
the form is empty :(
The answer is:
Daniel Roseman is correct about GET
And I changed these two in order to fix the NoReverseMatch
plant = get_object_or_404(Plant, slug=slug)
return redirect('data:detail', slug=plant.slug)
model:
class locations(models.Model):#table
Name = models.CharField(max_length=50,default='Joes quick stop', unique=True)
shop_code = models.CharField(max_length=5,default='AB005',unique=True)
manager = models.ManyToManyField(users)
ast_manager = models.ManyToManyField(users, blank=True, related_name='ast_mng')
sales_manager = models.ManyToManyField(users, blank=True, related_name='sales_mng')
forms:
class locations(models.Model):
Name = models.CharField(max_length=50,default='Joes quick stop', unique=True)
shop_code = models.CharField(max_length=5,default='AB005',unique=True)
manager = models.ManyToManyField(users)
ast_manager = models.ManyToManyField(users, blank=True, related_name='ast_mng')
sales_manager = models.ManyToManyField(users, blank=True, related_name='sales_mng')
class locationsForm(ModelForm):
class Meta:
model = locations
Views
def locations(request):
locations = locations.objects.values().filter(id=request.session['location'])
data=locations[0]
if request.method == 'GET':
if request.session['Manager']== True:
form = locationsForm(initial=data)
context = {'locations': locations, 'form': form}
return render(request, 'locations/locations.html', context)
elif request.method == 'POST':
form=locationsForm(request.POST, instance=data)
if form.is_valid():
cd=form.cleaned_data
form.save()
form = locationsForm()
locations= locations.objects.values().filter(id=request.session['depot'])
context = {'locations': locations}
return render(request, 'locations/locations.html', context)
else:
context = {'locations': locations, 'form': form}
return render(request, 'locations/locations.html', context)
I am trying to display a form that is populated with the relevant data but the user can change and then save/update the form. The above code does a good job of displaying the form with the relevant data but when the user tries to submit it the system tries to save a new record instead of updating the old and fails. I never get past if form.is_valid():
Your problem is that you are converting your locations objects into a list of dictionaries. And then passing a dictionary into the form as instance.
This is happening because you are calling the .values() method on the queryset. That method returns a special ValuesQuerySet which basically looks like a list of dictionaries. Not a list of locations objects.
The instance parameter on the form needs to be an object, not a dictionary. So just simply remove the .values() calls, and it should work. Like this:
def locations(request):
locations = locations.objects.filter(id=request.session['location'])
first_location=locations[0]
if request.method == 'GET':
if request.session['Manager']== True:
form = locationsForm(instance=first_location)
context = {'locations': locations, 'form': form}
return render(request, 'locations/locations.html', context)
elif request.method == 'POST':
form=locationsForm(request.POST, instance=first_location)
if form.is_valid():
cd=form.cleaned_data
form.save()
form = locationsForm()
locations= locations.objects.values().filter(id=request.session['depot'])
context = {'locations': locations}
return render(request, 'locations/locations.html', context)
else:
context = {'locations': locations, 'form': form}
return render(request, 'locations/locations.html', context)