django form to apply for designed html elements - html

I hve this html file:
<form method='POST'>
{% csrf_token %}
<input name='foo'/>
<button type="submit">submit</button>
</form>
Now, imagine this form has css atributes behind, I just want a form which would configure some inputs. For an example. The field is required, the min length is 10 chars, etc etc.
How could i approach that with Django forms?
is the something like:
from django import forms
class inputform(forms.Form):
input_line = forms.CharField(max_length=20, min_length=10, name='foo')
how would i apply that to vies.py and how to get errors out to html?
Would appreciate your reply.

you can try this.
class inputForm(forms.Form):
input_line = forms.CharField(max_length=30, widget=forms.TextInput(attrs={'class' : 'input-field form-control'}))
def clean(self, *args, **kwargs):
cleaned_data = super(inputForm, self).clean()
my_input = self.cleaned_data.get("input_line")
if not my_input:
raise forms.ValidationError('This field is required')
if len(my_input) < 10:
raise forms.ValidationError('the min length is 10 character')
return cleaned_data
the clean() method is used for validating input from form.

Related

How Do I Properly Submit Two Forms Within One HTML Structure?

I am trying to submit a create view with two forms. The code below works fine if everything is filled out and the form submitted. However if fields are omitted in form2...the form submission fails and the field that was filled out for "form"..."name"....gets reset. I've read you can do multiple forms and I've largely got this working...I just need to figure out how to incorporate form2 into the if_valid().... Here's my view...
def tasklist_detail_view(request, id):
context = {}
context["tasklist"] = TaskList.objects.get(id=id)
context["tasks"] = Task.objects.filter(task_list=id).all()
obj = get_object_or_404(TaskList, id=id)
form = UpdateTaskListForm(request.POST or None, instance=obj)
form2 = TaskForm(request.POST or None)
context["task_list_id"] = id
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("MyTaskLists:my_task_list_main_menu"))
context["form"] = form
context["form2"] = form2
return render(request, "my_task_list_tasklist_detail.html", context)
My HTML...
<form method="POST" enctype="multipart/form-data" id="forms">
{% csrf_token %}
{{ form.name }}
{% include "my_task_list_task_create_form1.html" with tasklist=tasklist %}
<button type="submit" class="button66" name="status" value="Submitted">Submit</button>
</form>
And then in my include HTML...
<div id="task-list-form" hx-target="this" hx-swap="outerHTML">
<button class="button35" hx-post="{% url 'MyTaskLists:task-create' id=task_list_id %}">Save</button>
{{ form2 }}
I did try to do something like....
if form.is_valid() and form2.is_valid():
form.save()
return HttpResponseRedirect(reverse("MyTaskLists:my_task_list_main_menu"))
But then nothing happens...the forms are not accepted at all even if the fields are filled out properly....From what I've read I understand the POST is being applied to both forms....if one is not filled out properly that is why the other errors out? I just can't quite figure out how to process them both properly.
Thanks in advance for any thoughts.
If you want the two forms to behave like one form, and save two objects only if both forms are valid, then the logic is
if form.is_valid() and form2.is_valid():
form.save()
form2.save()
return HttpResponseRedirect(reverse("MyTaskLists:my_task_list_main_menu"))
context["form"] = form
context["form2"] = form2
return render(request, "my_task_list_tasklist_detail.html", context)
If there is any field with the same name in form and form2 you need to use a prefix to remove the ambiguity.
form = UpdateTaskListForm(request.POST or None, instance=obj, prefix='form1')
form2 = TaskForm(request.POST or None, prefix='form2')

Django Forms Set Name Of The Form

How can I set the name of the form with model form ?
This is my model form :
class DetayModelForm(forms.ModelForm):
class Meta:
model = Detay
fields = [ 'yazi', 'tip', 'kullanimAdet']
I know how to set name attribute of a field in a form, there are a lot of examples also.
But I really really couldn't find that how can I set the form's own name , not a field in the form, exactly form's own name attribute; in the ModelForm class.
In html side , I will use this attribute : https://www.w3schools.com/tags/att_form_name.asp
I need to use html form name attribute in my template but, I couldn't find how to add this attribute to the form directly in ModelForm class.
I tried to use init in ModelForm class like that :
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.name = 'DetayFormu'
But in html side, still form doesn't have a name attribute.
And also I know , yes I can set this attribute in my template like that :
<form method="post" name="DetayFormu">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Sign in</button>
</form>
But I really wonder how can I set this attribute in ModelForm class
directly.
How can I do this ?
Just use helper attr to add any new attributes
from crispy_forms.helper import FormHelper
class DetayModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_action = 'url'
super(DetayModelForm, self).__init__(*args, **kwargs)
self.helper.attrs = {'name': 'DetayFormu','autocomplete':'off'}
class Meta:
model = Detay
fields = [ 'yazi', 'tip', 'kullanimAdet']

Invalid form when uploading file in Django

I need to upload file on a Django page, however, after following the official tutorial, I was not able to upload it, it always gives the error "invalid form", and when I tried to print out the error msg of the form, it says "This field is required".
One thing notable is: I have 2 forms on one page, one is this upload form and the other one is for filling out information. Not sure if this is the root cause.
I have tried all solutions provided on the Internet.
Template file:
<form id="uploadForm" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="file" value="upload" name="sourcefile">
<button type="submit">Upload</button>
</form>
Forms.py:
from django import forms
from .models import SourceFile
class UploadFileForm(forms.ModelForm):
class Meta:
model = SourceFile
fields = ('file', 'title')
Models.py:
from django.db import models
# Create your models here.
class SourceFile(models.Model):
title = models.CharField(max_length=255, blank=True)
file = models.FileField(upload_to="media/")
Views.py
def model_form_upload(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
instance = SourceFile(file_field=request.FILES['file'])
instance.save()
return JsonResponse({'error': False, 'message': 'Uploaded Successfully!'})
else:
print("Invalid form")
# return JsonResponse({'error': True, 'errors': form.errors})
else:
form = UploadFileForm()
return render(request, 'source_validation.html', {'form': form})
Your template is wrong. Either use {{ form.as_p }} which should display a file input field because file is a field in your form. (so remove the <input type="file" ...>)
Or don't use it and manually add the <input> fields, but then you must use the correct names. Your form expects a "file" parameter, not a "sourcefile" parameter:
<input type="file" name="file">
Also, you're overcomplicating things in your view (even though your current code will work if you fix your template):
if form.is_valid():
form.save() # this will save your model
return redirect(...)

Django upload form with different models

I am building my first Django app and I need to have an upload page where I would be able to upload multiple files in different upload forms. I need different forms and, I guess, models since depending on the form the file has to be stored in a respective folder in my media root and go through different further transformations. I also want different users have different levels of access to these uploads.
So far I have something like this (I have quite a bit of additional code inside functions in views.py that send data to data frames or other programs but I am not posting those:
models.py
class Upload(models.Model):
document = models.FileField(storage=OverwriteStorage(),upload_to=get_file_path)
upload_date=models.DateTimeField(auto_now_add =True)
class Upload_variables(models.Model):
variables = models.FileField(storage=OverwriteStorage(),upload_to=get_file_path_var)
upload_date=models.DateTimeField(auto_now_add =True)
forms.py
from django import forms
from uploader.models import Upload, Upload_variables
class UploadForm(forms.ModelForm):
class Meta:
model = Upload
fields = ('document',)
class UploadFormVar(forms.ModelForm):
class Meta:
model = Upload_variables
fields = ('variables',)
views.py
def home(request):
if request.method=="POST":
img = UploadForm(request.POST, request.FILES)
if img.is_valid():
img.save()
else:
img=UploadForm()
files=Upload.objects.all()
return render(request,'home.html',{'form':img})
def variables(request):
if request.method == 'POST':
var = UploadFormVar(request.POST, request.FILES)
if var.is_valid():
var.save()
else:
var = UploadFormVar()
files_st = Upload_variables.objects.all()
return render(request, 'home.html', {'form_b': var})
HTML
<form action="#" method="post" enctype="multipart/form-data">
{% csrf_token %} {{form}}
<input type="submit" value="Upload" id="submit_form"/>
</form>
<form action="#" method="post" enctype="multipart/form-data">
{% csrf_token %} {{form_b}}
<input type="submit" value="Upload" id="staging"/>
</form>
So I can see 2 Upload buttons but only one 'choose file'....
Thank you for your help!
Currently you are placing the forms in two separate views. You need to put them in the same view like this:
def home(request):
if request.method=="POST":
var = UploadFormVar(request.POST, request.FILES)
img = UploadForm(request.POST, request.FILES)
if img.is_valid():
img.save()
if var.is_valid():
var.save()
else:
img = UploadForm()
var = UploadFormVar()
files=Upload.objects.all()
return render(request,'home.html',{'form': img, 'form_b': var})

Django 'ManagementForm data is missing or has been tampered with' when saving modelForms with foreign key link

I am rather new to Django so this may be an easy question. I have 2 modelForms where there is a ForeignKey to another. My main goal is to save Indicators with a link to Disease (FK), such that for a particular disease, you can have multiple indicators.
With the code below, I get an error when I hit submit that says 'ManagementForm data is missing or has been tampered with'. Also, the code in views.py does not seem to be validating at the 3rd 'if' statement where there is a return HttpResponseRedirect. However, when I check my database, the values from the form have been written. Any ideas on why the error has been raised? and how to fix it?
My code is below:
models.py
#Table for Disease
class Disease(models.Model):
disease = models.CharField(max_length=300)
#Tables for Indicators
class Indicator(models.Model):
relevantdisease = models.ForeignKey(Disease)
indicator = models.CharField(max_length=300)
forms.py
class DiseaseForm(forms.ModelForm):
class Meta:
model = Disease
class IndicatorForm(forms.ModelForm):
class Meta:
model = Indicator
DiseaseFormSet = inlineformset_factory(Disease,
Indicator,
can_delete=False,
form=DiseaseForm)
views.py
def drui(request):
if request.method == "POST":
indicatorForm = IndicatorForm(request.POST)
if indicatorForm.is_valid():
new_indicator = indicatorForm.save()
diseaseInlineFormSet = DiseaseFormSet(request.POST, request.FILES, instance=new_indicator)
if diseaseInlineFormSet.is_valid():
diseaseInlineFormset.save()
return HttpResponseRedirect('some_url.html')
else:
indicatorForm = IndicatorForm()
diseaseInlineFormSet = DiseaseFormSet()
return render_to_response("drui.html", {'indicatorForm': indicatorForm, 'diseaseInlineFormSet': diseaseInlineFormSet},context_instance=RequestContext(request))
template.html
<form class="disease_form" action="{% url drui %}" method="post">{% csrf_token %}
{{ indicatorForm.as_table }}
<input type="submit" name="submit" value="Submit" class="button">
</form>
You have neither diseaseFormSet nor diseaseFormSet's management form in your template, yet you try to instantiate the formset. Formsets require the hidden management form which tells django how many forms are in the set.
Insert this into your HTML
{{ diseaseFormSet.as_table }}
{{ diseaseFormSet.management_form }}