Django - ModelChoiceField validation - django

I have a simple form witch ModelChoiceField. This is a part of my view.py file:
def premium(request, id):
context = {}
try:
site = Site.objects.get(id=id)
except Site.DoesNotExist:
raise Http404("Nie ma takiej strony")
if request.method == 'POST':
premium_form = PremiumForm(request.POST)
if premium_form.is_valid():
# group = Group.objects.get(id=request.POST["kod"])
print('OK')
else:
print('NOT OK')
else:
premium_form = PremiumForm(site)
premium_form.fields['group'].queryset =
premium_form.fields['group'].queryset.exclude(group_name=site.group)
context['site'] = site
context['form'] = premium_form
context['category'] = site.category
context['subcategory'] = site.subcategory
return render(request, 'mainapp/premium.html', context)
This is my form:
class PremiumForm(forms.Form):
def __init__(self, site, *args, **kwargs):
super(PremiumForm, self).__init__(*args, **kwargs)
self.fields['group'].initial = 2
self.fields['group'].empty_label = None
group = forms.ModelChoiceField(
queryset=Group.objects.filter(is_active=True),
help_text="<div id='group'></div>",
label="Some text",
required=False)
My premium.html file:
<form method="post" action="" class="form-horizontal">
{% csrf_token %}
{% bootstrap_form form layout='horizontal'%} <br>
{% bootstrap_button "Submit" size='large' button_type="submit" button_class="btn-primary btn-main-add" %}
</form>
When I press "Submit" button I get "NOT OK". I can't resolve this problem. I don't have any idea how to validate forms.ModelChoiceField. Thanks for any help.

Form should be initialised with kwargs:
premium_form = PremiumForm(site=site)
And inside init:
def __init__(self, *args, **kwargs):
site = kwargs['site']
However, site is not used inside form initialization so you can just remove it and it will solve the issue.

Related

Dynamic particular field on a form in Django?

I have a form which has more than 10 fields. Now i want a particular field, lets say "requirements". This can be more than one requirement, i can deal with that using rich text editor as ask my user to input all the requirements as a ordered list. But for better user experience i am asking this !
I am gonna keep a button under "requirements" field, so that user can click on this button to get a new field. By this, i want all fields to be combined in a dict like
requirements = {'field1','extrafield1'} and etc
How to perform this ? I cant user formset ( as am just adding dynamic field not whole form )
How to deal this with django forms ?
I had a similar problem and came up with following solution (it's based on this answer mainly, but I was able to avoid any javascript):
form contains hidden field to store count of requirement fields; by default form has one such field, but pressing button "add_requirement" increases this count in TestView.post(). On __init__ form adds new fields with proper indexes, if needed, and on save() it goes through all requirement indexes to collect values from respective fields.
TestView.post() works differently for form's two buttons: "add_requirement" just increases fields count and renders form again with added field; default "submit" button saves valid form and redirects to success_url or re-displays invalid one.
forms.py
class SimpleForm(forms.Form):
requirements_count = forms.CharField(widget=forms.HiddenInput(), initial=1)
stable_field = forms.CharField(label='Stable field', required=False)
other_stable_field = forms.CharField(label='Other field', required=False)
requirements_1 = forms.CharField(label='Requirements', required=False)
def __init__(self, *args, **kwargs):
super(SimpleForm, self).__init__(*args, **kwargs)
if self.is_bound:
requirements_count = int(self.data.get('requirements_count', 1))
else:
requirements_count = int(self.initial.get('requirements_count', 1))
if requirements_count > 1:
for index in range(2, requirements_count + 1):
self.fields.update(
{'requirements_' + str(index):
forms.CharField(label='Requirements', required=False)}
)
def save(self, *args, **kwargs):
form = self.cleaned_data
requirements_count = int(form.get('requirements_count', 1))
requirements_list = []
for index in range(1, requirements_count + 1):
requirements = form.get('requirements_' + str(index), '')
if requirements:
requirements_list.append(requirements)
views.py
class TestView(FormView):
template_name = 'testtemplate.html'
form_class = SimpleForm
form = None
success_url = reverse_lazy('home')
def post(self, request, *args, **kwargs):
request_POST = request.POST
requirements_count = int(request_POST.get('requirements_count', 1))
if 'add_requirement' in request_POST:
new_initial = get_initial(request_POST)
new_initial['requirements_count'] = requirements_count + 1
self.form = SimpleForm(initial=new_initial)
context = self.get_context_data(form=self.form)
response = render(request, self.template_name, context)
else:
self.form = SimpleForm(data=request_POST)
context = self.get_context_data(form=self.form)
if self.form.is_valid():
response = self.form_valid(self.form)
else:
response = render(request, self.template_name, context)
return response
def form_valid(self, form):
form.save()
return super().form_valid(self.form)
# helper function
def get_initial(previous_data):
new_initial = {}
for key, value in previous_data.items():
if value != '' and key != 'csrfmiddlewaretoken':
new_initial.update({key: value})
return new_initial
testtemplate.html
<form action="" method="post">
{% csrf_token %}
<table border="1">
{{ form.as_table }}
</table>
<input type="submit">
<input type="submit" name="add_requirement" value="Add another requirement">
{{ form.non_field_errors }}
</form>
I'm in no way Django expert and it may be not the best solution, but it works for me and is relatively simple.

Django ModelForm not saving data even though form.save is executed

I have a website where user have 2 model for their profile, user_detail and user_location. I tried to serve 2 model form on one page with one submit. The problem is when the data from those model form does not save in to the database.
I confirmed that self.request.POST in the post method returns the correct data.
I tried :
Django ModelForm not saving data to database - Does not work
Django ModelForm not saving data - Does not work
The following code if for admins.
Here is my view :
class UpdateProfile(LoginRequiredMixin, UpdateView):
template_name = 'account/user_profile.html'
fields = '__all__'
model = models.UserProfile
user_detail_form_class = forms.UserDetailForm
user_location_form_class = forms.UserLocationForm
def get_context_data(self, **kwargs):
user_profile = get_object_or_404(models.UserProfile, pk=self.kwargs.get(self.pk_url_kwarg))
context = super(UpdateProfile, self).get_context_data(**kwargs)
if 'user_detail_form' not in context:
context['user_detail_form'] = self.user_detail_form_class(instance=user_profile.user_detail)
if 'user_location_form' not in context:
context['user_location_form'] = self.user_location_form_class(instance=user_profile.user_location)
return context
def get(self, request, *args, **kwargs):
super(UpdateProfile, self).get(request, *args, **kwargs)
return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs):
user_detail_form = self.user_detail_form_class(request.POST)
user_location_form = self.user_location_form_class(request.POST)
if user_detail_form.is_valid() and user_location_form.is_valid():
user_detail_form.save()
user_location_form.save()
return redirect(self.get_success_url())
else:
return self.render_to_response(self.get_context_data())
def get_success_url(self):
return reverse('account:admin_client_list')
def dispatch(self, request, *args, **kwargs):
if not request.user.groups.filter(name__in=['Admin']).exists():
return errors.render_403(request)
return super(UpdateProfile, self).dispatch(request, *args, **kwargs)
Here is my template :
{% extends 'base.html' %}
{% block content %}
<form method='POST' action="">{% csrf_token %}
{{ user_detail_form }}
{{ user_location_form }}
<input type="submit" value="Submit">
</form>
{% endblock %}
Here is the form :
class UserDetailForm(forms.ModelForm):
class Meta:
model = models.UserDetail
fields = '__all__'
class UserLocationForm(forms.ModelForm):
class Meta:
model = models.UserLocation
fields = '__all__'
You need to pass the instance parameter when you are creating the ModelForm in the post method. Sample code:
user_profile = get_object_or_404(models.UserProfile, pk=self.kwargs.get(self.pk_url_kwarg))
user_detail_form = self.user_detail_form_class(request.POST, instance=user_profile.user_detail)
user_location_form = self.user_location_form_class(request.POST, instance=user_profile.user_location)

All fields give this field is required error

When I submit this form & all fields are correctly populated, the form.is _valid() returns false & all the fields give : this field is required error, even the CharField!!!
can anybody see what's wrong?
this is my form:
class TemplateConfiguredForm(forms.Form):
"""This form represents the TemplateConfigured Form"""
template = forms.ChoiceField(widget=forms.Select(attrs={'id':'TemplateChoice'}))
logo = forms.ImageField( widget = forms.FileInput(attrs={'id': 'inputLogo'}))
image = forms.ImageField(widget = forms.FileInput(attrs={'id': 'inputImage'}))
message = forms.CharField(widget = forms.Textarea(attrs={'id': 'inputText', 'rows':5, 'cols':25}))
def __init__(self, custom_choices=None, *args, **kwargs):
super(TemplateConfiguredForm, self).__init__(*args, **kwargs)
r = requests.get('http://127.0.0.1:8000/sendMails/api/templates/?format=json')
json = r.json()
custom_choices=( ( template['url'], template['name']) for template in json)
if custom_choices:
self.fields['template'].choices = custom_choices
this my template:
<form id="template_form" method="post" role="form" enctype="multipart/form-data" action="{% url 'create_templates' %}" >
{% csrf_token %}
{{ form.as_p }}
{% buttons %}
<input type="submit" value="Save Template"/>
{% endbuttons %}
</form>
this is my view:
def create_templates(request):
if request.method == 'POST':
form = TemplateConfiguredForm(request.POST, request.FILES)
if form.is_valid():
template_configured = TemplateConfigured()
template_configured.owner = request.user
template_configured.logo = form.cleaned_data["logo"]
template_configured.image = form.cleaned_data["image"]
template_configured.message = form.cleaned_data["message"]
template = form.cleaned_data['template']
template = dict(form.fields['template'].choices)[template]
template_configured.template = Template.objects.get(name = template)
template_configured.save()
saved = True
else:
print form.errors
else:
form = TemplateConfiguredForm()
return render(request, 'sendMails/createTemplates.html', locals())
You've changed the signature of the form so that the first positional argument is custom_choices. Don't do that.
You don't seem to actually be passing that value at all from your view, so you should probably remove it completely. But if you do need it, you should get it from the kwargs dict:
def __init__(self, *args, **kwargs):
custom_choices = kwargs.pop('custom_choices')
super(TemplateConfiguredForm, self).__init__(*args, **kwargs)
The data you pass in your form, here:
form = TemplateConfiguredForm(request.POST, request.FILES)
is captured by the first keyword argument of your signature:
def __init__(self, custom_choices=None, *args, **kwargs):
Remove the custom_choices=None

"post" method condition not working in django form edit and save

After Clicking on a edit method in a form the data of the model gets loaded in the form view but when I click on the save button the value is not saved instead the page is again reloaded with the same values. Saving the New form in database via form works fine
views.py
def sessioncreate(request):
if request.method=="GET":
form=SessionForm();
return render(request,'app/sessions_form.html',{'form':form});
elif request.method=="POST":
form=SessionForm(request.POST);
form.save();
return HttpResponseRedirect('/sessions');
def SessionUpdate(request,pk):
post = get_object_or_404(Sessions, pk=pk)
if request.method == "post":
form = SessionForm(request.POST)
form.save()
return RedirectView('/sessions',pk=form.pk);
else:
form = SessionForm(instance=post)
return render(request,'app/sessions_form.html',{'form':form});
models.py
class Sessions(models.Model):
title=models.CharField(max_length=50)
abstract=models.CharField(max_length=2000)
track=models.ForeignKey(Track)
speaker=models.ForeignKey(Speaker)
status=models.CharField(max_length =1, choices=SESSION_STATUSES)
# returning name in site
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('sessions_detail', kwargs={'pk':self.pk})
class SessionForm(forms.ModelForm):
class Meta:
model=Sessions;
fields=['title','abstract','track','speaker'];
url.py
url(r'^sessions/$',views.SessionList.as_view(),name='sessions_list'),
url(r'^sessions/(?P<pk>[0-9]+)/$',views.SessionDetail.as_view() , name='sessions_details'),
url(r'^sessions/create/$',views.sessioncreate, name='sessions_create'),
url(r'^sessions/update/(?P<pk>[0-9]+)/$',views.SessionUpdate , name='sessions_update'),
url(r'^sessions/delete/(?P<pk>[0-9]+)/$',views.SessionDelete.as_view() , name='sessions_delete'),
session_form.html
{% extends 'layout.html' %}
{% block content %}
<form method="post">
{% csrf_token%}
{{form.as_table}}
<button type="submit">Save</button>
</form>
{% endblock %}
Methods are all caps. You should check if request.method == 'POST'.
Note also that you never check that your form is valid; you should do so by calling if form.is_valid() before the save.
This was my final views.py update file which worked...anything redundant i can remove from that ?
def SessionUpdate(request,pk):
form_class=SessionForm
post = get_object_or_404(Sessions, pk=pk)
form = SessionForm(request.POST)
if request.method == "POST":
if form.is_valid():
form = SessionForm(request.POST, instance=post)
form.save()
return HttpResponseRedirect('/sessions')
else:
form = SessionForm(instance=post)
return render(request,'app/sessions_form.html',{'form':form});

showing the model values of specific user django

I want to show the data of a user which he has entered. This is my model
class IgaiaContent(models.Model):
CONTENT_CHANNELS = (
('YouTube','Youtube'),
('FaceBook','FaceBook'),
('Flickr','Flickr'),
('Instagram','Instagram'),
)
content_name = models.CharField(max_length=255, primary_key=True)
content_type = models.CharField(max_length=255,null=True)
content_source = models.CharField(max_length=255,null=True, choices=CONTENT_CHANNELS)
content_location = models.CharField(max_length=255,null=True)
content_latitude = models.DecimalField(max_digits=20,decimal_places=2,null=True)
content_longitude = models.DecimalField(max_digits=20,decimal_places=2,null=True)
content_embed_code = models.TextField(null=True)
content_description = models.TextField(null=True)
content_tags_user = models.CharField(max_length=255,null=True)
content_time_uploaded = models.DateTimeField(auto_now_add=True)
content_time_updated = models.DateField(null=True)
def __unicode__(self):
return self.content_name
return self.content_type
return self.content_source
return self.content_location
return self.content_latitude
return self.content_longitude
return self.embed_code
return self.description
return self.tags_user
return self.time_uploaded
return self.time_updated
tagging.register(IgaiaContent)
My view
def create_page(request):
if request.method == 'POST':
form = AuthorForm1(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/thanks/')
else:
form = AuthorForm1()
c = {}
c.update(csrf(request))
return render_to_response('portal/form1.htm',{'form':form},context_instance=RequestContext(request))
My form template:
<form method="post" style="height: 553px; width: 594px">
<div class="style12">
{% csrf_token %}
</br>{{ form.as_p }}
</div>
</form>
thats how i am showing my model values
employee_info1 = {
"queryset" : IgaiaContent.objects.all(),
"template_name" : "portal/emp1.html",
}
urlpatterns = patterns('',
(r'^view5/', list_detail.object_list, employee_info1),
)
emp1.html
{% if object_list %}
<table>
<ul>
{% for item in object_list %}
<li>{{item.content_name}}</li>
<li>{{item.content_type}}</li>
<li>{{item.content_source}}</li>
<li>{{item.content_location}}</li>
<li>{{item.content_latitude}}</li>
<li>{{item.content_longitude}}</li>
<li>{{item.content_embed_code}}</li>
<li>{{item.content_description}}</li>
<li>{{item.content_tags_user}}</li>
<li>{{item.content_time_uploaded}}</li>
<li>{{item.content_time_updated}}</li></ul>
{% empty %}
<td colspan="11">No items.</td>
{% endfor %}
</table>
{% endif %}
It is not displaying specific user value means it is displaying me everything.
can anyone tell me how to show specific user values/data?
You need to update your model so that it contains a field to store the user -
from django.contrib.auth.models import User
class IgaiaContent(models.Model):
#...
user = models.ForeignKey(User)
Then you need to create a ModelForm as described here.
class IgaiaContentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
return super(MyModelForm, self).__init__(*args, **kwargs)
def save(self, *args, **kwargs):
kwargs['commit']=False
obj = super(MyModelForm, self).save(*args, **kwargs)
if self.request:
obj.user = self.request.user
obj.save()
class Meta:
model = IgaiaContent
Now update your view so that that you use your new ModelForm
def create_page(request):
if request.method == 'POST':
form = IgaiaContentForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/thanks/')
else:
form = IgaiaContentForm()
#...
Now in your object_list view you do something like -
from django.shortcuts import render_to_response
def object_list(request):
#....
object_list = IgaiaContent.objects.filter(user=request.user)
return render_to_response('object_list_template.html', {'object_list': object_list})