How can i create custom validation in django model forms - django

I want to create a custom form validation in Django forms. I am able to do it normal Django forms but unable to do it in model forms.
my Django form code is
class Post_Article(forms.Form):
title = forms.CharField(label = 'Title',max_length = 100)
abstract = forms.CharField(widget = forms.Textarea, max_length = 300)
body = forms.CharField(widget = forms.Textarea)
image = forms.ImageField(required = False)
hash_tags = forms.CharField(max_length = 50,required = False)
def no_of_hash_tags(self):
cleaned_data = super().no_of_hash_tags()
tags = cleaned_data.get('hash_tags')
if tags:
tags = split(str(tags))
if len(tags) > 5:
raise forms.ValiadationError('Maximum 5 tags are allowed')
the Django model is
class PostsArticle(models.Model):
title = models.CharField(max_length=255)
pub_date = models.DateTimeField(default= timezone.now)
abstract = models.TextField()
body = models.TextField()
image = models.ImageField(upload_to=('images/'),blank=True)
user = models.ForeignKey(User , on_delete = models.CASCADE)
hash_tags = models.CharField(max_length = 50,blank= True)
def _str_(self):
return self.title
def get_absolute_url(self):
return reverse('home')
def summary(self):
return self.absract[:200]
def pub_date_pretty(self):
return self.pub_date.strftime('%b %e %Y')
def link_tags(self):
cleaned_data = super().link_tags
tags = cleaned_data.get['hash_tags']
for tag in tags:
hashing(tag,"PostsArticle")
After some discussion on stack overflow I updates my Django forms to
class Post_Article(forms.ModelForm):
title = forms.CharField(label = 'Title',max_length = 100)
abstract = forms.CharField(widget = forms.Textarea, max_length = 300)
body = forms.CharField(widget = forms.Textarea)
image = forms.ImageField(required = False)
hash_tags = forms.CharField(max_length = 50,required = False)
class Meta:
model = PostsArticle
fields=("title", "abstract", "body", "image", "hash_tags")
def clean(self)
:
cleaned_data=super(Post_Article, self).clean()
tags = cleaned_data.get("hash_tags")
if tags:
tags = split(str(tags))
if len(tags) > 5:
raise forms.ValidationError('Maximum 5 tags are allowed')
return cleaned_data
Now I am unable to get how can I use it with my current class used in views.py
class FeedUpdateView(LoginRequiredMixin, UserPassesTestMixin , UpdateView):
model = FeedPosts
fields= ['body', 'image']
template_name= 'post/edit_Feed.html'
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
Posts = self.get_object()
if self.request.user == Posts.user:
return True
return False
I want to use my Django forms code instead of creating view from my model directly. I want to do it because I want to have some custom validation of a field as given in my forms code
kindly help how can I add form validation to my model

Cleaning a specific field attribute, you would have to call clean_<field_name>.
class Post_ArticleForm(ModelForm):
class Meta:
model = PostsArticle
fields = ['abstract', 'title', 'body', 'image', 'hash_tags']
def clean_hash_tags(self):
cleaned_data = super().clean_hash_tags()
tags = self.cleaned_data.get('hash_tags')
if tags:
tags = split(str(tags))
if len(tags) > 5:
raise forms.ValiadationError('Maximum 5 tags are allowed')
return cleaned_data

You need to override clean method for your ModelForm.
Example:
class Post_Article(forms.ModelForm):
...
hash_tags = forms.CharField(max_length = 50,required = False)
...
class Meta:
model = PostsArticle
fields=("title", "abstract", "body", "image", "hash_tags",)
def clean(self):
cleaned_data=super(Post_Article, self).clean()
tags = cleaned_data.get("hash_tags")
if tags:
tags = split(str(tags))
if len(tags) > 5:
raise forms.ValidationError('Maximum 5 tags are allowed')
return cleaned_data

the clean funtion is not getting invoked
Django forms is
class Post_Article(forms.ModelForm):
title = forms.CharField(label = 'Title',max_length = 100)
abstract = forms.CharField(widget = forms.Textarea, max_length = 300)
body = forms.CharField(widget = forms.Textarea)
image = forms.ImageField(required = False)
hash_tags = forms.CharField(max_length = 50,required = False)
class Meta:
model = PostsArticle
fields=("title", "abstract", "body", "image", "hash_tags")
def clean(self):
print(hello)
cleaned_data=super(Post_Article, self).clean()
tags = cleaned_data.get("hash_tags")
if tags:
tags = split(str(tags))
if len(tags) > 5:
raise forms.ValidationError('Maximum 5 tags are allowed')
return cleaned_data
the clean funtion is not getting invoked
the formview for the same is
class PostCreateView(LoginRequiredMixin,FormView):
form_class = Post_Article
template_name= 'post/post.html'
success_url = '/'
def form_valid(self, form):
form.instance.user = self.request.user
print(form.instance.user)
return super().form_valid(form)
the formview is in the views.py

Related

How to check if one field matches another in Django Form

I'm trying to have my form check if the email field matches the verify_email field in my Django form but it is not working.
My forms.py file:
class SignupForm(ModelForm):
class Meta:
model = FormSubmission
fields ='__all__'
widgets = {'botcatcher': forms.HiddenInput()}
def clean(self):
cleaned_data = super().clean()
email = self.cleaned_data.get('email')
vmail = self.cleaned_data.get('verify_email')
if email != vmail:
raise forms.ValidationError(_("Emails must
match"), code="invalid")
return cleaned_data
My model.py file:
class FormSubmission(models.Model):
first_name = models.CharField(max_length = 30)
last_name = models.CharField(max_length = 30)
email = models.EmailField(unique= False)
verify_email = models.EmailField(unique = False)
text = models.CharField(max_length=250)
botcatcher = models.CharField(max_length= 1, blank=True,
validators=[validators.MaxLengthValidator(0)])
def __str__(self):
return "%s %s"% (self.first_name, self.last_name)
It was my indentation for the def clean function.

django form failed to get values from request

this is views.py
def registerItem(request):
print(request)
try:
print("====111", request.method)
if request.method == 'POST':
print("=========222", request.POST)
form = ItemForm(request.POST)
print("====333", form.is_bound)
print("====444", form)
print("====555", form.cleaned_data['mart_id']())
print("====666", form.is_valid())
if form.is_valid():
mart = MartModel.objects.get(id__exact=form.cleaned_data['mart_id'])
print("====666", mart)
seq = ItemModel.objects.filter(mart_id__exact=mart).values('seq').order_by('-seq')[:1]
if seq:
seq = seq[0]['seq']+1
else:
seq = 1
# form.save()
item = ItemModel(mart_id=mart, seq=seq, name=form.cleaned_data['name'], price=form.cleaned_data['price'], expirationDate=form.cleaned_data['expirationDate'], stockYn=form.cleaned_data['stockYn'])
item.save()
form = ItemForm()
return render(request, 'mobileWeb/admin/register_item.html', {'form':form})
else:
form = ItemForm()
return render(request, 'mobileWeb/admin/register_item.html', {'form':form})
except Exception as ex:
print('====777 : Error occured : ', ex)
request.POST value is correct. you can confirm it by log No.2.
form is bound correctly. you can confirm it by log No.3.
but the form failed to receive values. you can confirm it by log No.4.
this is forms.py
class MartForm(forms.ModelForm):
class Meta:
model = MartModel
fields = ['name', 'address', 'tell', 'phone', 'xPosition', 'yPosition']
class ItemForm(forms.ModelForm):
choicesQueryset = MartModel.objects.all().values('id', 'name')
choicesDic = []
for choice in choicesQueryset:
choicesDic.append((choice['id'], choice['name']))
mart_id = forms.CharField(label='mart', widget=forms.Select(choices=choicesDic))
class Meta:
model = ItemModel
fields = ['mart_id', 'name', 'price', 'expirationDate', 'stockYn']
this is models.py
class MartModel(models.Model):
name = models.CharField(max_length=20, blank=False)
address = models.TextField(blank=False)
tell = models.CharField(blank=True, max_length=12)
phone = models.CharField(blank=True, max_length=11)
imageFileNo = models.CharField(blank=True, max_length=3)
xPosition = models.FloatField(blank=False)
yPosition = models.FloatField(blank=False)
delete_yn = models.CharField(blank=False, default="N", max_length=1)
ins_dttm = models.DateTimeField(blank=False, auto_now_add=True)
ins_user = models.CharField(blank=False, max_length=20, default='ADMIN')
upt_dttm = models.DateTimeField(blank=False, auto_now=True)
upt_user = models.CharField(blank=False, max_length=20, default='ADMIN')
class ItemModel(models.Model):
mart_id = models.ForeignKey('martModel', models.DO_NOTHING)
seq = models.IntegerField(blank=False)
name = models.CharField(blank=False, max_length=20)
price = models.IntegerField(blank=False)
expirationDate = models.DateField(blank=False)
stockYn = models.CharField(blank=False, max_length=1, default='Y')
delete_yn = models.CharField(blank=False, default="N", max_length=1)
ins_dttm = models.DateTimeField(blank=False, auto_now_add=True)
ins_user = models.CharField(blank=False, max_length=20, default='ADMIN')
upt_dttm = models.DateTimeField(blank=False, auto_now=True)
upt_user = models.CharField(blank=False, max_length=20, default='ADMIN')
class Meta:
unique_together = (
('mart_id', 'seq')
)
I know about that it must be a instance not a value when deal with the foreignKey.
but the error occured on binding time.
is this concerend with foreignKey??
================
after advice
no mart name is here.
this is forms.py
class ItemForm(forms.ModelForm):
mart = forms.ModelChoiceField(queryset=MartModel.objects.all(), to_field_name='name')
class Meta:
model = ItemModel
fields = ['mart', 'name', 'price', 'expirationDate', 'stockYn']
this is views.py
from django.shortcuts import render
from .forms import *
# Create your views here.
def index(request):
try:
marts = MartModel.objects.all().values('id', 'name', 'imageFileNo', 'xPosition', 'yPosition')
items = ItemModel.objects.filter(stockYn__exact='Y').values('mart', 'name', 'price', 'expirationDate').order_by('mart_id', 'seq')
return render(request, 'mobileWeb/index/index.html', {'marts':marts, 'items':items})
except Exception as ex:
print('Error occured : ', ex)
def registerMart(request):
try:
if request.method == 'POST' :
form = MartForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'mobileWeb/index/index.html')
else :
form = MartForm()
return render(request, 'mobileWeb/admin/register_mart.html', {'form':form})
except Exception as ex:
print('Error occured : ', ex)
def registerItem(request):
print(request)
try:
print("====111", request.method)
if request.method == 'POST':
print("=========222", request.POST)
form = ItemForm(request.POST)
print("====333", form.is_bound)
print("====444", form)
if form.is_valid():
mart = MartModel.objects.get(id__exact=form.cleaned_data['mart'])
print("====666", mart)
seq = ItemModel.objects.filter(mart__exact=mart).values('seq').order_by('-seq')[:1]
if seq:
seq = seq[0]['seq']+1
else:
seq = 1
# form.save()
item = ItemModel(mart=mart, seq=seq, name=form.cleaned_data['name'], price=form.cleaned_data['price'], expirationDate=form.cleaned_data['expirationDate'], stockYn=form.cleaned_data['stockYn'])
item.save()
form = ItemForm()
return render(request, 'mobileWeb/admin/register_item.html', {'form':form})
else:
form = ItemForm()
return render(request, 'mobileWeb/admin/register_item.html', {'form':form})
except Exception as ex:
print('====777 : Error occured : ', ex)
this is debug variable when make Item Form
this is debug variable about queryset
this is debug variable about 1st member of queryset
ofcourse I did makemigrations, migrate.
I don't know why are you trying to approach like this. ModelForm has very nice way to handle FK, and if you want to show name of the MartModel object, then you can use ModelChoiceField's to_field_name option. For example:
class ItemForm(forms.ModelForm):
mart_id = forms.ModelChoiceField(queryset=MartModel.objects.all(), to_field_name='name')
class Meta:
model = ItemModel
fields = ['mart_id', 'name', 'price', 'expirationDate', 'stockYn']
Also, please change the name of the field mart_id to mart, because underneath django creates a field name mart_id, if you assign the field name to mart.
Finally, in the view, you should not call cleaned_data[...] before calling form.is_valid(). Unless the form is validated, the data won't be available in cleaned_data.
Update
(from comments) Add a __str__ method at the bottom of MartModel class:
class MartModel(models.Model):
...
def __str__(self):
return self.name

How to update specific model fields using Django UpdateView

How can you update certain model fields when a form is posted using Django's UpdateView?
When the user checks complete = True on the form, and submits it, I want their name and date to be saved to this record (fields not visible on the form). The code below isn't throwing any errors, but it also isn't updating the fields requested.
Is it potentially because the view is already updating this record with the form, so they conflict?
view:
class maintenanceEdit(LoginRequiredMixin,UpdateView,):
model = Maintenance
form_class = EditMaintenance
template_name = 'maintenance_edit.html'
login_url = 'login'
success_url = reverse_lazy('equipmentdashboard')
def form_valid(self, form,):
instance = form.save(commit=False)
instance.user = self.request.user
user = instance.user.first_name +" "+instance.user.last_name
completed = form.instance.completed
dateCompleted = form.instance.dateCompleted
if (dateCompleted is None):
if completed == True:
updateMaintenance = Maintenance.objects.get(id = instance.id)
updateMaintenance.dateCompleted = timezone.now()
updateMaintenance.completedBy = user
updateMaintenance.save(update_fields=['dateCompleted','completedBy',])
return super(maintenanceEdit, self).form_valid(form)
model:
class Maintenance(models.Model):
device = models.ForeignKey(get_user_model(),on_delete=models.CASCADE,)
customerTag = models.CharField(max_length=50,)
maintenanceItem = models.CharField(max_length=35,blank=True,)
maintenanceDescrip = models.TextField(max_length=300,blank=True,)
maintenanceNotes = models.TextField(max_length=300,blank=True,)
dateCreated = models.DateTimeField(auto_now_add=True,)
dateDue = models.DateTimeField(auto_now=False, auto_now_add=False, null=True, blank=True, editable=True)
dateCompleted = models.DateTimeField(auto_now=False, auto_now_add=False, null=True, blank=True, editable=True)
completed = models.BooleanField(default = False)
createdBy = models.CharField(max_length=35,blank=True,)
completedBy = models.CharField(max_length=35,blank=True,)
form:
class EditMaintenance(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(EditMaintenance, self).__init__(*args, **kwargs)
self.fields['maintenanceItem'].required = True
self.fields['dateDue'].required = True
class Meta:
model = Maintenance
fields = ['maintenanceItem','dateDue','maintenanceDescrip',
'maintenanceNotes','completed',]
labels = {
'maintenanceItem': ('Maintenance Item'),
'dateDue': ('Maintenance Due'),
'maintenanceDescrip': ('Maintenance Description'),
'maintenanceNotes': ('Maintenance Notes'),
'completed': ('Complete Maintenance'),
}
I also tried, in my view:
def form_valid(self, form,):
instance = form.save(commit=False)
instance.user = self.request.user
user = instance.user.first_name +" "+instance.user.last_name
completed = form.instance.completed
dateCompleted = form.instance.dateCompleted
if (dateCompleted is None):
if completed == True:
Maintenance.objects.filter(id = instance.id).update(dateCompleted = timezone.now(),completedBy = user)
return super(maintenanceEdit, self).form_valid(form)

how to store modelform data to database

I have searched 20-30 posts and I did not find anything useful. I am to store data to database by selecting values from HTML file or form in view. Please tell me how I can achieve this. what code I am missing. Thanks in advance for Help.
view.py
def blog_list(request):
form = AttendanceForm()
if request.method == "POST":
form1 = AttendanceForm(request.POST)
if form1.is_valid:
form1.save()
return render(request, 'blog/blog_list.html',{
'form1':form1,
})
return render(request, 'blog/blog_list.html',{
'form':form,
})
my forms.py
class AttendanceForm(forms.ModelForm):
action = forms.ModelChoiceField(queryset=Action.objects.all(), empty_label="-----------", required=True)
employee = forms.ModelChoiceField(queryset=Employee.objects.all(), empty_label="-----------", required=True)
class Meta:
model = Action
fields = ['employee','action']
my model.py
class Action(models.Model):
action_name = models.CharField(max_length = 100)
def __str__(self):
return self.action_name
class Employee(models.Model):
employee_id = models.AutoField(primary_key = True)
employee_name = models.CharField(max_length = 100)
def __str__(self):
return self.employee_name
class Attendance(models.Model):
u = models.ForeignKey(Employee)
action = models.ForeignKey(Action)
action_time = models.DateTimeField(default=timezone.now())
In Python you need to call methods by using parentheses.
if form.is_valid():
form.save()
It is working fine after these changes in Model:
class Action(models.Model):
action_name = models.CharField(max_length = 100)
def __str__(self):
return self.action_name
class Employee(models.Model):
employee_id = models.AutoField(primary_key = True)
employee_name = models.CharField(max_length = 100)
def __str__(self):
return self.employee_name
class Attendance(models.Model):
employee = models.ForeignKey(Employee)
action = models.ForeignKey(Action)
action_time = models.DateTimeField(default=timezone.now())

form.is_valid method keeps failing

I'm trying to make an editing page for the users to update an object data. However, form.is_valid() keeps failing, I have no idea why.
My model:
class Thread(models.Model):
title = models.CharField(max_length=200)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(User, blank=True, null=True)
body = models.TextField(max_length=10000)
USER_TYPES = (
('INI','Iniciante'),
('INT','Intermediário'),
('AVA','Avançado')
)
user_type = models.CharField(max_length=20, choices = USER_TYPES, default='INI')
category = models.ForeignKey(Category)
orcamento = models.IntegerField(default=0)
slug = models.SlugField(max_length=40, unique=True)
def get_absolute_url(self):
return "/%s/" % self.slug
def __str__(self):
return self.title
def save(self, **kwargs):
slug_str = "%s %s" % (self.category, self.title)
unique_slugify(self, slug_str)
super(Thread, self).save(**kwargs)
My view:
def edit_thread(request, thread_slug):
thread = Thread.objects.get(slug=thread_slug)
if request.method == 'POST':
form = EditThread(request.POST)
if form.is_valid():
thread.title = form.cleaned_data['title']
thread.orcamento = form.cleaned_data['orcamento']
thread.user_type = form.cleaned_data['experiencia']
thread.body = form.cleaned_data['pergunta']
thread.save()
return HttpResponseRedirect('/thread' + thread.get_absolute_url())
else:
data = {'title' : thread.title, 'experiencia':thread.user_type, 'orcamento' : thread.orcamento, 'pergunta': thread.body}
form = EditThread(initial=data)
return render(request, 'edit_thread.html', {
'form': form })
My form:
class EditThread(forms.ModelForm):
title = forms.CharField(label='Título', max_length=200, error_messages=my_default_errors)
orcamento = forms.IntegerField(label='Preço máximo', error_messages=my_default_errors)
experiencia = forms.ChoiceField(label='Você é um usuário...', choices=Thread.USER_TYPES, error_messages=my_default_errors)
pergunta = forms.CharField(label='Pergunta', widget=forms.Textarea, error_messages=my_default_errors)
class Meta:
model = Thread
def __init__(self, *args, **kwargs):
super(EditThread, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.layout = Layout(
Div('title',
'experiencia',
PrependedAppendedText('orcamento', 'R$', ',00', active=True),
'pergunta',
FormActions(
Submit('save', 'Salvar alterações'),
)))
When accessing the page, the form gets pre-populated with the object's data as it should.
Your form should be inherited from the simple forms.Form instead of the forms.ModelForm:
class EditThread(forms.Form):
...
I would suggest you look at django's class based UpdateView. It can generate an update form for you or you could give it a custom ModelForm by overriding the form_class attribute on your view. When using a ModelForm, you also have to specify which model the form is for eg:
class EditThread(forms.ModelForm):
"field definitions ..."
class Meta:
model = Thread
fields = ['my_field_1', 'my_field_2']