I am working on student management project and I am unable to get the branch for student as it is foreignkey of Course model to Student model and I want to get the selected option into student model in branch row
models.py:
class Course(models.Model):
id=models.AutoField(primary_key=True)
course = models.CharField(max_length=50)
course_code = models.BigIntegerField(null=True)
def __str__(self):
return self.course
class Student(models.Model):
id=models.AutoField(primary_key=True)
user=models.OneToOneField(User,on_delete=models.CASCADE)
branch=models.ForeignKey(Course,on_delete=models.CASCADE,null=True,blank=True)
middle_name=models.CharField(max_length=50,null=True)
roll_no=models.IntegerField()
mobile_no=PhoneNumberField(default='')
parents_mobile_no=PhoneNumberField(default='')
division=models.CharField(max_length=10,null=True)
batch=models.CharField(max_length=10,null=True)
def __str__(self):
return self.user.first_name + " " + self.user.last_name
views.py:
def studentregister(request):
if request.method == 'POST':
first_name = request.POST['first_name']
middle_name = request.POST['middle_name']
last_name = request.POST['last_name']
email = request.POST['email']
branch= request.POST['branch']
division = request.POST['division']
roll_no = request.POST['roll_no']
mobile_no = request.POST['mobile_no']
parents_mobile_no = request.POST['parents_mobile_no']
pass1 = request.POST['password']
pass2 = request.POST['confirmpassword']
if pass1 == pass2 :
if User.objects.filter(email=email).exists():
return HttpResponse('User already exsits')
else:
user = User.objects.create_user(email=email, password=pass1, first_name=first_name, last_name=last_name)
user.save();
studentdetails = Student ( user=user, middle_name=middle_name,roll_no=roll_no,mobile_no=mobile_no,parents_mobile_no=parents_mobile_no, branch=branch,division=division)
studentdetails.save();
return render (request, 'ms/homepage/index.html')
else:
return HttpResponse('password does not match')
else:
return HttpResponse('failed')
def staffstudent(request):
if request.user.is_authenticated and request.user.user_type==3:
courses = Course.objects.all()
return render(request, 'ms/staff/student.html',{'courses':courses})
else:
return render(request,'ms/login/login.html')
html file as student.py:
<form action="studentregister" method="POST" style = "background-color:#011B3C;">
{% csrf_token %}
<div class="form-group" name="branch">
<select >
<option selected disabled="true">Branch</option>
{% for course in courses%}
<option>{{course.course}}</option>
{%endfor%}
</select>
</div>
</form>
The error I am getting is
MultiValueDictKeyError at /staff/studentregister
'branch'
Please help me with this as soon as possible.
You haven't named that <select> (<select name="branch">) so any choice you make in it will not be transmitted to the server, and that's why you get a key error.
In addition, the <option>'s value must be the course's id:
<option value="{{ course.id }}">{{ course.course }}</option>
... so you can look it up in the view:
branch = Course.objects.get(id=request.POST['branch'])
However, please look at Django's built-in forms functionality, especially model forms – you would be done in a fraction of the HTML and Python code you have now, plus you'd actually have correct data validation.
This is not the conventional way to deal with Forms in Django although it can be done. Convention would be:
Creating a form in forms.py like so:
class MyForm(forms.Form):
dropdown_one = forms.ChoiceField(
label="Country",
widget=forms.Select(attrs={"class": "selecter form-control"}),
choices=[],
)
dropdown_two = forms.ChoiceField(
label="Category",
widget=forms.Select(attrs={"class": "selecter form-control"}),
choices=[(None, '...')],
required=True
)
Then use this form in views.py like so:
my_form = MyForm(initial={})
return render(request,{'my_form':my_form})
Then finally in html file:
{{my_form.media}}
{% for item in my_form %}
<div class="form-group col-lg-2" id="dropdown-content">
{{item.label_tag}}
{{item}}
</div>
{% endfor %}
</div>
For more refer to this:
https://docs.djangoproject.com/en/4.0/topics/forms/
Related
I am trying to create a basic personality test in Django as a proof-of-concept at work. I'm new to Django (and python in general), coming at it from a C# .NET background.
I am trying to make a list of form objects (populated with information pulled from question objects stored in the database), then display them in the HTML.
This is only partly working; I can render the form attributes individually in a for loop (by calling, for example, question.pk) but nothing renders with the standard Django {{ form }} tag, and trying to submit the list of forms breaks the whole thing.
I'm pretty sure it's an issue with handling a bunch of form objects populated inside one larger html , but I'm not sure how to go about resolving it.
I've done some research into formsets, but I can't find any way to pre-populate the form items with information from the database.
Thanks in advance!
DISCQuestionForm in forms.py:
class DISCQuestionForm(forms.Form):
# create new form object from database question object
def __init__(
self,
pk,
disc_query,
dom_answer,
infl_answer,
stead_answer,
con_answer,
):
super().__init__()
self.pk = pk
self.disc_query = disc_query
self.dom_answer = dom_answer
self.infl_answer = infl_answer
self.stead_answer = stead_answer
self.con_answer = con_answer
self.disc_response = forms.DecimalField(
max_value=4,
widget=forms.NumberInput
)
disc_create method in views.py
# Create a new DISC assessment for current user
def disc_create(request, pk):
profile = User.objects.get(pk=pk)
user = int(profile.pk)
name = profile.name
rawquestionset = DISCQuestion.objects.all()
discformset = []
for item in rawquestionset:
question = DISCQuestionForm(
pk=item.pk,
disc_query=item.disc_query,
dom_answer=item.dom_answer,
infl_answer=item.infl_answer,
stead_answer=item.stead_answer,
con_answer=item.con_answer,
)
discformset.append(question)
if request.method == 'POST':
questionset = discformset[request.POST]
if questionset.is_valid():
dom = 0
infl = 0
stead = 0
con = 0
for discquestion in questionset:
if discquestion.disc_response == discquestion.dom_answer:
dom += 1
if discquestion.disc_response == discquestion.infl_answer:
infl += 1
if discquestion.disc_response == discquestion.stead_answer:
stead += 1
if discquestion.disc_response == discquestion.con_answer:
con += 1
disctest = DISCTest(
user=user,
name=name,
dom=dom,
infl=infl,
stead=stead,
con=con,
)
disctest.save()
else:
questionset = discformset
context = {
"pk": user,
"name": name,
"discquestionset": questionset
}
return render(request, "disc_create.html", context)
DISCTest and DISCQuestion models in models.py:
class DISCTest(models.Model):
user = models.ForeignKey('User', on_delete=models.CASCADE)
name = user.name
created_on = models.DateTimeField(auto_now_add=True)
dom = models.DecimalField(max_digits=3, decimal_places=0)
infl = models.DecimalField(max_digits=3, decimal_places=0)
stead = models.DecimalField(max_digits=3, decimal_places=0)
con = models.DecimalField(max_digits=3, decimal_places=0)
class DISCQuestion(models.Model):
disc_query = models.TextField()
disc_response = models.DecimalField(max_digits=1, decimal_places=0, null=True)
dom_answer = models.DecimalField(max_digits=1, decimal_places=0)
infl_answer = models.DecimalField(max_digits=1, decimal_places=0)
stead_answer = models.DecimalField(max_digits=1, decimal_places=0)
con_answer = models.DecimalField(max_digits=1, decimal_places=0)
and finally disc_create.html in templates:
{% extends "base.html" %}
{% block page_content %}
<div class="col-md-8 offset-md-2">
<h1>Take your DISC assessment</h1>
<hr>
<h3>Insert instructions here</h3>
<hr>
<form action="/assessment/create/{{pk}}/" method="post">
{% csrf_token %}
<div>
{% for question in discquestionset %}
<p>{{question.pk}}</p>
<p>{{ question.disc_query }}</p>
{{ form }}
{% endfor %}
</div>
<button type="submit">Submit</button>
</form>
</div>
{% endblock %}
Your DiscQuestionForm has no fields. disc_response is defined as an attribute of the form but for Django it isn't a field because it isn't added to self.fields. And form isn't defined in your template in your for loop, only question (which is the form) so {{ question }} would print the form if it had any fields.
But then the problem is that each of your question form fields would all have the same "name" attributes because they are not prefixed to make them unique.
You should read this document carefully to understand ModelForm and modelformset. Basically you need:
class DISCQuestionForm(forms.ModelForm):
class Meta:
model = DISCQuestion
def __init__(...):
...
Use the modelformset_factory to create a proper ModelFormSet that you can initialise with the request.POST when submitted.
DISCQuestionFormSet = modelformset_factory(DISCQuestionForm, form = DISCQuestionForm) # note DISCQuestionForm not needed if you don't customise anything in your form.
and in your view:
formset = DISCQuestFormSet(request.POST or None)
then in your template you can loop through the forms in the formset:
{% for form in formset %}{{ form }}{% endfor %}
I do really know that is a common topic but I've already checked every solution i could find and it did not work for me.
I would like to add user points using button click.
views.py
def add_points(request):
if request.GET.get('mybtn'):
profil = get_object_or_404(Profile, created_by=request.user)
profil.points += 10
profil.save(update_fields=["points"])
return render(request, 'users/profile.html')
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to="profile_pics")
points = models.PositiveIntegerField(default=0)
people = models.PositiveIntegerField(default=0)
html file
<div>
<form method="POST">
{% csrf_token %}
<input type="submit" class="btn" value="+10 pkt" name="mybtn"/>
</form>
</div>
I have tried diffrent solutons but nothing really worked out for me.
Try F function.
from django.db.models import F
def add_points(request):
if request.GET.get('mybtn'):
profil = get_object_or_404(Profile, created_by=request.user)
profil.points = F('points') + 10
profil.save(update_fields=["points"])
return render(request, 'users/profile.html')
I am new to Django and I've got the hang of the basics so far but I am trying to do something that the tutorials I learnt from haven't taught me and basically what I want to do is, I have a field in my models.py called delegates_num and that field is a counter for the number of delegates which sign up for a particular course. I want to be able to increment that field by 1 each time someone signs up for a particular course, the courses being [ITIL, Change Management, Management of Risk, Programme Management, PRINCE2]
So for example, if the user books an ITIL course, the counter for that course will be incremented by 1. Each course has a limit of 15 spaces so a condition somewhere which says something like:
if course.name = 'ITIL' && if delegates_num > 15
redirect user to 'course is full page'
else submit registration form and increment delegates_num by 1
I would be extremely grateful for any help, here's the code so far:
class Course(models.Model):
MY_CHOICES = (
('Open', 'Open'),
('Closed', 'Closed'),
('Fully Booked', 'Fully Booked'),
)
course_name = models.CharField(max_length=40)
course_code = models.CharField(max_length=40)
price = models.CharField(max_length=40, default='add price')
topic_details = models.TextField(max_length=200)
start_date = models.DateField('start date')
end_date = models.DateField('end date')
status = models.CharField(max_length=20, choices=MY_CHOICES)
venue = models.ForeignKey(Venue, on_delete=models.CASCADE)
room = models.CharField(max_length=20)
delegates_num=models.IntegerField()
def add_delegate(self):
#for count, thing in enumerate(args):
self.delegates_num+=1
def __str__(self):
return self.course_name
models.py
<h1>Registration</h1>
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_p }}
{% if course.course_name = 'ITIL' %}
{{ course.delegates_num|inc }}
{% if course.delegates_num > 15 %}
<meta http-equiv="refresh" content="1;url=http://example.com">
<script type="text/javascript">
window.location.href = "https://yr4-group-project-mfblack.c9users.io/sorry_full/"
</script>
{% endif %}
{% endif %}
<button type="submit" class="save btn btn-default">Save</button>
</form>
book_course.html
def book_course(request):
if request.method == "POST":
form = StudentForm(request.POST)
if form.is_valid():
student = form.save(commit=False)
student.save()
student.course.add_delegate()
return redirect('registration_complete')
else:
form = StudentForm()
return render(request, 'website/book_course.html', {'form': form})
views.py
It's probably much easier to just make a property, since I'm guessing you're not taking into account people leaving the course - or the possibility of user error.
A property that retrieves a count is usually a small database operation and has some guarrantee to be accurate
#property
def delegates_num(self)
return self.user_set.count()
I assume you have a fk to a user model or simlar..
I am Learning Django and i need to allow users of the app to be able to add more options to the item_name field through the template but i don't have an idea on how to achieve that. Thanks for the help.
Here is my model
class ItStore(models.Model):
type_choice = (
('Printer Catridge', 'Printer Catridge'),
('UPS', 'UPS'),
('UPS Battery', 'UPS Battery'),
('Mouse', 'Mouse'),
('Keyboard', 'Keyboard'),
)
item_name = models.CharField(max_length='100', blank=True, null=False, choices=type_choice)
quantity = models.IntegerField(default='', blank=True, null=False)
Here is my View
def itstore_create(request):
form = ItStoreCreateForm(request.POST or None)
submit = "Create IT Store Items"
if form.is_valid():
instance = form.save(commit=False)
instance.save()
message = instance.item_name + " Successfully Created"
messages.success(request, message)
return redirect("items:itstore_list")
context = {
"form": form,
"title": "CREATE ITEM",
}
return render(request, "store_form.html", context)
Here is my form
class ItStoreCreateForm(forms.ModelForm):
class Meta:
model = ItStore
fields = ['item_name', 'quantity']
You could not define choices= on your model. But instead define a list of default choices outside of the model.
my_choices = (
"foo",
"bar",
"pop",
)
class MyModel(models.Model):
my_field = models.CharField(max_length=100)
Then in your view you'd want to import that tuple and pass it to you template:
from my_app.models import my_choices
def my_view(request, *a, **kw):
# view logic
return render(request, "path/to/my/template", choices=my_choices)
Then in your template you can have a select box with the default choices and string values. And also have an optional input type=text that will save to that field if populated.
Something like:
<select name="my_field">
<option value="" selected="selected">-----</option>
{% for choice in choices %}
<option value="{{ choice }}">{{ choice }}</option>
{% endfor %}
</select>
Will give you default choices. Then add an input with the same name, this will act as an optional new choice.
<input type="text" name="my_field"/>
Optionally you could write javascript logic that will ensure only the selectbox or the textfield gets submitted.
I have a simple form where there is a username and a message. Upon clicking the submit button, I want the data for user and message to be stored separately into the database. I am currently receiving an IntegrityError on m.save()
"Exception Value: SimpleMessage_message.content may not be NULL"
and was told to instead use forms to accomplish this. However, I am confused as to how to use a form to pass in form data to the individual User and Message Models so that the input data is saved in the database.
Models
class User (models.Model):
name = models.CharField(max_length=20)
def __unicode__(self):
return self.name
class Message (models.Model):
content = models.TextField(max_length=140, null=True, blank=True)
user = models.ForeignKey(User)
time = models.DateTimeField()
def __unicode__(self):
return self.content
views.py
def index (request):
if request.method == 'POST':
u = User(name=request.POST.get('user'))
u.save()
m = Message(content=request.POST.get('text'), user = u)
m.save()
return render_to_response('index.html', {
'user': u,
'message': m,
}, RequestContext(request))
else:
u = User()
m = Message()
return render_to_response('index.html', {
'user': u,
'message': m,
}, RequestContext(request)
)
index.html
<form action="{% url 'index' %}" method = "post">
{% csrf_token %}
<input type="text" name="user" id="user" maxlength="20" placeholder = "Username">
<br>
<br>
<textarea rows="4" cols="35" id="text" name="text" maxlength="140" placeholder = "Message goes here"></textarea><br>
<input type="submit" value="Submit">
</form>
Try changing your model so that content can be null:
class Message (models.Model):
content = models.TextField(max_length=140, null=True, blank=True)
Or give a default value in the form:
m = Message(content=request.POST.get('text', ' '), user = u)