I have a problem: when i try to login with information that doesn't get validated, the page is just refreshes, and nothing happens. My goal is to pop up any validation error, but they literally refuse to appear. Could you please check my code, and help me to find out what to do.
template
<form method="post" action="">
{% csrf_token %}
{% bootstrap_form_errors form %}
{% bootstrap_form form %}
<input type="hidden" name="next" value="{{ request.path }}">
<input type="submit" value="Войти">
</form>
form
class LoginForm(forms.ModelForm):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = CustomUser
fields = ('username', 'password')
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username is not None and password:
user = authenticate(username=self.cleaned_data.get('username'), password=self.cleaned_data.get('password'))
if user is None:
raise ValidationError('Неверное имя пользователя или пароль')
if username is None or password is None:
raise ValidationError('Неверные данные')
return self.cleaned_data
view
class LoginView(FormView):
form_class = LoginForm
template_name = 'user/login.html'
def get_success_url(self):
return self.request.META.get('HTTP_REFERER')
def get_context_data(self, **kwargs):
ctx = super().get_context_data()
ctx['form'] = self.form_class
return ctx
def form_valid(self, form):
user = authenticate(username=form.cleaned_data.get('username'),
password=form.cleaned_data.get('password'))
login(self.request, user)
return super().form_valid(form)
def dispatch(self, request, *args, **kwargs):
if self.request.user.is_authenticated():
return redirect('post-list')
return super().dispatch(request, *args, **kwargs)
UPD: It's not bootsrap. When i use the default forms, there are no validationErrors aswell
Your problem is in get_context_data, where you pass the form class, rather than the object instantiated with the post data.
However you should not be overriding that method at all. Even if you fixed this issue, it would only be duplicating what the method already does. Remove the method altogether.
Related
I made a custom user interface for user. I can create the user and edit with no problem except that when in edit form, the previous user doesn't show (nor does the passwor1, but that's ok I guess).
I don't know what I'm missing. It's a silly thing maybe, but I want it to be displayed.
The form:
class UserForm(UserCreationForm):
def __init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)
self.fields['username'].widget = TextInput(attrs = {'class': 'form-control',})
self.fields['password1'].widget = PasswordInput(attrs = {'class': 'form-control',})
self.fields['password2'].widget = PasswordInput(attrs = {'class': 'form-control',})
class Meta:
model = User
fields = ['username', 'password1', 'password2']
The view:
class UserUpdateView(LoginRequiredMixin, PermissionRequiredMixin, SuccessMessageMixin, UpdateView):
model = User
form_class = UserForm
template_name = 'security/user_create.html'
success_message = "El usuario fue editado exitosamente."
permission_required = ('user.can_update')
def get_success_url(self, **kwargs):
context = super(UserUpdateView, self).get_context_data(**kwargs)
person_id = self.kwargs['person_id']
return reverse('people:person-detail', args = [person_id])
def get_context_data(self, **kwargs):
context = super(UserUpdateView, self).get_context_data(**kwargs)
context['person'] = Person.objects.get(pk = self.kwargs['person_id'])
context['form_user'] = self.form_class
return context
The template:
<div class="form-group">
<div class="col-sm-9">
{{ form_user.username }}
</div>
</div>
Thanks!
You shouldn't be defining or using form_user. That's a reference to the form class; the instantiated form, including the initial data, is already passed to the template as form.
UpdateView allows you to just put {{ form }} in the template without defining the form in the view.
For the form to work, you are going to need something like this:
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update" />
</form>
I'm trying to save form data in database by POST request, request successfully done but data not saved in database.
models.py
class Image(models.Model):
user = models.ForeignKey(User, related_name='images')
tagName = models.CharField(max_length=255)
instance = models.CharField(max_length=255)
forms.py
class BuildImageForm(forms.ModelForm):
class Meta:
fields = ('user', 'tagName', 'instance')
model = Image
views.py
class BuildImage(LoginRequiredMixin, CreateView):
form_class = BuildImageForm
model = Image
template_name = 'images/buildImage.html'
success_url = 'user/gui'
def get(self, request, *args, **kwargs):
objectlist = request.user.instances.all()
return render(request, 'images/buildImage.html', {'form': forms.BuildImageForm,
'objectlist': objectlist})
def form_valid(self, form):
instance = form.save()
instance.user = self.request.user
instance.tagName = self.request.tagName
instance.instance = str(self.request.instance_name)
instance.save()
return HttpResponse(status=200)
Update - Edited
I have update my view as:
def post(self, request, *args, **kwargs):
if request.method == 'POST':
form = BuildImageForm(request.POST)
if form.is_valid():
data = form.cleaned_data
form.instance.user = self.request.user
form.instance.tagName = data['tagName']
form.instance.instance = data['instance']
form.save()
else:
print(form.errors)
return HttpResponse(status=200)
Now it prints that error in console:
<ul class="errorlist"><li>instance<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
[23/Jul/2017 04:36:56] "POST /user/images/buildImage/ HTTP/1.1" 200 0
Try changing your view method like this,
def form_valid(self, form):
instance = form.save(commit=False)
instance.user = self.request.user
instance.save()
return HttpResponse(status=200)
you are actually saving the file before adding data
def form_valid(self, form):
instance = form.save(commit=False)
instance.user = self.request.user
instance.tagName = self.request.tagName
instance.instance = str(self.request.instance_name)
instance.save()
return HttpResponse(status=200)
My issue has been solved just by providing a title attribute in my template for instance input field.
Updated code as:
buildImage.html
<form class="form-horizontal" method="POST" id="dockerForm">
{% csrf_token %}
<fieldset>
{% if not objectlist %}
<h3><strong>Sorry!</strong> You couldn't have created any Instance yet! <strong>Let's Create One </strong></h3>
{% else %}
<div class="form-group">
<span class="col-md-1 col-md-offset-2 text-center"><label for="package">Select Your Instance:</label></span>
<div class="col-md-8">
<select class="form-control" name="instance" id="instance_id" title="Select your Instance">
{% for element in objectlist %}
<option value={{ element.name }}> {{ element.name }} </option>
{% endfor %}
</select>
{% endif %}
</div>
</div>
</fieldset>
</form>
forms.py
class BuildImageForm(forms.ModelForm):
class Meta:
fields = ('tagName', 'instance')
model = Image
views.py
def post(self, request, *args, **kwargs):
if request.method == 'POST':
form = BuildImageForm(request.POST)
if form.is_valid():
data = form.cleaned_data
form.instance.user = self.request.user
form.instance.tagName = data['tagName']
form.instance.instance = data['instance']
form.save()
else:
print(form.errors)
return HttpResponseRedirect(reverse('users:gui'))
try to set try and cache for database operation
may be there is some error cached in cache section
Update
try:
"save to database code here"
except Exception as e:
print "error here" print e
I am trying to use django-cripsy-for to customize my forms. But it seems that crispy form is somehow not rendering the submit button and the form action attribute.
Here is template i am rendering the form at.(login.html)
{% extends '_base.html' %}
{% block content %}
{{ login_error_message }}
{% load crispy_forms_tags %}
{% crispy form form.helper %}
{% endblock %}
And here is the view
class LoginView(FormView):
form_class = LoginForm
template_name = "login.html"
success_url = reverse_lazy('home')
def form_valid(self, form):
email = form.cleaned_data['email']
password = form.cleaned_data['password']
referrer = self.request.POST.get('referrer')
user = authenticate(email=email, password=password)
if user is not None:
# if user.is_active:
login(self.request, user)
if referrer !="":
self.success_url = referrer
return super(LoginView, self).form_valid(form)
else:
return render(self.request, "login.html", {'form': form, 'login_error_message': "Invalid username and password."})
def get_context_data(self, **kwargs):
result = super(LoginView, self).get_context_data( **kwargs)
param = self.request.GET.get('next', '')
result.update({'param': param})
return result
And here is my form class
class LoginForm(forms.Form):
def __init__(self, *args, **kwargs):
super(LoginForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_id = 'id-form'
self.helper.form_class = 'form-horizontal'
self.helper.form_method = 'post'
self.helper.form_action = 'login'
email = forms.EmailField(max_length=100)
password = forms.CharField(max_length=100)
What am I missing ? Please help .
Regarding the missing submit button:
You have to add it first!
self.helper.add_input(Submit('submit', 'Submit'))
As can be seen in the 4th listing of the Fundamentals documentation
From the Django Docs (https://docs.djangoproject.com/en/1.8/topics/templates/):
{# this won't be rendered #}
You are outputting your form as a series of Django comments in your template for some reason. Why?
This is rather weird. I've been using Django forms for a long time and can't figure this out.
I have a small form with 1 field for "Quantity". Whenever I submit the form nothing happens and it NEVER get's into my condition to check if the request method is a POST. I have put a pdb in the code as well and it never reaches. I am not sure why. Here is the code.
views.py
def show_product(request, product_slug, template_name='catalog/product.html'):
product_cache_key = request.path
product = cache.get(product_cache_key)
if not product:
product = get_object_or_404(Product, slug=product_slug)
cache.set(product_cache_key, product, settings.CACHE_TIMEOUT)
categories = product.categories.filter(is_active=True)
if request.method == 'POST':
import pdb; pdb.set_trace() # it NEVER hit's this
postdata = request.POST.copy()
form = ProductAddToCartForm(request, postdata)
if form.is_valid():
cart.add_to_cart(request)
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
url = urlresolvers.reverse('show_cart')
return redirect(url)
else:
form = ProductAddToCartForm(request=request)
form.fields['product_slug'].widget.attrs['value'] = product_slug
request.session.set_test_cookie()
context = RequestContext(request, locals())
return render_to_response(template_name, context)
forms.py
class ProductAddToCartForm(forms.Form):
quantity = forms.IntegerField(widget=forms.TextInput(attrs={'class': 'input-quantity', 'placeholder': 'Qty'}), error_messages={'invalid': 'Please enter a valid quantity.'}, min_value=1)
product_slug = forms.CharField(widget=forms.HiddenInput())
def __init__(self, request=None, *args, **kwargs):
self.request = request
super(ProductAddToCartForm, self).__init__(*args, **kwargs)
def clean(self):
if self.request:
if not self.request.session.test_cookie_worked():
raise forms.ValidationError("Sorry, please enable your cookies.")
return self.cleaned_data
template
<form method="post" action=".">
{% csrf_token %}
{{ form.quantity.errors }}
{{ form.quantity }}
<input type="submit" name="submit" value="Add to Cart" class="btn btn-danger" />
{{ form.product_slug }}
</form>
When I click "Add to Cart" the URL goes from http://localhost:8000/product/arm-glove/ to this one http://localhost:8000/product/arm-glove/?csrfmiddlewaretoken=RFG0F1Lg0Eu3GcDhtYwPPCpy9Oct5zCX&quantity=2&submit=Add+to+Cart&product_slug=arm-glove
What am I missing here?
Turns out there was an unclosed tag used for the search which is a GET request so the form's POST was never being seen.
How to exclude form fields if the user is not staff ? I tried this but didn't work , giving an error :
global name 'user' is not defined
class PostForm(ModelForm):
class Meta:
model = Photo
exclude = ['author','featured','published']
def __init__(self, *args, **kwargs):
published = kwargs.pop('published', None)
super(PostForm, self).__init__(*args, **kwargs)
if not user.is_staff:
del self.fields['published']
view.py
def addpost(request):
if request.method == 'POST':
form = PostForm(request.POST,request.FILES,user=request.user)
if form.is_valid():
post = form.save(False)
post.author = request.user
form.save()
return HttpResponseRedirect(reverse('insight.content.views.index', ))
else:
form = PostForm(user=request.user)
ispost = True
return render_to_response('form_add_place.html', {'form': form,'ispost':ispost},context_instance=RequestContext(request))
This can be achieved in the template when rendering the form. It will need to allow null values or have a default value in the model definition or alternatively have its validation overridden:
<form method="post">{% csrf_token %}
{% if request.user.is_staff %}
<p>{{ form.published }}</p>
{% endif %}
<p>{{ form.author }}</p>
<!-- ... your other fields -->
</form>
Similarly you can check for is_superuser or check permissions, see the docs: https://docs.djangoproject.com/en/dev/topics/auth/default/#permissions
You need to pass it the user instance from your request - the model form doesn't have access to it.
my_form = PostForm(user=request.user)
Then, in your __init__:
def __init__(self, *args, **kwargs):
published = kwargs.pop('published', None)
user = kwargs.pop('user', None)
super(PostForm, self).__init__(*args, **kwargs)
if not user.is_staff:
del self.fields['published']