Error on django - .save() function - python

class Member(models.Model):# member db table
userID = models.CharField(max_length=80,primary_key=True) #user id
password = models.CharField(max_length=32)# password
nickname = models.CharField(max_length=100)# user nickname
penalty = models.PositiveSmallIntegerField(max_length=10,default=0,null=True)
participation=models.ForeignKey('Room',default=None,blank=True,null=True)
def __unicode__(self):
return self.userID
def doJoin(request):
if request.is_ajax() and request.method == 'POST':
# check validation
userID = request.POST['userID']
userNickname = request.POST['nickname']
if (checkID(userID) == False) and (checkNickname(userNickname) == False) :
#save to the database
newUser = Member()
newUser.userID = userID
newUser.nickname = userNickname
newUser.password = request.POST['password']
print newUser.userID , newUser.nickname , newUser.password , newUser.penalty , newUser.participation
newUser.save() #<------------error line!!!!
return HttpResponse('true')
else:
return HttpResponse('false')
else:
HttpResponse('false')
line about 8
In function doJoin:
newUser.save() # <--- error... so sad...
What should I do? Help me please.
What's wrong in this source?

Do you have debugging turned off? If you're getting a 500 and you have debugging turned on, you'll get a stack trace with the exception.
What are checkID() and checkNickname() doing? If those are performing some sort of validation, you really should be doing that in a form class instead of in the view. I also wouldn't be pulling values directly out of the request.POST to populate your model. I would highly recommend retrieving those values from a form's cleaned_data dictionary.

Related

I want to get only customer id but getting whole customer information

I am trying to show orders by customer id by i am getting this error :
TypeError at /orders
Field 'id' expected a number but got {'id': 3, 'phone_number': '01622153196', 'email': 'sakibovi#gmail.com', 'password': 'pbkdf2_sha256$216000$H2o5Do81kxI0$2tmMwSnSJHBVBTU9tQ8/tkN7h1ZQpRKrTAKkax1xp2Y=', 'coin': 1200.0}.
Actually i want to fetc only customer id but getting whole dictionary.
Here in Login Class in views.py i fetch whole customers info like this
request.session['customer'] = customer.__dict__
Here is the details :
class Login(View):
def get(self, request):
return render(request, 'signupsignin/signin.html')
def post(self, request):
phone_number = request.POST.get('phone_number')
password = request.POST.get('password')
customer = Customer.get_customer(phone_number)
error_message = None
if customer:
match = check_password(password, customer.password)
if match:
customer.__dict__.pop('_state')
request.session['customer'] = customer.__dict__
# request.session['customer'] = customer.id
#request.session['customer'] = customer.coin
#request.session['phone_number'] = customer.phone_number
return redirect('Home')
else:
error_message = 'Phone number or Password didnt match on our record'
else:
error_message = 'No Customer Found! Please Registrer First!'
print(phone_number, password)
context = {'error_message':error_message}
return render(request, 'signupsignin/signin.html', context)
I think for that reason i am getting the whole informaton of a customer
Here is my Views.py for userorders by customer id ::
class UserOrders(View):
def get(self, request):
customer = request.session.get('customer')
user_orders = Order.get_orders_by_customer(customer)
print(user_orders)
args = {'user_orders':user_orders}
return render(self.request, 'Home/all_orders.html', args)
Here i have a method named get_orders_by_customer() i made this in models.py
Here it is ::
#staticmethod
def get_orders_by_customer(customer__id):
return Order.objects.filter(customer=customer__id)
So what i am trying to do is customers can see their own orders.I have a panel called "all orders" here a customer can see their own order only.
Please Help me i got really confused here
As per my understanding, you have to pass a number, but you're passing a whole dictionary.
#staticmethod
def get_orders_by_customer(customer__id):
return Order.objects.filter(customer=customer__id)
here before return try to debug with a print or something. and you'll see what I mean.
try this and it should work, if im not wrong:
costomer__id['id'] instead of costomer__id
or change your code into this:
#staticmethod
def get_orders_by_customer(customer):
return Order.objects.filter(customer=customer['id'])
You can try using values() query to achieve your purpose.
Here is the link to the documentation - https://docs.djangoproject.com/en/3.1/ref/models/querysets/#values

Validating Entered Data with custom constraints in Django Forms in __init__

In my project, the user is entering data in a settings page of the application and it should update the database with the user's settings preference. I read this answer by Alasdair and how using the __init__() will allow to access the user's details. I was wondering if it's possible to return data from __init__() so I can validate the entered data before calling the save() function in the view? This is what I tried (and did not work). I am open to going about this in a better approach so I appreciate all your suggestions!
**EDIT: ** I am deciding on moving the validation of the data entered by the user in the forms file because when I wrote it in my views, I ended up getting 5 if statements (nested). IMO, and given the situation of this application, moving it to the forms seems to be a cleaner approach. I also considered using the clean_['field'] but I need the side variable from the __init__() function to do that and I am not sure how to extract that value.
Forms.py
class t_max_form(forms.ModelForm):
side = None
def __init__(self, *args, **kwargs):
side = kwargs.pop('side', None)
super(t_max_form, self).__init__(*args,**kwargs)
if side == "ms":
self.fields['hs_max_sessions'].widget.attrs.update({'class':'form-control', 'readonly':True})
self.fields['ms_max_sessions'].widget.attrs.update({'class':'form-control mb-3'})
elif side == "hs":
self.fields['hs_max_sessions'].widget.attrs.update({'class':'form-control'})
self.fields['ms_max_sessions'].widget.attrs.update({'class':'form-control', 'readonly':True})
else:
self.fields['hs_max_sessions'].widget.attrs.update({'class':'form-control'})
self.fields['ms_max_sessions'].widget.attrs.update({'class':'form-control'})
#Trying to validate the data here
valid_session_count = settings.objects.first()
if(side == "ms"):
input_sessions = self.fields['ms_max_sessions'].widget.attrs['readonly']
if(input_sessions > valid_session_count.max_sessions):
self.add_error("ms_max_sessions", "You have entered more than the limit set by the TC. Try again")
elif(side == "hs"):
input_sessions = self.cleaned_data['hs_max_sessions']
if(input_sessions > valid_session_count.max_sessions):
self.add_error("hs_max_sessions", "You have entered more than the limit set by the TC. Try again")
else:
input_sessions = self.cleaned_data['ms_max_sessions'] + self.cleaned_data['hs_max_sessions']
if(input_sessions > valid_session_count.max_sessions):
self.add_error("hs_max_sessions", "You have entered more than the limit set by the TC. Try again")
return input_sessions
And this is what I was trying in my views
views.py
def t_time_slots(request):
name = request.user.username
t = t_info.objects.get(student__user__username = name)
timeSlots = tutor_time_slot.objects.filter(tutor = tutor).order_by('time')
side = decide_side(request.user)
if request.method == 'POST':
form = t_time_slot_form(request.POST)
if form.is_valid():
if check_unique_time_slot(request.user, form.cleaned_data['day'], form.cleaned_data['time']):
timeSlots = form.save(commit=False)
timeSlots.t = t
timeSlots.save()
messages.success(request, "Added Successfully")
return redirect('TTimeSlot')
else:
print("Overlap")
messages.error(request, "The time slot overlaps with a Current one. Please Change the time and try again.")
return redirect('TTimeSlot')
else:
form = t_time_slot_form()
context = {'timeSlots': timeSlots, 'form': form, 'side':side}
return render(request, 't/t_time_slot.html', context)
Set self.side in the __init__ method, then you can access it in the clean() or clean_<field> methods.
I would avoid putting validation code in the __init__ method.
class MyForm(forms.Form):
my_field = forms.CharField()
def __init__(self, *args, **kwargs):
self.side = kwargs.pop('side', None)
super(t_max_form, self).__init__(*args,**kwargs)
...
def clean_my_field(self):
my_field = self.cleaned_data['my_field']
# Use self.side to validate data
if my_field = self.side:
raise forms.ValidationError("Invalid")
return my_field

Django form field update

I have a Django form that lets users choose a tag from multiple tag options. The problem I am facing is that even when the tag list gets updated, the model form does not get the updated tag list from database. As a result, new tags do not appear in options.
Here is my code in forms.py:
class EnglishTagForm(forms.Form):
tag_choices = [(x.tagName, x.tagName.upper()) for x in ClassTag.objects.filter(
agentId=Agent.objects.get(name='English Chowdhury'))]
tag = forms.CharField(widget=forms.Select(choices=tag_choices,
attrs={'class':'form-control'}))
def __init__(self, *args, **kwargs):
super(EnglishTagForm, self).__init__(*args, **kwargs)
self.fields['tag'].choices = [(x.tagName,
x.tagName.upper()) for x in ClassTag.objects.filter(
agentId=Agent.objects.get(name='English Chowdhury'))]
This form is being instantiated in view. My question is what changes should I do so that tag_choices gets updated from database on every instantiation.
How the above form is used in views.py:
```
def complaintDetail(request, complaint_id):
complaint = Complaints.objects.filter(pk=complaint_id).first()
context = {}
if request.method == 'POST':
agent = Agent.objects.get(name="English Chowdhury")
if "SubmitTag" in request.POST:
englishForm = EnglishTagForm(request.POST)
if englishForm.is_valid:
// Complaint Delete Logic
return redirect('chatbot:modComplaints')
else:
englishForm = EnglishTagForm()
context['eForm'] = englishForm
elif "SubmitBundle" in request.POST:
newTagForm = NewTagForm(request.POST)
if newTagForm.is_valid():
// Complaint Delete Logic
complaint.delete()
return redirect('chatbot:modComplaints')
else:
newTagForm = NewTagForm()
context['newForm'] = newTagForm
else:
englishForm = EnglishTagForm()
context['eForm'] = englishForm
newTagForm = NewTagForm()
context['newForm'] = newTagForm
context['complaint'] = complaint
return render(request, 'chatbot/complaintDetail.html', context)
```
Edit: (For future reference)
I decided to modify the tag attribute and convert CharField to ModelChoiceField, which seems to fix the issue.
Updated Class:
class EnglishTagForm(forms.Form):
tag = forms.ModelChoiceField(queryset=ClassTag.objects.filter(
agentId=Agent.objects.get(name='English Chowdhury')),
empty_label=None, widget=forms.Select(
attrs={'class':'form-control'}))
Please remove the list comprehension from Line 2. So that,
tag_choices = [(x.tagName, x.tagName.upper()) for x in ClassTag.objects.filter(
agentId=Agent.objects.get(name='English Chowdhury'))]
becomes
tag_choices = []

How to assign dict values to user_id for creating objects

def insertCompany_type(request):
if request.method == 'POST':
try:
data = json.loads(request.body)
c_type = data["subject"]
user = get_user_id(request)
print user
c_ty=Company_Type(user_id=user,type=c_type)
c_ty.save(force_insert=True)
except:
print 'nope'
return JsonResponse({'status': 'success'})
print user
displays [{'user_id': 1L}]
.. How can i assign 1 to user_id in Company_Type(user_id=user,type=c_type)for creating objects
If user is a list of length 1, containing a dict, you can extract the value of a dict as follows:
value = user[0]['user_id']
You could modify your code as:
if request.method == 'POST':
try:
data = json.loads(request.body)
c_type = data["subject"]
user = get_user_id(request)
id = user[0]['user_id']
c_ty=Company_Type(user_id=id,type=c_type)
c_ty.save(force_insert=True)
except:
print 'nope'
return JsonResponse({'status': 'success'})
Also if you need to make sure the id is an integer cast it to the right data type as int(id)
When you actually make a user (which doesnt happen your snippet of code) you can pass a constuctor argument setting user_id. e.g.
myUser = User(name="shalin", user_id=1)
myUser.save()
Also, you can get user objects from requests simply by doing this:
user = request.user
which is a bit easier than what you're doing I think.

How to fetch column values using SQLAlchemy?

I am using Flask+Python and to check if a username (and email) is already taken or not i am using this logic:
#app.route('/register', methods=['GET', 'POST'])
def register():
form = SignupForm()
if form.validate_on_submit():
user = Users.query.filter_by(username=form.username.data).first()
email = Users.query.filter_by(email=form.email.data).first()
if form.username.data in user:
error = 'Username already taken. Choose another'
elif form.email.data in email:
error = 'Email already registered. Login or register with another Email'
else:
user = Users(
form.username.data,
form.password.data,
#form.confirm.data ,
form.email.data,
1,
# form.cityaddress.data,
# form.countryaddress.data,
#form.accept_tos.data,
)
db.session.add(user)
db.session.commit()
return redirect(url_for('index'))
But its giving error like object has no attribute 'username'
I know my logic for fetching data from db is not correct. I have little knowledge of SQLalchemy.
Could you suggest me How can i fetch Username (and Email) column value from table Users and then check them if there are same as form.username.data ?
Your queries look fine, the return value from first() will be an instance of your User object, or None if there were no results:
u = Users.query.filter_by(username=form.username.data).first()
if u is not None:
print u.username
print u.email
So given that, here's what your logic could look like:
user_by_name = Users.query.filter_by(username=form.username.data).first()
user_by_email = Users.query.filter_by(email=form.email.data).first()
if user_by_name:
error = 'Username already taken. Choose another'
elif user_by_email:
error = 'Email already registered. Login or register with another Email'
else:
#Unique user and email
You could also do it in one query:
existing = Users.query.filter((Users.username == form.username.data) | (Users.email == form.email.data)).all()
if existing:
error = 'User or email taken'
Note the use of filter rather than filter_by - you cant use the bitwise operators in filter_by. Here's a quick working example
Your error confuses me. That said, your code looks okayish, except for the test. I use this then:
user = Users.query.filter_by(username=form.username.data).first()
...
if user is not None:
error("user already found")

Categories

Resources