This field is required. Error with ImageField and FileField on Django - python

I am new on Django, I am using Django 1.6.1 and in one of my form I get the next error
This field is required.
I don't understand why I get this error, my form is very basic, so my Model, the statement who launch this error is form.is_valid(), but I don't know why.
Some help would be apreciate.
my views is:
if request.method == 'POST':
form = campoImagenForm(request.POST, request.FILES)
if form.is_valid():
articulo = form.save(commit=False)
articulo.item = item
articulo.atributo = atributo
articulo.save()
return HttpResponseRedirect('/workproject/' + str(project.id))
my Form is:
class campoImagenForm(forms.ModelForm):
class Meta:
model = campoImagen
fields = ('imagen',)
my Model is:
class campoImagen(models.Model):
item = models.ForeignKey(ItemBase)
atributo = models.ForeignKey(TipoItem)
imagen = models.ImageField(verbose_name='Imagen', upload_to='archivos')
version = models.IntegerField()
I don't have a clue of why I get such an error.

At first, in your model make your fields empty and nullable:
class campoImagen(models.Model):
# [...]
imagen = models.ImageField(verbose_name='Imagen', upload_to='archivos', null=True, blank=True)
Then in your model form alter the required parameter of your field:
class campoImagenForm(forms.ModelForm):
class Meta:
model = campoImagen
fields = ('imagen',)
def __init__(self, *args, **kwargs):
super(campoImagenForm, self).__init__(*args, **kwargs)
self.fields['imagen'].required = False
The model part is, however, obligatory. Otherwise you might be getting database inconsistency errors.
Keep in mind that blank and null are different things. They do, however, work well together and should give you what you want.

In forms.py
class campoImagenForm(forms.ModelForm):
imagen = forms.ImageField(verbose_name='Imagen', upload_to='archivos', required = False)
class Meta:
model = campoImagen
fields = ('imagen',)

Related

Django Inline form validation ignored partly filled form

I have got the code from https://github.com/adandan01/mybook, the code is working fine, even when I have updated it to Django 2. It's very simple project for adding a person in a form, and his/her relatives in the inline form. Everything works but when I add a relative name and forget to add his relationship, and submitted the form, unfortunately, that record will not pass the validation but will give no error messages as well. Django will ignore the entire record. For example, the record for Hawra in the image, will not be saved and Django will remove it. For this simple App there are only two fields to be filled (name and relationship), but I'm working on app with 8 fields, and it will be difficult to lose the data. is there any way to make django do the validation in the formset/subform as long as any fields have data and will ask the user to fill all required fields?
models.py:
class Profile(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
created_date = models.DateTimeField(default=timezone.now)
def get_absolute_url(self):
return reverse('profile-update', kwargs={'pk': self.pk})
def __unicode__(self):
return "%s %s" % (self.first_name, self.last_name)
class FamilyMember(models.Model):
profile = models.ForeignKey(Profile, on_delete=models.PROTECT)
name = models.CharField(max_length=100)
relationship = models.CharField(max_length=100)
form.py
class ProfileForm(ModelForm):
class Meta:
model = Profile
exclude = ()
class FamilyMemberForm(ModelForm):
class Meta:
model = FamilyMember
exclude = ()
FamilyMemberFormSet = inlineformset_factory(Profile, FamilyMember,
form=FamilyMemberForm, extra=1)
views.py
class ProfileCreate(CreateView):
model = Profile
fields = ['first_name', 'last_name']
class ProfileFamilyMemberCreate(CreateView):
model = Profile
fields = ['first_name', 'last_name']
success_url = reverse_lazy('profile-list')
def get_context_data(self, **kwargs):
data = super(ProfileFamilyMemberCreate, self).get_context_data(**kwargs)
if self.request.POST:
data['familymembers'] = FamilyMemberFormSet(self.request.POST)
else:
data['familymembers'] = FamilyMemberFormSet()
return data
def form_valid(self, form):
context = self.get_context_data()
familymembers = context['familymembers']
with transaction.atomic():
self.object = form.save()
if familymembers.is_valid():
familymembers.instance = self.object
familymembers.save()
return super(ProfileFamilyMemberCreate, self).form_valid(form)
I found the solution here django inline_formset - form.empty_permitted = False doesn't work
I had to add the following code before if (familymembers.is_valid():...) in the create and update class, so, now Django will show the error if I entered data in the Name field only and will tell me the Relationship field is required.
if familymembers.is_valid() == False:
return self.render_to_response(self.get_context_data(form=form,familymembers=familymembers ))

Django forms ChoiceField not selecting the wanted value

I created a django form (IssueForm) which is meant to be used to register an object which is instance of one of my models (Issue). Following are the model:
model.py
class Issue(models.Model):
TYPE_FIELDS = [
("Math", "Math"),
("Physics", "Physics"),
("Programming", "Programming"),
("Arts", "Arts")
]
issue_text = models.TextField(default="Please insert text")
issue_description = models.TextField(default="Newly created")
issue_deadline = models.DateField()
issue_field = models.CharField(max_length=30, choices=TYPE_FIELDS)
published_by = models.ForeignKey(User, on_delete=models.CASCADE, default=None)
def __str__(self):
return self.issue_description
the form used:
forms.py
class IssueForm(forms.ModelForm):
def __init__(self, user, *args, **kwargs):
self.user = user
super(IssueForm, self).__init__(*args, **kwargs)
TYPE_FIELDS = [
("Math", "Math"),
("Physics", "Physics"),
("Programming", "Programming"),
("Arts", "Arts")
]
issue_text = forms.CharField(widget=forms.Textarea, required=True)
issue_description = forms.CharField(widget=forms.Textarea, required=True)
issue_deadline = forms.DateField(required=True)
issue_fields = forms.ChoiceField(choices=TYPE_FIELDS, required=True)
class Meta:
model = Issue
fields = [
'issue_text',
'issue_description',
'issue_deadline',
'issue_fields'
]
def save(self, commit=True):
issue = super(IssueForm, self).save(commit=False)
issue.issue_text = self.cleaned_data['issue_text']
issue.issue_description = self.cleaned_data['issue_description']
issue.issue_deadline = self.cleaned_data['issue_deadline']
issue.issue_fields = self.cleaned_data['issue_fields']
if commit:
issue.published_by = self.user
issue.save()
return issue
and the related view:
views.py
def create_issue(request):
if ExtendedUser.objects.filter(user=request.user).exists():
if request.method == 'POST':
form = IssueForm(request.user, request.POST)
if form.is_valid():
form.save()
return redirect("/issues")
else:
form = IssueForm(request.user)
args = {'form': form}
return render(request, "issues/create_issue.html", args)
else:
raise Http404("You are not allowed to perform this action")
The forms works for every field in the model, they are all registered right, except for issue_fields. If i try giving a default value to the field in the model, that is the value that is saved on the database, otherwise I just get an empty field. Also I believe the problem comes from the form used, because if i try to create a new issue from the django admin interface it works just fine.
I feel like it's one of those silly mistakes, but I'm just starting with django and python in general and cannot figure it out on my own.
Thank you for your time!!
The field on your model is called issue_field, but you set issue_fields.
Note that also you are doing far more work here than necessary. Your save method completely duplicates what the superclass does already; you should remove all that code except for the setting of the user value.
enter code hereIf you want to use Choices, you haven't to write one more time list of choices in your forms.py file.
This is an example :
#In your models.py file
LIST_CHOICE = (('A','A'), ('B','B'))
class Test(models.Model) :
foo = models.CharField(choices=LIST_CHOICE, verbose_name="foo")
and
#In your form.py file
TestForm(forms.Modelform) :
class Meta :
model = Test
fields = ['foo']
It's not necessary to overwrite LIST_CHOICE in your form file ;)
So, dont touch to your model.py file, but in your form.py file, just write :
class IssueForm(forms.ModelForm):
issue_text = forms.CharField(widget=forms.Textarea)
issue_description = forms.CharField(widget=forms.Textarea)
def __init__(self, user, *args, **kwargs):
self.user = user
super(IssueForm, self).__init__(*args, **kwargs)
class Meta:
model = Issue
fields = [
'issue_text',
'issue_description',
'issue_deadline',
'issue_fields'
]
Don't forget to remove s in issue_field ;)

Setting model data after validation

I'm trying to set data in a FormModel after validation. Example of a use case here is if I want to assign a unique number to a form data set if and only if it passes validation. There's some other information I'm trying to tack on too that isn't available prior to validation. I've tried setting in both the view class and in the clean() method of the ModelForm but can't seem to get it right. Each time I get an exception saying that "tag_id" cannot be null. Obviously I'm not setting it in a way that let's form.save() access the data.
Note that in the example below I'm trying to set tag_id in two places to illustrate what I've tried; obviously only one place would be needed if it worked.
What is the proper way to do this?
Model and FormModel:
class Video(models.Model):
tag_id = models.BigIntegerField()
name = models.CharField(max_length=200)
uploaded = models.DateTimeField()
size = models.BigIntegerField()
video_file = models.FileField(upload_to='documents/%Y/%m/%d')
class Meta:
db_table = 'videos'
class VideoForm(forms.ModelForm):
class Meta:
model = Video
fields = ['name', 'video_file']
def clean(self):
self.data['tag_id'] = 10
return self.cleaned_data
The view class:
class Upload(FormView):
template_name = "account/templates/upload.html"
form_class = VideoForm
success_url = reverse_lazy('account:home')
def form_valid(self, form):
form.cleaned_data['tag_id'] = 10
form.save()
return super().form_valid(form)
Exception on form.save():
IntegrityError at /account/upload/
(1048, "Column 'tag_id' cannot be null")
You should set the attribute of the model instance:
form.instance.tag_id = 10
form.save()

Django:What is wrong with my code?

These are my models:
class war(models.Model):
title = models.CharField(max_length=20)
class option(models.Model):
warval =models.ForeignKey(war)
value = models.CharField(max_length=10)
class warform(ModelForm):
class Meta:
model = war
class option_form(ModelForm):
class Meta:
model = option
exclude = ('warval')
And this is the view which handles creation of option:
def warhandler(request,war_id):
f=modelformset_factory(option,form=option_form)
wobj=get_object_or_404(war,pk=war_id)
if request.method == 'POST':
formset = f(request.POST,queryset=option.objects.filter(warval=wobj))
if formset.is_valid():
formset.save()
return HttpResponse("Saved!check your model")
else:
return render_to_response("formset.html",RequestContext(request,{"set":formset}))
else:
formset = f(queryset=option.objects.filter(warval=wobj))
print(formset)
return render_to_response("formset.html",RequestContext(request,{"set":formset,"war":wobj}))
So when I submit the form to this view,I get the following error:
Exception Type: IntegrityError
Exception Value: hit_option.warval_id may not be NULL
I know what this error is and why it is coming but how can I remove this error?
As you realize, this is because you're not setting the foreign key value anywhere. You probably want to use inlineformset_factory which will take care of setting the FK to the parent war object for you.
Make warval a non-required field with
class option(models.Model):
warval =models.ForeignKey(war, null=True)
value = models.CharField(max_length=10)
or define formset.warval before saving, make a default value...
edit:
read here and here for using subset of fields on a form and saving.

Django required field in model form

I have a form where a couple of fields are coming out as required when I don't want them too. Here is the form from models.py
class CircuitForm(ModelForm):
class Meta:
model = Circuit
exclude = ('lastPaged',)
def __init__(self, *args, **kwargs):
super(CircuitForm, self).__init__(*args, **kwargs)
self.fields['begin'].widget = widgets.AdminSplitDateTime()
self.fields['end'].widget = widgets.AdminSplitDateTime()
In the actual Circuit model, the fields are defined like this:
begin = models.DateTimeField('Start Time', null=True, blank=True)
end = models.DateTimeField('Stop Time', null=True, blank=True)
My views.py for this is here:
def addCircuitForm(request):
if request.method == 'POST':
form = CircuitForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/sla/all')
form = CircuitForm()
return render_to_response('sla/add.html', {'form': form})
What can I do so that the two fields aren't required?
If you don't want to modify blank setting for your fields inside models (doing so will break normal validation in admin site), you can do the following in your Form class:
def __init__(self, *args, **kwargs):
super(CircuitForm, self).__init__(*args, **kwargs)
for key in self.fields:
self.fields[key].required = False
The redefined constructor won't harm any functionality.
If the model field has blank=True, then required is set to False on the form field. Otherwise, required=True
Says so here: http://docs.djangoproject.com/en/dev/topics/forms/modelforms/
Looks like you are doing everything right.
You could check the value of self.fields['end'].required.
Expanding on DataGreed's answer, I created a Mixin that allows you to specify a fields_required variable on the Meta class like this:
class MyForm(RequiredFieldsMixin, ModelForm):
class Meta:
model = MyModel
fields = ['field1', 'field2']
fields_required = ['field1']
Here it is:
class RequiredFieldsMixin():
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
fields_required = getattr(self.Meta, 'fields_required', None)
if fields_required:
for key in self.fields:
if key not in fields_required:
self.fields[key].required = False
It's not an answer, but for anyone else who finds this via Google, one more bit of data: this is happening to me on a Model Form with a DateField. It has required set to False, the model has "null=True, blank=True" and the field in the form shows required=False if I look at it during the clean() method, but it's still saying I need a valid date format. I'm not using any special widget and I get the "Enter a valid date" message even when I explicitly set input_formats=['%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', ''] on the form field.
EDIT: Don't know if it'll help anyone else, but I solved the problem I was having. Our form has some default text in the field (in this case, the word "to" to indicate the field is the end date; the field is called "end_time"). I was specifically looking for the word "to" in the form's clean() method (I'd also tried the clean_end_time() method, but it never got called) and setting the value of the clean_data variable to None as suggested in this Django ticket. However, none of that mattered as (I guess) the model's validation had already puked on the invalid date format of "to" without giving me a chance to intercept it.
This is a bug when using the widgets:
workaround:
Using Django time/date widgets in custom form
or ticket 12303
From the model field documentation,
If you have a model as shown below,
class Article(models.Model):
headline = models.CharField(
max_length=200,
null=True,
blank=True,
help_text='Use puns liberally',
)
content = models.TextField()
You can change the headline's form validation to required=True instead of blank=False as that of the model as defining the field as shown below.
class ArticleForm(ModelForm):
headline = MyFormField(
max_length=200,
required=False,
help_text='Use puns liberally',
)
class Meta:
model = Article
fields = ['headline', 'content']
So answering the question,
class CircuitForm(ModelForm):
begin = forms.DateTimeField(required=False)
end = forms.DateTimeField(required=False)
class Meta:
model = Circuit
exclude = ('lastPaged',)
this makes begin and end to required=False

Categories

Resources