How to match Questions with Answers in django - python

Please explain me how to match the Answer of a particular Question in django.
Right Now I am facing the issue that whatever the user inputs in the form if it exits in Answer database it returns True, But what I want is that whatever the user inputs should be matched with the Answer of that particular Question and not any of the Answers present.
models.py
from django.db import models
from django.contrib.auth import get_user_model
from PIL import Image
User=get_user_model()
# Create your models here.
class Question(models.Model):
question_name=models.CharField(max_length=20,unique=True,default=' ')
question_image=models.ImageField(upload_to='levels/')
question_text=models.TextField(blank=True,max_length=100)
def __str__(self):
return str(self.question_name)
class Meta:
ordering= ["question_name"]
class Answer(models.Model):
question_relation=models.ForeignKey(Question,on_delete=models.CASCADE)
answer=models.CharField(max_length=100,unique=True)
def __str__(self):
return self.answer
forms.py
from django import forms
from .models import Answer,Question
from django.core.exceptions import ObjectDoesNotExist
from . import views
class CheckAnswer(forms.Form):
your_answer=forms.CharField(label='Answer')
def clean(self):
cleaned_data=super(CheckAnswer,self).clean()
response=cleaned_data.get("your_answer")
try:
p = Answer.objects.get(answer__iexact=response)
except Answer.DoesNotExist:
raise forms.ValidationError("Wrong Answer.")
views.py
from django.shortcuts import render,redirect,get_object_or_404
from django.views.generic import *
from . import models
from django import forms
from .forms import CheckAnswer
from django.contrib.auth.decorators import login_required
from .models import Question
from dashboard.models import UserLoggedIn
# Create your views here.
#login_required
def Arena1(request):
if request.method=='POST':
form = CheckAnswer(request.POST)
if form.is_valid():
return redirect('thanks')
else:
form=CheckAnswer()
args={'form':form}
return render(request,'levels/arena1.html',args)
I think the concept of pk will be used but I dont know how to implement it
Please update my code that solves this problem.

First of All, Matching the Question would Require you to Store of Provide the Question to the Function Somehow. What You can do it use a Global Variable or a Container in which you would set the value while rendering the Question and then Import it to forms.py and set the your_question = Question
forms.py
from django import forms
from .models import Answer,Question
from django.core.exceptions import ObjectDoesNotExist
from . import views
class CheckAnswer(forms.Form):
your_answer=forms.CharField(label='Answer')
def clean(self):
cleaned_data=super(CheckAnswer,self).clean()
response=cleaned_data.get("your_answer")
try:
p = Answer.objects.get(answer__iexact=response)
if(your_answer == p.answer and your_question == p.question_relation.question_text): #user inputs should be matched with the Answer of that particular Question
#Code To Run for Correct Answer Goes Here
else:
#The Answer is Wrong or Does not Match the Particular Question
raise forms.ValidationError("Wrong Answer.")
except Answer.DoesNotExist:
raise forms.ValidationError("Wrong Answer.")

Related

How to do validation in django serializers?

I have 2 custom validation functions created using packages from PyPI, I want to inlcude them in my serializers.py in my django project before converting it to JSON using rest. Problem is i dont know where or how to put the functions in such that the code will run through it. Here is my code:
enter image description here(this is how im adding users right now, using the model's fields ive registered)
Here is my code:
/* serializers.py */
import re
import phonenumbers
from rest_framework import serializers
from phonenumbers import carrier
from validate_email import validate_email
class basicSerializer(serializers.Serializer):
emailplus = serializers.EmailField()
country = serializers.CharField(max_length=2)
phone_number = serializers.CharField(max_length=100)
def validate_emailplus(self):
email = self.validated_data.get("email")
if not validate_email(email, check_mx=True, verify=True):
raise serializers.ValidationError("Invalid email")
return email
/* views.py */
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import basic
from .serializers import basicSerializer
class basicList(APIView):
def get(self, request):
basic1 = basic.objects.all()
serializer = basicSerializer(basic1, many=True)
return Response(serializer.data)
def post(self):
pass
As you can see I am not using models.py anymore and serializers.py as some sort of model with the given email and phone fields. In order for my function to work (which is not at the moment), it needs to use get() method from the entered data and do validate_email to know if the email exists. Please tell me what changes should be made, i do not know if the problem is with views.py which still uses models.py or if i should register the serializer as a model?
To run your validations, you must call serializer.is_valid(), however, that requires data to be passed to the serializer not instances. The logic behind this is that drf validates data coming in not data already stored in your DB
Correct logic
Considerations
It looks like you are implementing a list view, but you are validating the email address, which is probably not what you intended to do in the first place. I am guess you want to validate email on create.
You can make use of drf's generic views and mixins such as GenericViewSet, ListModelMixin, and ListModelMixin
I think you have a type in validate_emailplus where you try to get the field email while the serializer declares it as emailplus
You seem not to be following PEP-8 (style guide for Python)
serializers.py
import re
import phonenumbers
from rest_framework import serializers
from phonenumbers import carrier
from validate_email import validate_email
class BasicSerializer(serializers.Serializer):
emailplus = serializers.EmailField()
country = serializers.CharField(max_length=2)
phone_number = serializers.CharField(max_length=100)
def validate_emailplus(self):
email = self.validated_data.get("emailplus")
if not validate_email(email, check_mx=True, verify=True):
raise serializers.ValidationError("Invalid email")
return email
views.py
from rest_framework import mixins, viewsets
class BasicViewSet(
viewsets.GenericViewSet,
mixins.ListModelMixin,
mixins.CreateModelMixin,
):
queryset = Basic.objects.all()
serializer_class = BasicSerializer
For a better understanding of how viewset and mixins work, I recommend checking their implementation
Validation in Admin site
From the screenshot you added, it looks like you are trying to validate in the admin site, for that consider the below code:
models.py
class Basic(models.Model):
...
def clean(self):
if not validate_email(self.email, check_mx=True, verify=True):
raise ValidationError("Invalid email")
This works because Django admin generates forms based on your models and then the forms call full_clean() on the model, which calls clean()

How to compare models using id's Django

Can anyone please help in tackling the following problem?
Suppose I have a model named Answer and a form for user input named CheckAnswer.
What I want is that when a particular Question page is openend and the user types the answer, it should get checked with the corresponding answer
The answer from the model can be accessed using the id. but how can i specify the id of question page that opens up and link it to the answer id.
Below are the codes attached
forms.py
from django import forms
from .models import Answer
from django.core.exceptions import ObjectDoesNotExist
class CheckAnswer(forms.Form):
your_answer=forms.CharField(label='Answer')
def clean(self):
cleaned_data=super(CheckAnswer,self).clean()
response=cleaned_data.get("your_answer")
try:
p = Answer.objects.get(id=1,answer__iexact=response)
except Answer.DoesNotExist:
raise forms.ValidationError("Wrong Answer.")
views.py
from django.shortcuts import render,redirect
from django.views.generic import *
from . import models
from django import forms
from .forms import CheckAnswer
from django.contrib.auth.decorators import login_required
# Create your views here.
#login_required
def Arena1(request):
if request.method=='POST':
form = CheckAnswer(request.POST)
if form.is_valid():
return redirect('thanks')
else:
form=CheckAnswer()
return render(request,'levels/arena1.html',{'form':form})
models.py
from django.db import models
from django.contrib.auth import get_user_model
User=get_user_model()
users=User.objects.all()
# Create your models here.
class Answer(models.Model):
name=models.CharField(max_length=10,unique=True)
answer=models.CharField(max_length=100)
def __str__(self):
return self.name
class Meta:
ordering= ["-name"]

Django IntegrityError-NOT NULL constraint failed: portfolio_myportfolio.holder_id

I am trying to make a portfolio manager app in django. I tried making the holder as a primary key. But in that case, the new entry overlaps the old one. So, I deleted that database and started afresh. Now, when I am trying to add a portfolio with a logged in user, I am getting the error as under:-
IntegrityError-NOT NULL constraint failed: portfolio_myportfolio.holder_id
I also wanted to set my database in such a way that If user adds the quantity of the same stock with same nsecode, it should add up in the previous entry instead of making a new row. In that case, what should be my scenario.
Since, I am very new to python and django, my code is not clean and might have few lines of code, which is un-necessary, any help in removing such errors would be much appreciated.
My Model is
from django.db import models
from django.contrib.auth.models import User
codes=(tuple of tuples)
class MyPortfolio(models.Model):
nsecodes = models.CharField(max_length=10, choices=codes)
quantity = models.PositiveIntegerField()
buyvalue=models.DecimalField(max_digits=15,decimal_places=2)
holder = models.ForeignKey(User, related_name='myportfolio')
# Create your models here.
my views. py is :
from django.shortcuts import render,redirect,get_object_or_404
from django.views.generic.edit import CreateView
from .models import MyPortfolio
from .forms import AddNewForm
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
def home(request):
return render(request,'home.html')
#login_required
def my_portfolio(request):
if request.user.is_authenticated():
myportfolios=MyPortfolio.objects.filter(holder=request.user)
return render(request, 'my_portfolio.html',{'myportfolios':myportfolios})
#login_required
def add_new_form(request):
if request.user.is_authenticated():
myportfolios = MyPortfolio.objects.filter(holder=request.user)
if request.method=="POST":
form=AddNewForm(request.POST)
if form.is_valid():
myportfolio=form.save()
myportfolio.nsecodes=form.cleaned.data.get('nsecodes')
myportfolio.buyvalue = form.cleaned.data.get('buyvalue')
myportfolio.quantity = form.cleaned.data.get('quantity')
myportfolio.holder=request.user
myportfolio.save()
return redirect('my_portfolio')
else:
form=AddNewForm()
return render(request,'add_new.html',{'form':form,'myportfolios':myportfolios})
my forms.py is as under:-
class AddNewForm(forms.ModelForm):
nsecodes=forms.ChoiceField(choices=codes, required=True)
quantity=forms.IntegerField(min_value=1,required=True)
buyvalue=forms.DecimalField(max_digits=10, decimal_places=2,required=True,min_value=.01)
class Meta:
model=MyPortfolio
fields=['nsecodes','quantity','buyvalue']
you are saving the data before assigning the foreign key id
try this
if form.is_valid():
myportfolio=form.save(commit=False)
myportfolio.holder=request.user
myportfolio.save()
return redirect('my_portfolio')

Django ModelForm validate if input exists in model

I have a model Linea with only one field named numero, wich is a charset (the values of numero are supposed to be numbers) . I want to do a form where the user can search for a value of numero. If the number that the user inputs exists in the database the view will redirect to a template that shows information about that value of numero, but if the value that the user search is not in the database it will throw an error.
I'm very new in Django, and I've searched the way to do it but I can't achieve it.
forms.py
from django import forms
from .models import Linea
class LineaForm(forms.ModelForm):
class Meta:
model = Linea
fields = ('numero',)
models.py
from __future__ import unicode_literals
from django.db import models
class Linea(models.Model):
numero = models.CharField(max_length=2)
def __str__(self):
return self.numero
views.py
from django.shortcuts import render, redirect, reverse
from .forms import LineaForm
from django.http import HttpResponseRedirect
import googlemaps
from datetime import datetime
def lineas(request, template="bustopaplineas.html"):
if request.method == "POST":
form = LineaForm(request.POST)
if form.is_valid():
numero = form.save(commit=False)
linea_numero = str(numero)
return redirect('lineas_detalles', linea_numero=linea_numero)
else:
form = LineaForm()
return render(request, 'bustopapp/lineas.html', {'form': form})
Thanks in advance.
You can check in the Linea table if it exists or not:
Linea.objects.get(numero=input)
In case, it doesn't it will throw an exception

NameError: global name 'Model' is not defined

I have a simple Django app where I want to define two tables in the database: user and question.
I have the following models.py:
from django.db import models
class User(models.Model):
name = models.CharField(max_length=100)
#classmethod
def create(cls, name):
user = cls(name=name)
return user
class Question(models.Model):
content = models.CharField(max_length=300)
answer = models.CharField(max_length=200)
#classmethod
def create(cls, content, answer):
question = cls(content=content, answer=answer)
return user
In /questions, which is defined in views.py, I would like to display all objects of type question:
from django.views.generic.base import TemplateView
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.db import models
def questions(request):
questions = Model.objects.raw('SELECT * FROM questions')
return render_to_response('questions.html', questions)
However, I am getting:
NameError: global name 'Model' is not defined
Why is the Model object visible in models.py but not in views.py?
Also, is the way in which I query the database correct?
Answer to the question
Model is not visible in models.py - it's accessed as models.Model.
You're importing models but trying to use Model instead of models.Model.
Try this:
def questions(request):
questions = models.Model.objects.raw('SELECT * FROM questions')
return render_to_response('questions.html', questions)
Alternatively you can import Model directly:
from django.db.models import Model
Answer to the problem
I think this is a case of the XY problem.
What you really want to do is access all instances of the Question model. If you want to use function based views for some reason, you can import the Question model and use it directly with .all():
Function based views
question/views.py
from myapp.models import Question
def questions(request):
questions = Question.objects.all()
return render_to_response('questions.html', questions)
Class based views
The better option however, is to use a class based generic view.
An example from the documentation:
questions/views.py
from django.views.generic import ListView
from questions.models import Question
class QuestionList(ListView):
model = Question
urls.py
from django.conf.urls import url
from questions.views import QuestionList
urlpatterns = [
url(r'^questions/$', QuestionList.as_view()),
]
Class based views offer much bigger expressiveness than funciton based viwes. They also eliminate the need for a lot of code duplication since commonly changed parts of a view can be overridden individually (e.g. get_context_data)
You have to call your model in the following way inside your view
from myapp.models import Question
def questions(request):
questions = Question.objects.all()
return render_to_response('questions.html', questions)
for more information read the official documentation about views... https://docs.djangoproject.com/en/1.10/topics/http/views/

Categories