User doesnt save to database Django - python

views.py
def registerPage(request):
form = UserCreateForm()
if request.method=='POST':
form=UserCreateForm(request.POST)
if form.is_valid():
user=form.save(commit=False)
user.save()
return redirect('home')
return render(request,'base/signup.html',{'form':form})
model.py
class User(AbstractUser):
name = models.CharField(max_length=200,null=True)
email = models.EmailField(unique=True,null=True)
bio=models.TextField(null=True)
avatar = models.ImageField(upload_to='images/',null=True)
USERNAME_FIELD='email'
REQUIRED_FIELDS=['username']
forms.py
class UserCreateForm(UserCreationForm):
class Meta:
model = User
fields = ['name','email','password1','password2','bio','avatar']
htmltemplate
{% include 'main.html' %}
{% block content %}
<div>
<form method="POST">
{% csrf_token %}
{% for field in form %}
{{field.label}}
{{field}}
{% endfor %}
<input type="submit" value="Register" >
</form>
</div>
{% endblock content %}
when ever i try to sign up on html template it doesnt work but if i do it in admin panel it works how can i solve it ?

First of all, it is generally not recommended to mess with the default User model from django. Its better to create a Profile model with a OneToOneField relationship with the user.
Other than that, your issue lies with your form. Since you have avatar which is an ImageField you need to change your form in a way that it can accept FILES.
So what you need to do is change your form like this:
<form method="post" action="" enctype="multipart/form-data" >
When you are writing client-side code:
use multipart/form-data when your form includes any <input type="file"> elements.
In order to make your POST request valid, you need to also receive your FILES on your view. That can be done by changing your code to:
if request.method=='POST':
form=UserCreateForm(request.POST, request.FILES)
if form.is_valid():
....

Related

How to loop through a form and add same form in django if we click add more button and store that in django

What I really want to do is , if a user click on "ADD more" button then a same form repeat itself and the values should store in database, if he/she doesn't click of that button then only the values from first form should be stored.
I am not able to get this, I just created a form , and a table in database for those details but can't loop though the form neither in data.
please help.
This is the form and the button:
This is the model.py code:
from django.db import models
class experience(models.Model):
company_name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
startdate = models.Datefield(default = 01-01-2020)
lastdate = models.DateField(default = 01-01-2020)
profile = models.CharField(max_length=100)
description = models.TextField(max_length = 250)
This is the views.py code:
from django.shortcuts import render, redirect
import requests
from django.contrib.auth.models import User, auth
# Create your views here.
def profile(request):
return render(request, 'profile.html')
Unfortunately, there's no built-in way (as far as I know) in Django to do that without Javascript, but here's an approach:
HTML:
<div class="container" id="experiencesContainer">
<form method='POST' name='experienceForm'>
{{form.as_p}}
</form>
<form method='POST' name='experienceForm'>
{{form.as_p}}
</form>
<button type="button" id="addMoreButton">Add more</button>
<button type="submit">Save Changes</button>
</div>
Django POST method:
# Get a list of submitted forms
experiences = request.POST.getlist('experienceForm')
for experience in experiences:
# this is how you loop throuh every form
experience.get('company_name)
Your javascript something like:
// clonning his childs as well
let cloneForm = document.querySelector('form[name=experienceForm]').cloneNode(true);
document.querySelector('div#experiencesContainer').appendChild(cloneForm);
// see this https://www.w3schools.com/jsref/met_node_clonenode.asp
Of course this code is not tested but I've done this in several projects before, hope it works!
A simple way would be to request the same view from the "Add", just make sure your form view saves the data when request method is POST.
<form action="{% url 'your-form-url' %}" method="GET">
{% csrf_token %}
<input type="submit" value="Add">
</form>
one other way to repeat forms would be using formsets. Formsets allow you to repeat the same form 'extra' times. Check out the documentation for more about this.
def repeat_form(request):
ExpFormSet = formset_factory(ExperienceForm, extra=3)
#extra defines the no. of forms you want to display
if request.method == 'POST':
formset = ExpFormSet(request.POST, request.FILES)
if formset.is_valid():
# do something with the formset.cleaned_data
#loop through each form in the formser
for form in formset.cleaned_data:
obj = form.save()
else:
formset = ExpFormSet()
return render(request, 'exp_form.html', {'formset': formset})
The corresponding template should be:-
<form method="post">
{{ formset.management_form }}
{% for form in formset %}
{{ form.as_p }}
{% endfor %}
</form>
Make sure you add form.management_form. Using the combination of the above might solve your problem of taking and saving several inputs.

Creating Dropdown from Model in Django

I am looking to create a dropdown in a template where the values of the dropdown come from a field (reference) within my Orders model in models.py. I understand creating a dropdown where the values are set statically, but since I am looking to populate with values stored in the DB, I'm unsure of where to start.
I've created the model and attempted playing around with views.py, forms.py and templates. I am able to get each of the order numbers to display but not in a dropdown and I am struggling with how to write my template.
models.py
from django.db import models
class Orders(models.Model):
reference = models.CharField(max_length=50, blank=False)
ultimate_consignee = models.CharField(max_length=500)
ship_to = models.CharField(max_length=500)
def _str_(self):
return self.reference
forms.py
from django import forms
from .models import *
def references():
list_of_references = []
querySet = Orders.objects.all()
for orders in querySet:
list_of_references.append(orders.reference)
return list_of_references
class DropDownMenuReferences(forms.Form):
reference = forms.ChoiceField(choices=[(x) for x in references()])
views.py
def reference_view(request):
if request.method == "POST":
form = references(request.POST)
if form.is_valid():
form.save()
return redirect('index')
else:
form = references()
return render(request, 'proforma_select.html', {'form': form})
proforma_select.html
{% extends 'base.html' %}
{% block body %}
<div class="container">
<form method="POST">
<br>
{% for field in form %}
<div class="form-group row">
<label for="id_{{ field.name }}" class="col-2 col-form-label"> {{ field.label }}</label>
<div class="col-10">
{{ field }}
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-primary" name="button">Add Order</button>
</form>
</div>
{% endblock %}
All I get when I render the template is each of the reference #s listed out but NOT within a dropdown. This leads me to believe my problem is mainly with the template, but I'm unsure as I am new to using Django.
Are you using Materialize CSS? If yes, then Django forms renders dropdowns differently from how Materialize expects them. So you will want to override the form widget. You can do something like so:
forms.py:
class DropDownMenuReferences(forms.Form):
reference = forms.ChoiceField(choices=[(x) for x in references()],
widget=forms.Select(choices=[(x) for x in references()], attrs={'class':
'browser-default'}))
This overrides the parameters passed into html. You can also pass any name tags in the attrs too.
The issue:
https://github.com/Dogfalo/materialize/issues/4904

Django unable delete form with data shown

i have created a delete function for my forms but it can only delete if i did not display out my information.
However if i try to display the information out on the delete page, the delete function wouldn't work.
i think because when i display the information out, the form isn't valid, hence unable to delete the object.
My views.py
def servicing_entry_delete(request, serv_entry_id):
delete_object = get_object_or_404(serv_entry, id=serv_entry_id)
if request.method == 'POST':
form = Delete_Flying_form(request.POST, instance=delete_object)
if form.is_valid(): # checks CSRF
delete_object.delete()
return HttpResponseRedirect(reversed('hello:servicing_entry')) # wherever to go after deleting
else:
form = Delete_Flying_form(instance=delete_object)
return render(request, 'hello/servicing_entry_delete.html', {'form':form})
My forms.py
class Delete_Flying_form(forms.ModelForm):
class Meta:
model = serv_entry
fields = ('Servicing_Type', 'Time', 'Date','Ic_Clear_Name','Ic_Clear_Time','Ic_Clear_Date')
My deleteconfirmation.html
{% extends 'hello/base.html' %}
{% block content %}
<h1>Delete Servicing Entry</h1>
<p>Are you sure you want to delete this Entry: </p>
{{ form }}
<form action="" method="POST">
{% csrf_token %}
<input type="submit" action="" value="Yes, delete this Entry." />
</form>
{% endblock %}
Without the {{ form }}, i am able to delete the object smoothly but not being able to display any information.
However if i try to display, like this
is there anyway if i could display this few fields and still delete successfully?
My django version is 1.11
with python 2.7.5
Much appreciate!

Inline formset not rendering form field

I have models:
class MediaInfo(models.Model):
title = models.CharField(max_length=50,blank=True)
description = models.CharField(max_length=255,blank=True)
media_file = models.FileField(upload_to=get_upload_file_name)
def __unicode__(self):
return self.title
class Media(models.Model):
media_files = models.ForeignKey(MediaInfo) # I want ManyToManyField but it gives error saying no ForeignKey relation
Here I used Inline Formset to select multiple file.
What I wanted was I wanted a browser button on template and when I click that I could select multiple file or images with all those title and description informations.
For this I wrote a view:
def MediaAddView(request):
MediaInlineFormset = inlineformset_factory(MediaInfo, Media)
if request.method == "POST":
formset = MediaInlineFormset(request.POST, request.FILES)
if formset.is_valid():
formset.save()
return HttpResponseRedirect("someurl")
else:
return render_to_response("media_add.html", {"formset":formset,})
else:
formset = MediaInlineFormset()
return render_to_response("media_add.html", {"formset":formset,})
and my template media_add.html
{% block content %}
<form method="post" action="" enctype="multipart/form-data">{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{form.id}}
<ul>
<li>{{form.media_file}}</li>
</ul>
{% endfor %}
<input type="submit" value="Submit" />
</form>
{% endblock %}
When I do this in my template I see nothing just 3 dots of list (li).
Like I said I wanted a browse button and when I click it I wanted to select and upload multiple files.
Whats wrong in here ? Can anyone guide me ?

Django - importing form into template outside app

I have an app with name account which contain all the models, views, and forms to be used in registering and signing in users.
I have a template that is located outside the app folder that suppose to contain all the forms in account app.
I am having problem trying to get the forms showing in the template.
Can someone help me?
Here are some snippet of codes:
accounts/forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
# Safe from injection, etc.
class UserRegistrationForm(UserCreationForm):
email = forms.EmailField(required = True)
first_name = forms.CharField(max_length=30, required=True)
last_name = forms.CharField(max_length=30, required=True)
class Meta:
model = User
fields = ('username','email','password1', 'password2','first_name','last_name')
def save(self, commit=True):
user = super(UserRegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
if commit:
user.save()
return user
accounts/view.py
from forms import UserRegistrationForm
def register_user(request):
if request.POST:
form = UserRegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
else:
form = UserRegistrationForm()
args = {}
# prevent forgery
args.update(csrf(request))
# empty form
args['form'] = form
return render_to_response('signup.html', args)
def register_success(request):
return render_to_response('signup_success.html')
and finally the template, which is not in account folder. It's in the same folder as settings.py
signup.html
{% extends "base.html" %}
{% block content %}
<form action="" method="post"> {% csrf_token %}
<ul>
{{accounts.form.as_ul}}
</ul>
<input type="submit" name="submit" value="Register">
</form>
{% endblock %}
UPDATE
Upon obtaining permission to move the template from the project manager, I moved it to accounts/template, and changed the render to response address.
I have new problem of form not submitting now.
OMG what's going on??
The template should not be in the same directory as settings.py.
It should be in a directory within the accounts app: accounts/templates/signup/html.
If you've configured your Django project correctly then Django should pickup the template after restarting the web server.
as I see you are passing form variable to template,
but you are trying to use accounts.form.
Hope this helps.
Ok the problem lies on my signup.html file. It should have script for onclick and the form should have an id.
{% extends "base.html" %}
{% block content %}
<form action="" method="post" id="form"> {% csrf_token %}
<ul>
{{accounts.form.as_ul}}
</ul>
<input type="submit" name="submit" value="Register" onclick="submit()">
</form>
<script>
function submit() {document.forms["form"].submit();}
</script>
{% endblock %}

Categories