Python noob here trying to learn something very simple.
I'm trying to create a basic form that takes some personal information from a user and saves it into a sqlite3 table with the username of the user as the primary key.
My models.py looks like this:
class userinfo(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key= True,
on_delete=models.CASCADE)
name = models.CharField(max_length = 200, blank = True)
email = models.EmailField(max_length= 300, default = 'Null')
phone = models.CharField(max_length= 10, default = 'Null')
def __unicode__(self):
return self.user
forms.py:
class NewList(forms.ModelForm):
class Meta:
model = userinfo
exclude = {'user'}
views.py
def newlist(request):
if request.method == 'POST':
form = NewList(request.POST)
if form.is_valid():
Event = form.save(commit = False)
Event.save()
return redirect('/home')
else:
form = NewList()
return render(request, 'home/newlist.html', {'form': form})
html:
{% load static %}
<form action="/home/" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
urls.py too, but I don't know how that would help:
urlpatterns = [
url(r'^newlist/$', views.newlist, name='newlist')
]
So when I go to the url, I see the form. I can then fill the form, but when I submit the form, the data doesn't go into the database.
What am I doing wrong here?
Thanks in advance!
I think all you need to do is just save the form if it's valid, probably also add the userinfo as an instance of the form. You are also exluding the user from the form and need to assign it manually.
def newlist(request):
if request.user.is_authenticated():
user = request.user
if request.method == 'POST':
form = NewList(request.POST, instance=user.userinfo)
if form.is_valid():
form.save(commit=false)
form.user = user
form.save()
return redirect('/home')
else:
form = NewList(instance=user.userinfo) # add this if you want it to automatically fill the form with the old data if there is any.
return render(request, 'home/newlist.html', {'form': form})
The rest look like it should work.Except you need to send the post URL back to newlist:
{% load static %}
<form action="/newlist/" method="POST">
{% csrf_token %}
{{ form.as_p }}
</form>
If users are assigned at the creation of the model the first time, you don't need the user save, but since this is saving a users data you want to make sure they are logged in anyway:
def newlist(request):
if request.user.is_authenticated():
user = request.user
if request.method == 'POST':
form = NewList(request.POST, instance=user.userinfo)
if form.is_valid():
form.save()
return redirect('/home')
else:
form = NewList(instance=user.userinfo) # add this if you want it to automatically fill the form with the old data if there is any.
return render(request, 'home/newlist.html', {'form': form})
The instance is the model it is either going to save to, or copying data from. In the: form = NewList(request.POST, instance=user.userinfo) part, it is taking the POST data from the form, and linking that to the specific model entry of user.userinfo, however, it will only save to the database when you call form.save().
The user.userinfo is just so you can get the correct form to save to, as userinfo is a onetoone model to user. Thus making it possible to get it with user.userinfo.
The form = NewList(instance=user.userinfo) part is where it takes the currently logged in user's userinfo and copies into the form before it is rendered, so the old userinfo data will be prefilled into the form in the html. That being if it got the correct userinfo model.
Related
I'm creating a form where if we register it should save data to the database if the form is valid. otherwise, it should raise an error but it doesn't save data to the database, and also some fields are required but if I submit the form it doesn't even raise the error field is required. but if I register it manually on Django admin pannel it works perfectly fine.
here is my model:
class foodlancer(models.Model):
Your_Name = models.CharField(max_length=50)
Kitchen_Name = models.CharField(max_length=50)
Email_Address = models.EmailField(max_length=50)
Street_Address = models.CharField(max_length=50)
City = models.CharField(max_length=5)
phone = PhoneNumberField(null=False, blank=False, unique=True)
def __str__(self):
return f'{self.Your_Name}'
also, I disabled html5 validation
forms.py
class FoodlancerRegistration(forms.ModelForm):
phone = forms.CharField(widget=PhoneNumberPrefixWidget(initial="US"))
class Meta:
model = foodlancer
fields = "__all__"
views.py:
def apply_foodlancer(request):
form = FoodlancerRegistration()
return render(request, 'appy_foodlancer.html', {"form": form})
and finally Django template
<form method="POST" novalidate>
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="cta-btn cta-btn-primary">Submit</button>
</form>
Thank you for your time/help
You don't have any form saving logic in your view.
Try something like this:
def apply_foodlancer(request):
if request.method == 'POST':
form = FoodlancerRegistration(data=request.POST)
if form.is_valid(): # if it's not valid, error messages are shown in the form
form.save()
# redirect to some successpage or so
return HttpResponse("<h1>Success!</h1>")
else:
# make sure to present a new form when called with GET
form = FoodlancerRegistration()
return render(request, 'appy_foodlancer.html', {"form": form})
Also check that the method of your form in your HTML file is post. I'm not sure if POST also works.
Avoid defining fields in a modelform with __all__. It's less secure, as written in the docs
I have been trying to create a view that lets a user create a "profile" but if the user already has a profile then the user is redirected to page where the user can see other people's profiles(in order to see this other people's profiles, the user has to create a profile as a requirement), for doing this proces I have 2 templates, one that has a form to create the profile and other one that displays other user's profile. The error is that every user is redirected to mates-form.html even the ones that already have a profile. So far I think that the error is on the views.py file.
models.py
class Mates(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='usermates')
users_requests = models.ManyToManyField(User, related_name="users_requests")
req_bio = models.CharField(max_length=400)
req_image = models.ImageField(upload_to='requestmates_pics', null=True, blank=True, default=False)
views.py
def matesmain(request):
contents = Mates.objects.all()
if contents == request.user:
context = {
'contents': contents,
'form_mates': MatesForm(),
}
print("nice3")
return render(request, 'mates.html', context)
else:
return render(request, 'mates-form.html')
def mates(request):
if request.method == 'POST':
form_mates = MatesForm(request.POST, request.FILES)
if form_mates.is_valid():
instance = form_mates.save(commit=False)
instance.user = request.user
instance.save()
return redirect('mates-main')
print('succesfully uploded')
else:
form_mates = MatesForm()
print('didnt upload')
context = {
'form_mates': form_mates,
'contents': Mates.objects.all()
}
return render(request, 'mates-form.html', context)
forms.py
class MatesForm(forms.ModelForm):
class Meta:
model = Mates
fields = ('req_bio', 'req_image',)
exclude = ['user']
mates.html
{% if contents %}
{% for content in contents %}
Here is where the user can see other user's profiles
{% endfor %}
{% endif %}
mates-form.html
<form method="post" enctype="multipart/form-data">
{{ form_mates.as_p }}
</form>
If you have any questions or if you need to see more code please let me know in the comments, also I thought of other way for doing these removing the if statements from matesmain view and just using them on the html but that didnt work.
I suppose the user will have only one profile so Instead of ManyToOneRelation i.e. ForeignKey using OneToOneRelation with the User Model would be better.
class Mates(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='usermates')
Now while creating the profile you can check whether the user profile already exists or not like this:
def mates(request):
if Mates.objects.filter(user=request.user).exists():
return redirect('redirect_to_some_view_you_want')
if request.method == 'POST':
form_mates = MatesForm(request.POST, request.FILES)
I want to save a username in database, but it doesn't work. Below is the code. I've created a DB named User and I'm trying to save the user who has been taking by the input from the html I've created. And my database User contains only username field. I used the UserCrationForm as default, and my database appear as polls_user in phpmyadmin. I don't think that's the problem. When I'm trying to save from shell, its working, using the save modelform.
views.py
def register_user(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
q = form.save(commit=False)
q.username = request.username
q.save()
return HttpResponseRedirect('/polls/login')
else:
messages.error(request, "Error")
args = {}
args.update(csrf(request))
args['form'] = UserCreationForm()
return render_to_response('polls/register.html', args, context_instance= RequestContext(request))
register.html
{% block content %}
<h2> Register</h2>
<form action="/polls/login/" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Register">
</form>
{% endblock %}
I cant see where the problem is.
Someone help?
Problem is here: q.username = request.username .It should be:
def register_user(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
q = User() #import your own User model here.
q.username = request.user.username
q.save()
return HttpResponseRedirect('/polls/login')
PS: This will only get you the username of the logged in user.
EDIT:
(from comments)
As you can see, UserCreationForm is a modelform, where in meta class, model is auth.User model(check here). So your data is being saved in auth.User. So override the UserCreationForm like this (If you want to use the UserCreationForm):
#form
class MyUserCreationForm(UserCreationForm):
class Meta:
model = PollUser #Your poll user model
fields = ("username",)
#view
if request.method == 'POST':
form = MyUserCreationForm(request.POST)
if form.is_valid():
....
For this solution, you have to keep in mind that, you need to subclass PollUser model from auth.User model. If you want to use your own PollUser model (not subclassing from auth.User model), then I will suggest you to make a new modelform for PollUser and not use UserCreationForm.
I am getting a valid response back when requesting my form, but I am getting no form fields with the response. It is loading the Submit button only, but no form fields.
Goal: get form fields to load and be able to submit form.
I have a views.py:
def Registration(request):
form = NewUserRegistrationForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
form.save()
return HttpResponseRedirect("/Login/")
else:
form = NewUserRegistrationForm()
return render(request, 'VA/reuse/register.html', {
'form': form
})
forms.py
class NewUserRegistrationForm(UserCreationForm):
username = forms.CharField(required=True,max_length=30,validators=[RegexValidator('^[A-Za-z0-9]{1,30}$','e.g. must be 30 characters or less','Invalid Entry')])
email = forms.EmailField(required=True, max_length=75)
password = forms.PasswordInput()
class Meta:
model = User
fields = ("username", "email", "password1","password2")
def save(self, commit=True):
user = super(NewUserRegistrationForm, self).save(commit=False)
user.username = self.cleaned_data["username"]
user.email = self.cleaned_data["email"]
user.password = self.cleaned_data["password1"]
if commit:
user.save()
return user
a template
<div id="register_bubble">
<form method="post" id="userRegistration">
{% csrf_token %}
{{ NewUserRegForm.as_p }}
<input type="submit" value="Submit" />
</form> <!-- /RegistrationForm (FORM) -->
</div>
What am I doing wrong here? I'm getting no error while in debug mode locally either.
Thank you!
You have two mistakes.
Firstly, you're passing the form class into the template context, not the form instance: the class is NewUserRegistrationForm, but you've instantiated it as NewUserRegForm, and that's what you should be passing as the value in the form context.
To make it more complicated, the key name you've given to that value is also NewUserRegistrationForm - but you're still referring to NewUserRegForm in the template, even though that doesn't exist there.
This would be much more obvious if you used PEP8 compliant names. Instances should be lower case with underscore: eg new_user_registration_form. However, in this case you could just call it form, since there's only one.
return render(request, 'mysite/reuse/register.html', {
'NewUserRegForm': NewUserRegForm
})
or, better:
form = NewUserRegistrationForm(request.POST or None)
...
return render(request, 'mysite/reuse/register.html', {
'form': form
})
You're passing the form instance to the context as 'form', but calling it in the template as {{ NewUserRegForm.as_p }}.
You should use {{ form.as_p }} instead.
The Problem:
I'm tying to post to a view and pass on a value from the template by using a hidden value field and a submit button. The values from the submit button (ie the csrf_token) gets through but the hidden value does not. I've checked from the Wezkrug debugger that request.POST only contains form values and not my 'id' value from the hidden field.
Background:
The button takes you to a form where you can enter a comment. I'm trying to include the review.id that the user is commenting on to make commenting easy. I have the value as 'test' not for test purposes.
My form:
<div>
<form method='POST' action='/add_comment/'>
{% csrf_token %}
<input type="hidden" name='id' value='test'>
<input type="submit" value="Make a Comment">
</form>
</div>
Comment View:
#login_required
def make_comment(request):
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.user = request.user
comment.save()
# render?
return HttpResponseRedirect('/results/', {
'restaurant': get_object_or_404(
Restaurant,
name=request.POST['name'],
address=request.POST['address']
)
})
else:
form = CommentForm()
return render(request, 'stamped/comment.html', {'form': form})
Comment Model:
class Comment(models.Model):
content = models.TextField()
review = models.ForeignKey(Review)
user = models.ForeignKey(User)
date_added = models.DateTimeField(auto_now_add=True)
Comment ModelForm Code:
class CommentForm(ModelForm):
class Meta:
model = Comment
exclude = ('user', 'review',)
I've been trying to follow the tactics in this question, but using the request.session dict is undesirable because Id have to store an id for every review regardless if they're are ever commented on.
What is a more efficient way to pass variables from Template to View in Django?
Any ideas on how to include the hidden value in the POST? Thanks!
views.py
def make_comment(request):
if request.method == 'POST':
if 'prepair_comment' in request.POST:
review = get_object_or_404(Review, pk=request.POST.get('id'))
form = CommentForm({'review': review.id})
return render(request, 'stamped/comment.html', {
'form': form,
})
else: # save the comment
models.py
class CommentForm(ModelForm):
class Meta:
model = Comment
exclude = ('user',)
widgets = {'review': forms.HiddenInput()}
restaurant.html
<form method='POST' action='/add_comment/'>
{% csrf_token %}
<input type='hidden' value='{{ r.id }}' name='id'>
<input type="submit" name='prepair_comment' value="Make a Comment">
</form>
You can access the form with form.cleaned_data. You could also use a if form.is_valid() or if you want to ignore the hidden test value when there is no comment, then you could use a if/else logic to ignore the hidden value if comment is None: logic.
To access the form and only record the test value if comment is not None, the views.py might look like this:
def form_view(request):
if request.method == 'POST'
form = form(request.POST)
if form.is_valid():
comment = form.cleaned_data['comment']
# do something with other fields
if comment is not None:
id = form.cleaned_data['test']
# do something with the hidden 'id' test value from the form
return HttpResponseRedirect('/thanks/')
else:
form = form()
return render(request, 'form.html', {'form': form})
Here are the Django Docs that I would reference for this:
https://docs.djangoproject.com/en/dev/topics/forms/