im trying to build a simple form with some simple validation rules.
the problem i am having is that fields that are supposed to be required are not causing any validation prompts to appear in the form page when i try to submit the form. As in, when i submit a completely blank form, i get redirected to my specified page instead of having any valifation error promts appear.
The form does not actually any data to the database though, so it looks like the is_valid function is working fine, and if i enter a string where an integer should be, i get my error messages ok. So im wondering if you normally have to do some extra coding to have some 'field required' messages appear. currently i am letting django take care of all the validation, and i am not creating any custom rules. heres some code:
the model
class Advert(models.Model):
user = models.ForeignKey(User)
category = models.ForeignKey('Category')
title = models.CharField(max_length=100, null=False, blank=False)
description = models.TextField()
price = models.IntegerField(null=False, blank=False)
image = models.FileField(upload_to=get_upload_file_name, null=True)
location = models.CharField(max_length=50, null=False, blank=False)
pub_date = models.DateField(auto_now_add=True)
something i want to note is that after adding these to the model, makemigrations did not detect the changes, but i think its assumed that null=False when not explicity specified? and in the ModelForm, required=True is assumed also no?
the form
class AdvertForm(forms.ModelForm):
class Meta:
model = Advert
exclude = ['user']
the view file
def create_advert(request):
if request.POST:
form = AdvertForm(request.POST, request.FILES)
if form.is_valid():
ad = form.save(False)
ad.user = request.user
ad.save()
return HttpResponseRedirect('/adverts/list_adverts/0/')
else:
c = {}
c.update(csrf(request))
c['form'] = AdvertForm()
return render(request, 'create_advert.html', c)
so is_valid is working, the record is not saved, but im getting no error prompts for leave required fields blank.
is there something im missing?
Because you're redirecting even if the form is not valid. Instead, you should stay on the same view and re-render the form. The view should look like this:
def create_advert(request):
if request.POST:
form = AdvertForm(request.POST, request.FILES)
if form.is_valid():
ad = form.save(commit=False)
ad.user = request.user
ad.save()
return HttpResponseRedirect('/adverts/list_adverts/0/')
else:
form = AdvertForm()
return render(request, 'create_advert.html', {'form': form})
(Note there's no point in manually adding the CSRF token, the context processors will do so since you are using the render shortcut.)
Related
I have a form in my django website where the user requests coins and the information is sent to the admin for me to process. I want to automatically get the user who filled the form without them doing it themselves.
Here's the model.py file:
class Requestpayment (models.Model):
username= models.ForeignKey(User, on_delete= models.CASCADE, null=True)
useremail= models.CharField(max_length=100)
accountmail= models.CharField(max_length=100)
accountphonenumber=models.CharField(max_length=15)
coinsrequested=models.ForeignKey(Requestamount, on_delete= models.SET_NULL, null=True)
created= models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.accountmail
the forms.py:
class Requestpaymentform (ModelForm):
class Meta:
model = Requestpayment
fields = '__all__'
and the views.py:
#login_required(login_url='login')
def redeemcoins (request):
form = Requestpaymentform
if request.method =='POST':
form = Requestpaymentform(request.POST)
if form.is_valid():
form = form.save(commit=False)
username = request.user
form.save()
return redirect ('home')
I am pretty sure something is wrong but i don't know what it is (I'm very new at django) anyway the form always shows all the users in the website for the current user to pick who they are.
redeem coins page
I also tried excluding that part of the form but it didn't work it just shows up empty in the admin.
thank you.
You need to assign it to the instance wrapped in the form, so:
#login_required(login_url='login')
def redeemcoins(request):
form = Requestpaymentform()
if request.method == 'POST':
form = Requestpaymentform(request.POST)
if form.is_valid():
form.instance.username = request.user
form.save()
return redirect('home')
# …
It makes more sense however to name this field user than username. In the model you can also make the username field non-editable, such that it does not appear in the form:
from django.conf import settings
class Requestpayment(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL, editable=False, on_delete=models.CASCADE
)
# …
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
When you use username= models.ForeignKey(User, on_delete= models.CASCADE, null=True), Django add a field named user_id in your database which allow django to find User object for Requestpayment.
You can use user_id field to add a User object in Requestpayment.
You don't need to pass username field in your fields list if you want to get user in view.
class Requestpaymentform (ModelForm):
class Meta:
model = Requestpayment
#fields = '__all__'
fields = ['useremail',
'accountmail',
'accountphonenumber',
'coinsrequested',
'created']
Now do this to get user in your view.
#login_required(login_url='login')
def redeemcoins(request):
form = Requestpaymentform()
if request.method == 'POST':
form = Requestpaymentform(request.POST)
if form.is_valid():
requestpayment = form.save(commit=False)
requestpayment.user_id = request.user.id
requestpayment.save()
return redirect('home')
And it's great to use user instead username because it's a User object and not a simple field.
Please for my English !!!
I am very new to Django and try to build a little app for my family with some basic features, one of which is a blog app. In this now I want to store the author of a blog entry in the article model to save it in the database. In the end in the blog entry I want a header that displays the author and the datetime.
I found several approaches to that but some how none of them worked for me so far. The last thing I did now was to try and grab the username in the view with requests.user.get_username() and then populate the field in my form with this string as initial value. Somehow it just doesn't come through, I always get the "field is required" error message...
Here is my blog-create-view.py:
def blog_create_view(request):
user = request.user.get_username()
data = {'author': user}
form = BlogForm(request.POST, data)
if form.is_valid():
form.save()
return HttpResponseRedirect('/blog/blog-create/thanks')
else:
print(form.errors)
form = BlogForm()
context = {
'articleform' : form,
}
return render(request, "blog-create.html", context)
this is the form:
class BlogForm(forms.ModelForm):
title = forms.CharField(label='',
widget=forms.TextInput(attrs={"placeholder":"Titelfeld"}))
text = forms.CharField(
label='',
widget=forms.Textarea(
)
)
author = forms.CharField(widget=forms.HiddenInput())
class Meta:
model = Article
fields = [
'title',
'text',
]
and this is the model:
class Article(models.Model):
title = models.CharField(blank=False,max_length=1000)
text = models.CharField(blank=False, default='Text', max_length=10000)
datetime = models.DateTimeField(auto_now=True)
featured = models.BooleanField(default='False')
author = models.CharField(max_length=1000)
Help is much appreciated! I am getting really frustrated trying to figure this out
if you want to add the author name as current logged in users username you can do it as follows. And remove author in the form
if form.is_valid():
instance = form.save(commit=False)
instance.author = request.user.username
instance.save()
Being said that, it will be better to change the author to foreignkey from django.contrib.auth.models import User and assign to the request.user rather than to the username, so that you can filter the articles by Article.objects.filter(author=request.user)
I have created a Edit Profile form in my Django app but it doesn't save in the database.
This is the profile model:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile', primary_key=True) #Each User is related to only one User Profile
city_search_text = models.CharField(blank=True, max_length=300)#user picks a city from autocomplete and in the view I get or create a City object
city = models.ForeignKey(City, blank=True, null=True, related_name='city') #Each User Profile must be related to one city.
prof_pic = models.ImageField(blank=True, upload_to='profile_pictures')
dob = models.DateField(blank=True, null=True)
def __str__(self):
return self.user.first_name
This is the form:
class EditProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('dob',)#I'm testing to update this field only
def save(self, commit=True):
profile = super(EditProfileForm, self).save(commit=False)
if commit:
profile.save()
return profile
This is the view:
def editprofile(request):
if request.method == 'POST':
edit_profile_form = EditProfileForm(request.POST, instance=request.user)
if edit_profile_form.is_valid():
profile = edit_profile_form.save(commit=False)
profile.save()
if 'next' in request.GET:
return redirect(request.GET['next'])
else:
print (profile_form.errors)
else:
edit_profile_form = EditProfileForm(instance=request.user.profile)
return render(request, 'excurj/editprofile.html', {'edit_profile_form':edit_profile_form,})
After I submit the form it forwards me to index page okay but the values remain the same in the user's profile.
Seems like
if edit_profile_form.is_valid():
isn't getting called at all, and your data is not saved. That means your form has invalid data, and you should check for form errors to detect those.
Also, you are trying to print form errors if the request isn't POST, which makes no sense and won't help you printing form errors. Try using this way;
if edit_profile_form.is_valid():
profile = edit_profile_form.save(commit=False)
profile.save()
else:
print (profile_form.errors)
And check your form for errors.
I figured it out eventually. In the view I should have passed an instance of the profile not the User object. So it needs to be like this:
edit_profile_form = EditProfileForm(request.POST, instance=request.user.*profile*)
How can I use Django sessions to have a user be able to start a form on one page, and move to the next page and have them complete the form?
I have looked into pagination and wizard forms, but I don't get them at all.
When I have one page with a small portion of a model I'm using - in forms - and another page with the rest of the model - forms.py with the rest of the model info - I can use the first form perfectly.
But when I move to the next page, I get an error saying (1048, "Column 'user_id' cannot be null").
My best guess is to use Django sessions to fix this issue. I don't want the user to have to put in their username and password a second time to get this to work. Any ideas?
my models/forms.py:
class Contact(models.Model):
user = models.OneToOneField(User)
subject = models.CharField(max_length=100, blank=True)
sender = models.EmailField(max_length=100, blank=True)
message = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.user.username
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = Contact
fields = ('username', 'password', 'email')
class ContactForm1(forms.Form):
class Meta:
model = Contact
fields = ('subject', 'sender')
class ContactForm2(forms.Form):
message = forms.CharField(widget=forms.Textarea)
class Meta:
model = Contact
fields = ('message',)
views:
def contact(request):
registered = False
if request.method =='POST':
user = UserForm(request.POST)
contact = ContactForm1(request.POST)
if user.is_valid() and contact.is_valid():
user = user.save()
user.set_password(user.password)
user.save()
contact = contact.save(commit=False)
contact.user = user
registered = True
return render(request, 'mysite/contact.html', {'user': user, 'contact': contact, 'registered': registered})
def contact_second(request):
if request.method =='POST':
contact = ContactForm2(request.POST)
if contact.is_valid():
contact = contact.save(commit=False)
contact.save()
return render(request, 'mysite/contact_two.html', {'contact': contact}
I think it's a good idea to use sessions to store the forms because you don't want on each page to store the user input into the database because what if s/he change mind in the 3rd page and s/he wants to discard the registration or whatever it is?
I think is better to store the forms in session until you get in the last page, you ensure that everything is valid and then save the data in the database.
So let's say that the bellow code is in one of the view that will serve the first form/page. You retrieve the data from the POST request and you check if the given data are valid using the form.is_valid(), you then store the form.cleaned_data (which contains the user's validated data) to a session variable.
form = CustomForm(request.POST)
...
if form.is_valid():
request.session['form_data_page_1'] = form.cleaned_data
Note here that you may need to add code to redirect the user to the next page if form.is_valid() is true, something like this:
if form.is_valid():
request.session['form_data_page_1'] = form.cleaned_data
return HttpResponseRedirect(reverse('url-name-of-second-page'))
Then in any other view let's say in the view that is going to serve the second page you can retreive the from data from the first page like this:
first_page_data = request.session['form_data_page_1']
And you can do whatever you want with them as if it was after you executed the form.is_valid() in the first view.
I am trying to build a Create Profile Form after registration and my codes are below.Its already working only for a slight problem,that is,if the name field of Profile model matches one in database,django brings an error message column slug is not unique .I see that slug field is clashing with another,how am I going to edit the below codes to raise a validation error message if name submitted is similiar to one in db?
models.py
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
name= models.CharField(max_length=10)
description=models.TextField()
slug=models.SlugField(unique=True)
user = models.OneToOneField(User, blank=True, null=True)
def __str__(self):
return self.name
views.py
def create_profile(request):
form_class = ProfileForm
if request.method == 'POST':
form = form_class(request.POST)
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.slug = slugify(profile.name)
profile.save()
slug = slugify(profile.name)
return redirect('profile_details', slug=profile.slug)
else:
form = form_class()
return render(request, 'profile/create_profile.html', {'form': form,})
urls.py
urlpatterns=[url(r'^accounts/create_profile/$',views.create_profile,name='registration_create_profile'),]
Thanks
ModelForms actually validate uniqueness as part of the is_valid() checks.
The problem in your case is that you are manually setting the slug after running is_valid(). Because of this you will have to manually validate uniqueness after setting the slug. Something like this would work:
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.slug = slug = slugify(profile.name)
# Check slug uniqueness, keep appending a digit until it fits
n = 1
while Profile.objects.filter(slug=profile.slug).exists():
# Need to find a new slug.
profile.slug = '%s-%d' % (slug, n)
n += 1
profile.save()
return redirect('profile_details', slug=profile.slug)
Note that it is probably better to perform this uniqueness check inside the model's save() method instead of in the view - this just illustrates the logic.
Alternatively you could use a library like django-autoslug which performs this logic for you.