I have an app that let you create a profile.
One of my app feature is it's let you edit your name and upload a image.
The problem is the user cannot submit the image unless he type his name.How can I fix this page to make it so If the user submit an image but doesn't submit a name . He will still have his old name
or if he doesn't submit an image and changes his name . He will still have his old picture?
I tried adding blank=True and null = False , null = True but doesn't seem to do the job
My models.py
class Person(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100,null=True,blank=False)
image = models.FileField(upload_to="images/")
def __unicode__(self):
return self.name
My forms.py
class PersonForm(forms.ModelForm):
class Meta:
model = Person
fields = ('image','name',)
My views.py
def Display(request):
if not request.user.is_authenticated():
return HttpResponseRedirect(reverse('world:LoginRequest'))
if request.method == 'POST':
form = PersonForm(request.POST, request.FILES)
if form.is_valid():
person = Person.objects.get(user=request.user)
person.image = form.cleaned_data['image']
person.name = form.cleaned_data['name']
person.save()
return render(request,'edit.html',{'form': PersonForm()})
class Person(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100, blank=True)
image = models.FileField(upload_to="images/", blank=True)
def __unicode__(self):
return self.name
def Display(request):
if not request.user.is_authenticated():
return HttpResponseRedirect(reverse('world:LoginRequest'))
if request.method == 'POST':
form = PersonForm(request.POST, request.FILES)
if form.is_valid():
image = form.cleaned_data['image']
name = form.cleaned_data['name']
person = Person.objects.get(user=request.user)
if image:
person.image = form.cleaned_data['image']
if name:
person.name = form.cleaned_data['name']
person.save()
return render(request,'edit.html',{'form': PersonForm()})
django forms does validation on the users data
validation is done on two levels:
the field level:
if the field is required and the user didn't enter any data it will raise an error
if the user entered improperly formatted data for that field it will raise an error
you can override the behavior of field validation by implementing functions named as clean_fieldname
this type of validation results in form.field.errors
the form level:
checks for any (non-field specific) validation errors
you can override the behavior by implementing clean method
this type of validation results in form.non_field_errors
from your models:
image is not allowed to be blank which means it is required. not entering an image will raise an error
let blank=True for both name and image
also I recommend using form.save() over saving models from the views
also there is a built in ImageField for saving images
Related
I am in the middle of a project. I have extended the custom django user and modified it.
this is my user model:-
class User(AbstractUser):
name = models.CharField(max_length=200, null=True, blank=True)
usertype = models.CharField(choices = [('d','doctor'), ('p','patient')], max_length=1)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []
def __str__(self):
return self.name
Also I have declared two seperate models named Patient and Doctors. My objective is to register the users in their respective models(Doctors or Patients) by checking the usertype.
Here are those models:-
class Patient(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='patient')
dob = models.DateField(null=True, blank=True)
contact = models.CharField(null=True, blank=True, max_length=100)
def __str__(self):
return self.user.name
class Doctor(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='doctor')
deg = models.TextField(null=True, blank=True)
def __str__(self):
return self.user.name
Now at the front end I want to apply the logic as every time a user is registered the user selects the usertype and based on that selection the Doctor or the Patient module is updated.
I have tried creating separate forms for that too.
Here are my forms :-
class MyUserCreation(UserCreationForm):
class Meta:
model = User
fields = ['name','username','usertype']
class DoctorCreation(ModelForm):
class Meta:
model = Doctor
fields = ['user','deg']
class PatientCreation(ModelForm):
class Meta:
model = Patient
fields = ['dob', 'contact','user']
The view handling this URL is :-
def registerUser(request):
page = 'general'
form = MyUserCreation()
if request.method == 'POST':
form = MyUserCreation(request.POST)
if form.is_valid:
user = form.save(commit=False)
user.save()
login(request, user)
return redirect('home')
else:
messages.error(request, 'Error occured')
if user.usertype == 'p':
page = 'patient'
form = PatientCreation()
form = PatientCreation(request.POST)
if form.is_valid:
form.save()
elif user.usertype== 'd':
page = 'doctor'
form = DoctorCreation()
form = DoctorCreation(request.POST)
if form.is_valid:
form.save()
context = {'form':form, 'page':page}
return render(request, 'rec/register_user.html', context )
The front end for this project is handled with very basic HTML.
Also, if possible I want the front end such that every time a user is registered and the usertype is selected(which is a dropdown menu) some more fields show up depending on the usertype selection by the user. If selected Doctor the additional fields respective to the Doctor module show up, and same for the patient module.
To keep it simple on the front end this solution works like:
Loads Page with User Form
Submit User Form
Uses value to Load Next form
Submit Next Form + Redirect
Notes:
Uses the Values POSTed to determine what form is being submitted
Uses Initial to set User for the 2nd Form
This current flow could be broken up into 3 view with their own distinct URLs
Django View
def registerUser(request):
form = None
if request.method == 'POST':
valid = False
if 'usertype' in request.POST:
# 1st form submit
form = MyUserCreation(request.POST)
if form.is_valid:
valid = True
user = form.save(commit=False)
user.save()
login(request, user)
# Get 2nd form for load
if user.usertype == 'p':
page = 'patient'
form = PatientCreation(initial={'user':user})
elif user.usertype== 'd':
page = 'doctor'
form = DoctorCreation(initial={'user':user})
else:
# 2nd form submit
if 'dob' in request.POST:
form = PatientCreation(request.POST)
if form.is_valid:
form.save()
valid = True
elif 'deg' in request.POST:
form = DoctorCreation(request.POST)
if form.is_valid:
form.save()
valid = True
if valid:
# form sequence done
return redirect('home')
if not valid:
# a form failed somewhere
print(form.errors)
messages.error(request, 'Error occured')
if form == None:
page = 'general'
form = MyUserCreation()
context = {'form':form, 'page':page}
return render(request, 'rec/register_user.html', context )
Basic Django HTML Form
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
Now you could make this a single page by making the Template more complex, with JQuery Hiding/Showing extra fields based on dropdown Value on Change, but I assumed this would be the route you wanted.
Edit
To make the field disabled you'd just edit the forms.py
Note: the form-control is just showing that you can also add classes + extra attributes if you need to
class PatientForm(forms.ModelForm):
class Meta:
model = RunRequest
fields = (
'user',
'dob',
'contact',
)
def __init__(self, *args, **kwargs):
super(PatientForm, self).__init__(*args, **kwargs)
self.fields['user'].widget.attrs={'class': 'form-control', 'disabled':True}
I am writing an application which stores "Jobs". They are defined as having a ForeignKey linked to a "User". I don't understand how to pass the ForeignKey into the model when creating it. My Model for Job worked fine without a ForeignKey, but now that I am trying to add users to the system I can't get the form to validate.
models.py:
from django.db import models
from django import forms
from django.contrib.auth.models import User
class Job(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=50, blank=True)
pub_date = models.DateTimeField('date published', auto_now_add=True)
orig_image = models.ImageField('uploaded image', upload_to='origImageDB/', blank=True)
clean_image = models.ImageField('clean image', upload_to='cleanImageDB/', blank=True)
fullsize_image = models.ImageField('fullsize image', upload_to='fullsizeImageDB/')
fullsize_clean_image = models.ImageField('fullsize clean image', upload_to='fullsizeCleanImageDB/')
regions = models.TextField(blank=True)
orig_regions = models.TextField(blank=True)
class JobForm(forms.ModelForm):
class Meta:
model = Job
In views.py I was creating the objects as follows:
if request.method == 'POST':
form = JobForm(request.POST, request.FILES)
if form.is_valid():
#Do something here
I understand that this passes the form data and the uploaded files to the form. However, I don't understand how to pass in a User to be set as the ForeignKey.
Thanks in advance to anyone who can help.
A typical pattern in Django is:
exclude the user field from the model form
save the form with commit=False
set job.user
save to database
In your case:
class JobForm(forms.ModelForm):
class Meta:
model = Job
exclude = ('user',)
if request.method == 'POST':
form = JobForm(request.POST, request.FILES)
job = form.save(commit=False)
job.user = request.user
job.save()
# the next line isn't necessary here, because we don't have any m2m fields
form.save_m2m()
See the Django docs on the model form save() method for more information.
Try:
if request.method == 'POST':
data = request.POST
data['user'] = request.user
form = JobForm(data, request.FILES)
if form.is_valid():
#Do something here
I've created a Django view that does 2 things:
Create a new account
Modify a account
Works:
Creating new account and submitting the HTML form data to the database. Also works: showing a prefilled HTML form if user wants to modify an account with the account data that is known in the database.
Doesnt work:
When the user submits his/her form to update an account (user modified the info in the form), nothing is updated in the database.
I know how to update one single static value in the database like so:
a = accounts.objects.filter(pk=account_id).update(name='static value here')
but I don't know how to update the database with all the form data that the user submits when using Django Modelforms. Does anyone knows how to update the database with the submitted form data?
Code
#login_required(login_url='/dashboard/')
def dashboard_accounts_new_modify(request, account_id=None):
if request.method == 'POST':
# POST DETECTED
form = MyModelForm(request.POST, request.FILES)
if account_id:
# POST DETECTED
# ACCOUNT ID FOUND
# USER WANTS TO MODIFY A ACCOUNT
# WITH THIS QUERY I CAN UPDATE 1 STATIC VALUE IN THE DATABASE
# HOW DO I UPDATE THE VALUES FROM THE FORM IN THE DATABASE?? :(
a = accounts.objects.filter(pk=account_id).update(name='static value here')
return HttpResponseRedirect('/dashboard/accounts/')
else:
# POST DETECTED
# ACCOUNT ID NOT FOUND
# USER WANTS TO CREATE A NEW ACCOUNT
if form.is_valid():
if request.POST.get("name").lower() == 'new':
raise Http404("New account name may not be named NEW.")
# DATAHASE QUERY: ADD NEW ACCOUNT TO DATABASE
form.save()
# REDIRECT
return HttpResponseRedirect('/dashboard/accounts/')
elif account_id:
# NO POST DETECTED
# ACCOUNT ID FOUND
# PREFILL FORM WITH DATA
try:
from django.forms.models import model_to_dict
a = accounts.objects.get(pk=account_id)
form = MyModelForm(initial=model_to_dict(a))
except:
raise Http404("Account not found.")
else:
# NO POST DETECTED
# MODIFICATION IS NOT DETECTED
# LOAD EMPTY FORM
form = MyModelForm()
return render(request, 'backend/base_accounts_new.html', {'Title': 'Accounts', 'form' : form})
Model
# Clientdatabase
class accounts(models.Model):
name = models.CharField(max_length=200)
url = models.CharField(max_length=200)
website_title = models.CharField(max_length=200)
website_h1_text = models.CharField(max_length=200)
website_h2_text = models.CharField(max_length=200)
website_search_text = models.CharField(max_length=200)
website_font = models.CharField(max_length=200)
website_footer_left = models.CharField(max_length=600)
website_footer_right = models.CharField(max_length=600)
website_color_code_search_button = models.CharField(max_length=200)
website_color_code_banner = models.CharField(max_length=200)
website_logo_height_pixels = models.PositiveIntegerField()
website_logo_width_pixels = models.PositiveIntegerField()
filepath_favicon = models.FileField()
filepath_logo_vector = models.FileField()
filepath_logo_normal = models.FileField()
filepath_background_1 = models.FileField()
filepath_background_2 = models.FileField(blank=True, null=True)
filepath_background_3 = models.FileField(blank=True, null=True)
filepath_background_4 = models.FileField(blank=True, null=True)
setting_background_1_active = models.BooleanField()
setting_background_2_active = models.BooleanField()
setting_background_3_active = models.BooleanField()
setting_background_4_active = models.BooleanField()
def __str__(self):
return self.name
class AccountsForm(ModelForm):
class Meta:
model = accounts
fields = '__all__'
You can do like:
from django.shortcuts import get_object_or_404
if request.method == 'POST':
if account_id::
account = get_object_or_404(accounts, pk=account_id)
form = MyModelForm(request.POST,request.FILES, instance=account)
if form.is_valid():
...
form.save()
return HttpResponseRedirect('/dashboard/accounts/')
else:
form = MyModelForm(request.POST, request.FILES)
if form.is_valid():
if request.POST.get("name").lower() == 'new':
raise Http404("New account name may not be named NEW.")
form.save()
Learn more about forms here
I have question regarding how to attach additional form to logged in users in Django.
I want that additional form belongs to logged in user and the data I enter in the form should goes under logged in user table. I am new to Django and python please have patience I hope i can explain correctly what i want to do with this
Data I shall enter for this view shall go under logged in user only basically i want to attach this view to the logged in user only Error I am getting is
Exception Value:
registration_todos.user_id may not be NULL
#models
class userProfile(models.Model):
user = models.OneToOneField(User)
birth =models.DateField()
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
class todos(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=100)
created = models.DateField()
time = models.TimeField()
def __unicode__(self):
return unicode(self.user)
#forms additional form for todos
class formtodos(ModelForm):
title = forms.CharField(label=(u'Todo'))
created = forms.DateField(label=(u'Date'))
time = forms.TimeField(label=(u'Time'))
#user = forms.CharField(label=(u'username'))
class Meta:
model = todos
exclude=('user',)
#view
def modeltodo(request):
if request.user.is_authenticated():
todos.objects.filter(user=request.user)
if request.method == 'POST':
form =formtodos(request.POST)
if form.is_valid():# All validation rules pass
todoss = form.save(commit=False)
todoss.created_by = request.user
form.save()
return HttpResponseRedirect('/profile/')
else:
form = formtodos() # An unbound form
context = {'form':form}
return render_to_response('todo.html', context, context_instance=RequestContext(request))
you've specified exclude = ('user',) in your form. This means that when you try to save the form there is no user_id present which causes the error. You probably want to put this before the save() call: todoss.user = request.user
I got this form working Ok but i can't figure out how to save it to the database via the model i know this is a semantic question that i can't figure out Please Help. I'm using django The error is
D = Donation(user=request.user,name=form.cleaned_data['name'],description=cd['description']) D.save()
views.py
def donate(request):
if request.method == 'POST':
form = DonationForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
D = Donation(user=request.user,name=form.cleaned_data['name'],description=cd['description'])
D.save()
return HttpResponseRedirect('/test/')
else:
form =DonationForm()
return render_to_response('addaDonation.html',{'form': form},context_instance=RequestContext(request))
`
Donation is my Model and i need to get the information from my form into the Donation Model so i can D.save
class DonationForm(forms.Form):
name = forms.CharField(max_length=50)
description = forms.CharField(max_length=3000)
towards = forms.CharField()
#image = forms.ImageField()
class Donation (models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=50)
description = models.CharField(max_length=3000)
towards = models.ForeignKey(NonProfit)
image = models.ImageField(upload_to='photos/%Y/%m/%d')
The error I get is
(1054, "Unknown column 'name' in 'field list'")
Request information
GET
No GET data
POST
Variable Value
csrfmiddlewaretoken u'nXGN4gdZwk2qxNpP9YIXzvNQI7lKQe5r'
towards u'this'
name u'this'
description u'that'
change your form class to the following;
from django.forms import ModelForm
class DonationForm(ModelForm):
class Meta:
class = Donation
exclude = ("user", )
def save(self, user):
donation = super(DonationForm, self).save(commit=False)
donation.user = user
donation.save()
return donation
Then you should be able to change the view.py to the following;
def donate(request):
if request.method == 'POST':
form = DonationForm(request.POST, request.FILES)
if form.is_valid():
form.save(request.user)
return HttpResponseRedirect('/test/')
else:
form = DonationForm()
return render_to_response('addaDonation.html',{'form': form},context_instance=RequestContext(request))
See official documentation Creating forms from Models