I am trying to check and see if there is a duplicate entry in the database before adding an entry. Here are my current models --
class Education(models.Model):
school = models.CharField(max_length=100)
class_year = models.IntegerField(max_length=4, blank=True, null=True, choices=YEAR)
degree = models.CharField(max_length=100, blank=True, null=True)
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
employments = models.ManyToManyField(Employment)
On the form, a user must enter a school. Class year and degree are optional. To check for duplicate entries, right now I have --
if form.is_valid() and request.POST['school']:
school = form.cleaned_data['school']
try:
school_object = Education.objects.get(school=form.cleaned_data['school'],
class_year=form.cleaned_data['class_year'],
degree = form.cleaned_data['degree'])
except (Education.DoesNotExist):
school_object = Education(school=form.cleaned_data['school'],
class_year=form.cleaned_data['class_year'],
degree = form.cleaned_data['degree'])
school_object.save()
profile.educations.add(school_object)
profile.save()
I am getting an ValueError if the class_date is not filled out. How to fix this and also when checking for duplicates? Thank you.
First, unless you've got a great reason you really shouldn't be accessing post variables without sending them through a form.
from django import forms
class MyForm(forms.form):
school = forms.CharField()
degree = forms.CharField(required=False)
class_year = forms.CharField(required=False)
def clean(self):
if not self.cleaned_data.has_key('degree'):
self.cleaned_data['degree'] = None
if not self.cleaned_data.has_key('class_year'):
self.cleaned_data['class_year'] = None
return self.cleaned_data
Then when you're processing the view:
...
if request.method == "POST":
form = MyForm(request.POST)
if form.is_valid():
try:
# NOTE that the objects.get method will raise MultipleObjectsReturned if the
# database has more than one object that matches the query
my_object = Education.objects.get(school=form.cleaned_data['school'],
class_year=form.cleaned_data['class_year'],
degree = form.cleaned_data['degree'])
except Education.DoesNotExist:
my_object = Education(school=form.cleaned_data['school'],
class_year=form.cleaned_data['class_year'],
degree = form.cleaned_data['degree'])
else:
form = MyForm()
...
In views:
if 'Add School' in request.POST.values():
form = EducationForm(request.POST)
if form.is_valid() and request.POST['school']:
school = form.cleaned_data['school']
try:
school_object = Education.objects.get(school=form.cleaned_data['school'],
class_year=form.cleaned_data['class_year'],
degree = form.cleaned_data['degree'])
except (Education.DoesNotExist, ValueError):
school_object = Education(school=form.cleaned_data['school'],
class_year=form.cleaned_data['class_year'],
degree = form.cleaned_data['degree'])
school_object.save()
profile.educations.add(school_object)
profile.save()
return redirect('edit_education')
Or, using get_or_create to simplify:
if 'Add School' in request.POST.values():
form = EducationForm(request.POST)
if form.is_valid() and request.POST['school']:
school = form.cleaned_data['school']
school_object, created = Education.objects.get_or_create(school=form.cleaned_data['school'],
class_year=form.cleaned_data['class_year'],
degree = form.cleaned_data['degree'])
if created:
profile.educations.add(school_object)
profile.save()
return redirect('edit_education')
In forms:
YEAR = ([(x, x) for x in range(1970,2015)])
YEAR.append((0,'Select Year'))
YEAR.reverse()
class EducationForm(forms.Form):
school = forms.CharField()
class_year = forms.ChoiceField(choices=YEAR, required=False)
degree = forms.CharField(required=False)
def clean(self):
if not self.cleaned_data.get('class_year'):
self.cleaned_data['class_year'] = None
if not self.cleaned_data.get('degree'):
self.cleaned_data['degree'] = ''
return self.cleaned_data
Related
I everyone, I have a problem with a django's view. My goal is to change the 'execute' field into 'True' if newOrder is buy and there is some other sell order with a inferior price. And reverse for sell newOrders. I want to change the 'execute' field for the newOrder and also for the other order (in pairs). That's my code:
views.py
def order(request):
form = OrderForm()
if request.method == 'POST':
form = OrderForm(request.POST)
if form.is_valid():
new_order = form.save()
if new_order.buy is True:
sellOrder = Order.objects.filter(sell=True, execute=False,
price__lte=new_order.price).first().update(execute=True)
new_order.execute = True
sellOrder.save()
else:
buyOrder = Order.objects.filter(buy=True,
execute=False,price__gte=new_order.price).first().update(execute=True)
new_order.execute = True
buyOrder.save()
new_order.profile = request.user
new_order.save()
return redirect('home')
else:
form = OrderForm()
contex = {'form': form}
return render(request, 'app/new_order.html', contex)
models.py
class Profile(models.Model):
_id = ObjectIdField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
wallet = models.FloatField()
class Order(models.Model):
_id = ObjectIdField()
profile = models.ForeignKey(User, on_delete=models.CASCADE)
datetime = models.DateTimeField(auto_now_add=True)
buy = models.BooleanField(blank=True)
sell = models.BooleanField(blank=True)
price = models.FloatField()
quantity = models.FloatField()
execute = models.BooleanField(blank=True)
But something goes wrong. This is the error:
AttributeError at /new_order/
'NoneType' object has no attribute 'update'
sellOrder returns a count of updated rows, not the object updated
sellOrder = Order.objects.filter(sell=True, execute=False,
price__lte=new_order.price).first().update(execute=True)
instead try
sellOrder = Order.objects.filter(sell=True, execute=False,
price__lte=new_order.price).first()
new_order.execute = True
sellOrder.execute = True
sellOrder.save()
this is views.py
def registerItem(request):
print(request)
try:
print("====111", request.method)
if request.method == 'POST':
print("=========222", request.POST)
form = ItemForm(request.POST)
print("====333", form.is_bound)
print("====444", form)
print("====555", form.cleaned_data['mart_id']())
print("====666", form.is_valid())
if form.is_valid():
mart = MartModel.objects.get(id__exact=form.cleaned_data['mart_id'])
print("====666", mart)
seq = ItemModel.objects.filter(mart_id__exact=mart).values('seq').order_by('-seq')[:1]
if seq:
seq = seq[0]['seq']+1
else:
seq = 1
# form.save()
item = ItemModel(mart_id=mart, seq=seq, name=form.cleaned_data['name'], price=form.cleaned_data['price'], expirationDate=form.cleaned_data['expirationDate'], stockYn=form.cleaned_data['stockYn'])
item.save()
form = ItemForm()
return render(request, 'mobileWeb/admin/register_item.html', {'form':form})
else:
form = ItemForm()
return render(request, 'mobileWeb/admin/register_item.html', {'form':form})
except Exception as ex:
print('====777 : Error occured : ', ex)
request.POST value is correct. you can confirm it by log No.2.
form is bound correctly. you can confirm it by log No.3.
but the form failed to receive values. you can confirm it by log No.4.
this is forms.py
class MartForm(forms.ModelForm):
class Meta:
model = MartModel
fields = ['name', 'address', 'tell', 'phone', 'xPosition', 'yPosition']
class ItemForm(forms.ModelForm):
choicesQueryset = MartModel.objects.all().values('id', 'name')
choicesDic = []
for choice in choicesQueryset:
choicesDic.append((choice['id'], choice['name']))
mart_id = forms.CharField(label='mart', widget=forms.Select(choices=choicesDic))
class Meta:
model = ItemModel
fields = ['mart_id', 'name', 'price', 'expirationDate', 'stockYn']
this is models.py
class MartModel(models.Model):
name = models.CharField(max_length=20, blank=False)
address = models.TextField(blank=False)
tell = models.CharField(blank=True, max_length=12)
phone = models.CharField(blank=True, max_length=11)
imageFileNo = models.CharField(blank=True, max_length=3)
xPosition = models.FloatField(blank=False)
yPosition = models.FloatField(blank=False)
delete_yn = models.CharField(blank=False, default="N", max_length=1)
ins_dttm = models.DateTimeField(blank=False, auto_now_add=True)
ins_user = models.CharField(blank=False, max_length=20, default='ADMIN')
upt_dttm = models.DateTimeField(blank=False, auto_now=True)
upt_user = models.CharField(blank=False, max_length=20, default='ADMIN')
class ItemModel(models.Model):
mart_id = models.ForeignKey('martModel', models.DO_NOTHING)
seq = models.IntegerField(blank=False)
name = models.CharField(blank=False, max_length=20)
price = models.IntegerField(blank=False)
expirationDate = models.DateField(blank=False)
stockYn = models.CharField(blank=False, max_length=1, default='Y')
delete_yn = models.CharField(blank=False, default="N", max_length=1)
ins_dttm = models.DateTimeField(blank=False, auto_now_add=True)
ins_user = models.CharField(blank=False, max_length=20, default='ADMIN')
upt_dttm = models.DateTimeField(blank=False, auto_now=True)
upt_user = models.CharField(blank=False, max_length=20, default='ADMIN')
class Meta:
unique_together = (
('mart_id', 'seq')
)
I know about that it must be a instance not a value when deal with the foreignKey.
but the error occured on binding time.
is this concerend with foreignKey??
================
after advice
no mart name is here.
this is forms.py
class ItemForm(forms.ModelForm):
mart = forms.ModelChoiceField(queryset=MartModel.objects.all(), to_field_name='name')
class Meta:
model = ItemModel
fields = ['mart', 'name', 'price', 'expirationDate', 'stockYn']
this is views.py
from django.shortcuts import render
from .forms import *
# Create your views here.
def index(request):
try:
marts = MartModel.objects.all().values('id', 'name', 'imageFileNo', 'xPosition', 'yPosition')
items = ItemModel.objects.filter(stockYn__exact='Y').values('mart', 'name', 'price', 'expirationDate').order_by('mart_id', 'seq')
return render(request, 'mobileWeb/index/index.html', {'marts':marts, 'items':items})
except Exception as ex:
print('Error occured : ', ex)
def registerMart(request):
try:
if request.method == 'POST' :
form = MartForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'mobileWeb/index/index.html')
else :
form = MartForm()
return render(request, 'mobileWeb/admin/register_mart.html', {'form':form})
except Exception as ex:
print('Error occured : ', ex)
def registerItem(request):
print(request)
try:
print("====111", request.method)
if request.method == 'POST':
print("=========222", request.POST)
form = ItemForm(request.POST)
print("====333", form.is_bound)
print("====444", form)
if form.is_valid():
mart = MartModel.objects.get(id__exact=form.cleaned_data['mart'])
print("====666", mart)
seq = ItemModel.objects.filter(mart__exact=mart).values('seq').order_by('-seq')[:1]
if seq:
seq = seq[0]['seq']+1
else:
seq = 1
# form.save()
item = ItemModel(mart=mart, seq=seq, name=form.cleaned_data['name'], price=form.cleaned_data['price'], expirationDate=form.cleaned_data['expirationDate'], stockYn=form.cleaned_data['stockYn'])
item.save()
form = ItemForm()
return render(request, 'mobileWeb/admin/register_item.html', {'form':form})
else:
form = ItemForm()
return render(request, 'mobileWeb/admin/register_item.html', {'form':form})
except Exception as ex:
print('====777 : Error occured : ', ex)
this is debug variable when make Item Form
this is debug variable about queryset
this is debug variable about 1st member of queryset
ofcourse I did makemigrations, migrate.
I don't know why are you trying to approach like this. ModelForm has very nice way to handle FK, and if you want to show name of the MartModel object, then you can use ModelChoiceField's to_field_name option. For example:
class ItemForm(forms.ModelForm):
mart_id = forms.ModelChoiceField(queryset=MartModel.objects.all(), to_field_name='name')
class Meta:
model = ItemModel
fields = ['mart_id', 'name', 'price', 'expirationDate', 'stockYn']
Also, please change the name of the field mart_id to mart, because underneath django creates a field name mart_id, if you assign the field name to mart.
Finally, in the view, you should not call cleaned_data[...] before calling form.is_valid(). Unless the form is validated, the data won't be available in cleaned_data.
Update
(from comments) Add a __str__ method at the bottom of MartModel class:
class MartModel(models.Model):
...
def __str__(self):
return self.name
Have AttributeError 'QueryDict' object has no attribute 'first_name' Get examples from here. I'm don't understand what is the problem
models.py
class Employee(models.Model):
first_name = models.CharField(max_length=30)
second_name = models.CharField(max_length=30)
patronymic = models.CharField(max_length=30)
birth_date = models.DateField()
views.py
def edit_employee_action(request, employee_id):
if request.method == "POST":
form = AddEmployeeForm(request.POST)
if form.is_valid():
edited = Employee.objects.filter(pk=employee_id)
edited.update(
first_name = request.POST.first_name,
second_name = request.POST.second_name,
patronymic = request.POST.patronymic,
birth_date = request.POST.birth_date
)
else:
form = AddEmployeeForm()
form = AddEmployeeForm()
return render(
request,
'edit_employee.html',
context={'form': form}
)
The parameter employee_id is correct (debugged).
you need to get the value from request.POST like this:
request.POST['first_name']
(this approach will raise KeyError if first_name is not available in request.POST)
or
request.POST.get('first_name')
You are using incorrectly the request.POST. It is actually a `dictionary. Try the following.
def edit_employee_action(request, employee_id):
if request.method == "POST":
form = AddEmployeeForm(request.POST)
if form.is_valid():
edited = Employee.objects.filter(pk=employee_id)
edited.update(
first_name = request.POST.get('first_name'),
second_name = request.POST.get('second_name'),
patronymic = request.POST.get('patronymic'),
birth_date = request.POST.get('birth_date')
)
else:
form = AddEmployeeForm()
form = AddEmployeeForm()
return render(
request,
'edit_employee.html',
context={'form': form}
)
This way even if the key does not exist you'll get a None value instead of an exception. Also be sure that the key values are the same in your template.
I know there are a lot of similar questions here, but none of them seem to be working with my view in Django 1.8 with a ModelForm.
I have a user profile form that works as long as I have each required field in the template context, but I only want each logged in user to fill out their own form.
I'm doing something wrong here, and I'm not sure what the problem is. Can someone correct me? I've spent hours looking at other posts and trying various suggestions from SO. I'm getting "NOT NULL constraint failed: camp_userprofile.user_id"
Here's my models.py:
class UserProfile(models.Model):
user = models.OneToOneField(User)
picture = models.ImageField(upload_to='profile_images', blank=True)
city = models.CharField(max_length = 20)
needs_camp_bike = models.BooleanField(default=False)
diet_lifestyle = models.CharField(max_length = 200, choices=What_are_you, null=True, blank=True)
meal_restrictions = models.CharField(max_length = 200, blank= True)
other_restrictions = models.CharField(max_length=100, blank=True)
arrival_day = models.IntegerField(choices=Days)
departure_day = models.IntegerField(choices=Days)
date = models.DateTimeField(auto_now_add=True, blank=True)
def __str__(self):
return '%s %s %s %s %s %s %s %s %s' %(
self.user, self.picture, self.city,
self.needs_camp_bike,
self.diet_lifestyle, self.meal_restrictions, self.other_restrictions,
self.arrival_day, self.departure_day
)
My forms.py
class UserProfileForm(ModelForm):
class Meta:
Fish = "Fish"
Mammal = "Mammal"
Vegetarian = "Vegetarian"
Omnivore = "Omnivore"
Onions = "Onions"
Cucumber = "Cucumber"
Peppers = "Peppers"
Gluten_free = "Gluten_free"
Vegan = "Vegan"
Shellfish = "Shellfish"
Olives = "Olives"
Pork = "Pork"
Soy = "Soy"
Dairy = "Dairy"
Cilantro = "Cilantro"
Quinoa = "Quinoa"
Nightshades = "Nightshades"
Nuts = "Nuts"
Pescaterian = "Pescaterian"
Restrictions = (
(Mammal, "Mammal"),
(Onions, "Onions"),
(Cilantro, "Cilantro"),
(Soy, "Soy"),
(Dairy, "Dairy"),
(Quinoa, "Quinoa"),
(Pork, "Pork"),
(Olives, "Olives"),
(Dairy, "Dairy"),
(Peppers, "Peppers"),
(Cucumber, "Cucumber"),
(Nightshades, "Nightshades"),
(Nuts, "Nuts")
)
model = UserProfile
fields = ('picture', 'city',
'needs_camp_bike', 'diet_lifestyle',
'other_restrictions', 'arrival_day',
'departure_day', 'meal_restrictions')
widgets = {
'meal_restrictions': forms.widgets.CheckboxSelectMultiple(choices=Restrictions),
}
and my views.py
#login_required
def profile(request):
form = UserProfileForm(request.POST)
print(request.user)
if request.method == 'POST':
if form.is_valid():
form.save(commit=False)
form.user =request.user.username
form.save(commit=True)
else:
print(messages.error(request, "Error"))
return render(request, "profile.html", RequestContext(request, {'form': form, 'profile': profile,}))
You shouldn't do form.user = request.user.username, because form.user won't add the user to the form. You should capture the object that form.save(commit=false) returns, then assign the user to that object and save it.
Also you cannot assign a user field with username, username is only a string not User object. You should do this instead:
if form.is_valid():
userprofile = form.save(commit=False)
userprofile.user = request.user
userprofile.save()
forms.py
class UserProfileForm(forms.ModelForm):
phone = forms.CharField(max_length = 15,widget = forms.TextInput(attrs = {'placeholder':'Enter mobile no. ','class':''}))
profession = forms.CharField(max_length= 50,widget = forms.Select(choices = PROFESSION_CHOICES,attrs = {'class':''}))
#email = forms.EmailField(label='Email address',max_length = 75,widget = forms.TextInput(attrs={'placeholder':'Email address.','class':''}))
sex = forms.CharField(max_length = 20,label="I am :",widget=forms.Select(choices=SEX_CHOICES,attrs = {'class':''}))
first_name = forms.CharField(max_length = 50,widget = forms.TextInput(attrs={'placeholder':'Please enter your real name.','class':''}))
last_name = forms.CharField(max_length = 50,widget = forms.TextInput(attrs={'placeholder':'Enter last name.','class':''}))
location = forms.CharField(max_length = 50,widget = forms.TextInput(attrs={'placeholder':'Enter your current location','class':''}))
def clean_first_name(self):
first_name = self.cleaned_data['first_name']
if first_name == '':
raise forms.ValidationError("This field is required.")
return first_name
def save(self,*args,**kw):
self.instance.first_name = self.cleaned_data.get("first_name")
self.instance.last_name = self.cleaned_data.get("last_name")
self.instance.sex = self.cleaned_data.get("sex")
self.instance.location = self.cleaned_data.get("location")
self.instance.profession = self.cleaned_data.get("profession")
self.instance.phone = self.cleaned_data.get("phone")
self.instance.save()
return self.instance
class Meta:
model = User
fields = ('username','first_name','last_name','phone','sex','profession','location')
views.py
def profile(request,nav="profile",template="profile.html",context = {},extra_context = None):
if request.POST:
if 'profileFormSubmit' in request.POST:
pform = UserProfileForm(request.POST,instance = request.user)
if pform.is_valid():
try:
user = pform.save()
return redirect(profile,nav="profile")
except RuntimeError as e:
return HttpResponse(e)
error
The User could not be changed because the data didn't validate.
line
user = super(UserProfileForm,self).save(*args,**kw)
doubt
what changes am i supposed to make to get rid of this error
how am i supposed to change the , i have tried removing all the clean_field form methods , but still getting the same error , please help , thanks in advance.
You are calling save on your form before you clean. And you are calling save twice. Once at the start of the form save. And once at the end.
pform.is_valid() returns a boolean that you never check.
docs on modelforms
The form wasn't validating because I was using 'username' in my meta class of the UserProfileForm, which wasn't supposed to be there.