How to get manytomanyfield model data in View in Django - python

models.py
class Account(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE, default='auth.User')
id = models.CharField(max_length=50, unique=True)
pw = models.CharField(max_length=200)
nick = models.CharField(max_length=50, blank=True)
blog = models.URLField(null=True, blank=True)
published_date = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
self.published_date = timezone.now()
self.pw = make_password(self.pw)
super(Account, self).save(*args, **kwargs)
def __str__(self):
return self.id
class Meta:
ordering = ["-published_date"]
class Task(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE, default='auth.User')
account = models.ManyToManyField(Account)
published_date = models.DateTimeField(default=timezone.now)
def publish(self):
self.published_date = timezone.now()
self.save()
forms.py
classAccountForm(forms.ModelForm):
class Meta:
model = NaverAccount
fields = ('id', 'pw', 'nick','blog',)
class TaskForm(forms.ModelForm):
class Meta:
model = Task
fields = ('account',)
task.html
<form action="#" class="form-horizontal" method="POST">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-success" type="submit">Save</button>
views.py
def task(request):
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.published_date = timezone.now()
#1. id = str(from Account model)
#2. pw = str(from Account model)
post.save()
form.save_m2m()
return redirect('task')
else:
form = TaskForm()
context = {'form': form}
return render(request, 'work/task.html', context)
I'm making small task app.
I want to get model data that user select(Account) from template in view.
ex) user can select 'id1', 'id2'.
and I want to get id, pw value in view.
so I can play small task with using id, pw in view
I tried to test some code in view like print(post.account) but can't go further.
1. id = str(from Account model)
2. pw = str(from Account model)

Related

How to save foreign key data using forms.py?

urls.py
...
path('restaurant/menu/', r_view.Menu, name='menu'),
...
menu.html
<form method="POST" id="menuForm" autocomplete="off" action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-inline">
<div class="form-group mb-4">
{{ form.item|as_crispy_field }}
</div>
<div class="form-group mb-4">
{{ form.itemImage|as_crispy_field }}
</div>
<div class="form-group mb-4">
{{ form.price|as_crispy_field }}
</div>
<div class="form-group mb-4">
{{ form.category|as_crispy_field }}
</div>
</div>
<button type="submit" class="col-md-12 myBtn">Submit</button>
</form>
views.py
def Menu(request, restaurantID):
restaurant = get_object_or_404(Restaurant_Account, restaurantID=restaurantID)
form = MenuForm()
if request.method == 'POST':
form = MenuForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.restaurant = restaurant
instance.save()
messages.success(request, "Saved successfully!")
return redirect('r_index')
context = {'form':form}
return render(request, 'restaurant/menu.html', context)
forms.py
class MenuForm(forms.ModelForm):
restaurantID = Restaurant_Account.objects.filter(restaurantID='restaurantID')
item = forms.CharField(required=True)
itemImage = forms.ImageField(required=False, label='Item image')
price = forms.DecimalField(required=True)
category = forms.ChoiceField(choices=CATEGORY)
class Meta:
model = Menu
fields = ('item', 'itemImage', 'price', 'category')
models.py
class Restaurant(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
is_restaurant = models.BooleanField(default=True)
restaurantID = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
isActive = models.BooleanField(default=True)
image = models.ImageField(upload_to='images/', blank=True)
website = models.URLField(blank=True, unique=False)
country = models.CharField(max_length=50)
def __str__(self):
return self.user.username
class Menu(models.Model):
menuID = models.AutoField(primary_key=True)
restaurantID = models.ForeignKey(Restaurant_Account, on_delete=models.CASCADE, default=None)
item = models.CharField(max_length=100)
itemImage = models.ImageField(upload_to='images/', blank=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
category = models.CharField(
max_length=20,
choices=[('', 'Choose category'),('Appetizer', 'Appetizer'),('Entree', 'Entree'),('Drink', 'Drink'),('Dessert', 'Dessert'), ('Side', 'Side')])
def __str__(self):
return self.item
I'm new to Django.
I made a form for saving menu data. If the user fills the form and click the submit button every data should be saved in the Menu table. I have no idea how to save restaurantID, which is a foreign key that refers to the Restaurant table, automatically. (By automatically I mean without the user entering input) Can somebody help me with this?
You haven't need to do all these things, if you have made restaurantID a foreign key while defining the model that is Menu, django itself handles it.
Below code might work for you:
forms.py
class MenuForm(forms.ModelForm):
item = forms.CharField(required=True)
itemImage = forms.ImageField(required=False, label='Item image')
price = forms.DecimalField(required=True)
category = forms.ChoiceField(choices=CATEGORY)
class Meta:
model = Menu
fields = ('item', 'itemImage', 'price', 'category')
views.py
def menu(request):
if request.method == 'POST':
form = MenuForm(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.success(request, "Saved successfully!")
return redirect('r_index')
else:
form=MenuForm()
return render(request, 'restaurant/menu.html', {'form':form})
optional: You also don't need to write this line menuID = models.AutoField(primary_key=True) in Menu model, as django makes id column by default for AutoField.
Update:
Make your models.py in this way:
MY_CHOICES=[
('', 'Choose category'),
('Appetizer', 'Appetizer'),
('Entree', 'Entree'),
('Drink', 'Drink'),
('Dessert', 'Dessert'),
('Side', 'Side')
]
class Restaurant(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
is_restaurant = models.BooleanField(default=True)
name = models.CharField(max_length=200)
isActive = models.BooleanField(default=True)
image = models.ImageField(upload_to='images/', blank=True)
website = models.URLField(blank=True, unique=False)
country = models.CharField(max_length=50)
def __str__(self):
return self.user.username
class Menu(models.Model):
restaurant= models.ForeignKey(Restaurant, on_delete=models.CASCADE, default=None)
item = models.CharField(max_length=100)
itemImage = models.ImageField(upload_to='images/', blank=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
category = models.CharField(
max_length=20,
choices=MY_CHOICES)
def __str__(self):
return self.item
Remove your AutoField, django by default make id which is primary key.
Don't forget to run makemigrations and migrate, after doing this, if it still gives error, so comment your all models and then run.

Form is not saving in database when submitted

I am working on a project on Django, where user can input values on form and submit using POST request. When form is submitted, datas are not saved in database. How do I implement save data when form is submitted.
Models:
class DataInfo(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
beneficiary_name = models.CharField(max_length=250, blank=True)
beneficiary_bank_name = models.CharField(max_length=250, blank=True)
beneficiary_account_no = models.CharField(max_length=250, blank=True)
beneficiary_iban = models.CharField(max_length=250, blank=True)
beneficiary_routing_no = models.CharField(max_length=250, blank=True)
amount = models.IntegerField(blank=True)
date = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'DataInfo'
verbose_name_plural = 'DataInfo'
ordering = ['-date']
'''Method to filter database results'''
def __str__(self):
return self.user.username
Views:
#login_required
def TransferView(request):
form = DataForm(request.POST)
if request.method == "POST":
if form.is_valid():
pp = form.save(commit=False)
pp.user = request.user
pp.save()
return redirect('site:transfer_cot')
else:
form = DataForm()
context = {
'form':form
}
return render(request, 'transfer.html', context)
Forms:
class DataForm(forms.ModelForm):
class Meta:
model = DataInfo
fields = ('beneficiary_name', 'beneficiary_bank_name', 'beneficiary_account_no', 'beneficiary_iban', 'beneficiary_routing_no', 'amount')
Template:
<form method="POST" action="{% url 'site:transfer_cot' %}">
{% csrf_token %}
{{ form }}
<button type="submit" class="btn btn-secondary">Submit</button>
</form>

Attendance system using Django

Models
attendance_choices = (
('absent', 'Absent'),
('present', 'Present')
)
class Head_of_department(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
email = models.CharField(max_length=30)
def __str__(self):
return self.first_name
class Employee(models.Model):
first_name = models.CharField(max_length=200, unique=True)
last_name = models.CharField(max_length=200, unique=True)
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
email = models.EmailField(max_length=100)
def __str__(self):
return self.first_name + ' ' + self.last_name
class Attendance(models.Model):
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
employee = models.ForeignKey('Employee', on_delete=models.CASCADE, )
attendance = models.CharField(max_length=8, choices=attendance_choices, blank=True)
Views
class Attendancecreate(CreateView):
model = Attendance
fields = ['employee']
success_url = '/dashboard/'
def get_context_data(self,** kwargs):
context = super(Attendancecreate, self).get_context_data(**kwargs)
context['formset'] = AttendanceFormset(queryset=Attendance.objects.none())
context['attendance_form'] = Attendanceform()
email = self.request.user.email
hod = Head_of_department.objects.get(email=email)
context["employees"] = Employee.objects.filter(head_of_department =hod)
return context
def get_initial(self):
email = self.request.user.email
hod = Head_of_department.objects.get(email=email)
initial = super(Attendancecreate , self).get_initial()
initial['employee'] = Employee.objects.filter(head_of_department=hod)
return initial
def post(self, request, *args, **kwargs):
formset = AttendanceFormset(request.POST)
if formset.is_valid():
return self.form_valid(formset)
def form_valid(self, formset):
instances = formset.save(commit=False)
for instance in instances:
instance.head_of_department = get_object_or_404(Head_of_department, email=self.request.user.email)
instance.save()
return HttpResponseRedirect('/dashboard/')
Forms
class Attendanceform(ModelForm):
class Meta:
model = Attendance
fields = ('employee','attendance','head_of_department')
AttendanceFormset = modelformset_factory(Attendance,fields=('attendance',))
Template
{% csrf_token %}
{{ formset.management_form }}
{% for employee in employees %}
{% for form in formset %}
{{employee.first_name}} {{ form }}
{ % endfor %}<br><br>
{% endfor %}
The webapp has a login feature. The headofdepartment can mark the attendance . List of employees are rendered in the template without any issues , I want to mark attendance to the respective employees sorted in ascending order of their first_name .
That is when marking attendance employees will be listed in template, and to the right attendance form will be displayed for all the employees . It is saving only one object and not assigning the initial value for employee
Requirement :
Following dirkgroten I was able to solve the issue, answer allow to render a list employees under the head_of_department(logged in hod) and mark respective attendance .
Models
attendance_choices = (
('absent', 'Absent'),
('present', 'Present')
)
class Head_of_department(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
email = models.CharField(max_length=30)
def __str__(self):
return self.first_name
class Employee(models.Model):
first_name = models.CharField(max_length=200, unique=True)
last_name = models.CharField(max_length=200, unique=True)
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
email = models.EmailField(max_length=100)
def __str__(self):
return self.first_name + ' ' + self.last_name
class Attendance(models.Model):
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
employee = models.ForeignKey('Employee', on_delete=models.CASCADE, )
attendance = models.CharField(max_length=8, choices=attendance_choices, blank=True)
Views
class Attendancecreate(CreateView):
model = Attendance
form_class = Attendanceform
success_url = '/dashboard/'
def get_context_data(self,** kwargs):
context = super(Attendancecreate, self).get_context_data(**kwargs)
context['formset'] = AttendanceFormset(queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=self.request.user.email), initial=[{'employee': employee} for employee in self.get_initial()['employee']])
return context
def get_initial(self):
email = self.request.user.email
head_of_department = Head_of_department.objects.get(email=email)
initial = super(Attendancecreate , self).get_initial()
initial['employee'] = Employee.objects.filter(head_of_department=head_of_department)
return initial
def post(self, request, *args, **kwargs,):
formset = AttendanceFormset(request.POST,queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=self.request.user.email), initial=[{'employee': employee} for employee in self.get_initial()['employee']])
if formset.is_valid():
return self.form_valid(formset)
def form_valid(self,formset):
instances = formset.save(commit=False)
for instance in instances:
instance.head_of_department = get_object_or_404(Head_of_department, email=self.request.user.email)
instance.save()
return HttpResponseRedirect('/dashboard/')
Forms
class Attendanceform(ModelForm):
class Meta:
model = Attendance
widgets = {'employee' : HiddenInput}
fields = ('employee','attendance','hod')
AttendanceFormset = inlineformset_factory(Head_of_department,Attendance,form=Attendanceform,fields=('attendance','employee'))
Template
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form.employee.initial }} {{ form.employee}} {{ form.attendance }}
<br><br>
{% endfor %}

Drop down field shows values of all users

I have a form field in Django called Label. My problem is that the field shows the Labels of all users while I only want to show self created labels.
models
class Label(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
tag = models.CharField(max_length=25)
def __str__(self):
return self.tag
class Birthday(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=25, default="")
day = models.DateField()
label = models.ForeignKey(Label, on_delete=models.SET_NULL, default=0, null=True, blank=True)
def __str__(self):
return self.name
forms
class BirthdayForm(forms.ModelForm):
class Meta:
model = Birthday
fields = ('name', 'day', 'label')
class LabelForm(forms.ModelForm):
class Meta:
model = Label
fields = ('tag',)
template
<form method="POST">{% csrf_token %}
<table border="0">
{{ form }}
</table>
<button class="submitButton" type="submit">Submit</button>
</form>
This is the view for this template
view
#login_required
def index(request):
if request.method == "POST":
form = BirthdayForm(request.POST)
if form.is_valid():
birthday = form.save(commit=False)
birthday.user = request.user
birthday.save()
return redirect('index')
else:
#default_labels("Friend", request)
#default_labels("Family", request)
form = BirthdayForm()
birthday = Birthday.objects.filter(user=request.user)
username = request.user
return render(request, 'bd_calendar/index.html', {'form': form, 'birthday': birthday, 'username': username })

Properly configuring user registration using 2 forms

I am trying to submit 2 forms at a time to create my student user in Django. I have been struggling for a while now, but I think I'm finally closing to an end on how to manage 2 forms at a time for my users to register. But when I fill in the data and then click register, I get error: "This field is required." under my student ID field. What am I doing wrong ? Thanks.
class UserForm(forms.ModelForm):
password = forms.CharField(
label='Password',
max_length=32,
required=True,
widget=forms.PasswordInput,
)
password2 = forms.CharField(
label='Confirm',
max_length=32,
required=True,
widget=forms.PasswordInput,
help_text="Make sure they match!",
)
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name', 'password', 'password2')
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = ('phone', 'student_ID', 'photo')
class User(AbstractUser):
pass
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
student_ID = models.CharField(unique=True, max_length=14,
validators=[RegexValidator(regex='^.{14}$',
message='The ID needs to be 14 characters long.')])
photo = models.ImageField(upload_to='students_images')
phone = models.CharField(max_length=15, )
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_user_student(sender, instance, created, **kwargs):
if created:
Student.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_student(sender, instance, **kwargs):
instance.profile.save()
#csrf_protect
def student_register(request):
if request.method == 'POST':
form1 = UserForm(request.POST, prefix="user")
form2 = StudentForm(request.POST, prefix="profile")
if form1.is_valid() and form2.is_valid():
# create initial entry for user
username = form1.cleaned_data["username"]
password = form1.cleaned_data["password"]
new_user = User.objects.create_user(username, password)
new_user.save()
# create entry for UserProfile (extension of new_user object)
profile = form2.save(commit=False)
profile.user = new_user
profile.save()
return HttpResponseRedirect("index")
else:
form1 = UserForm(prefix="user")
form2 = StudentForm(prefix="profile")
c = {
'form1': form1,
'form2': form2,
}
return render(request, "student_signup_form.html", c)
<form method="post">
{% csrf_token %}
<p style="color:red"> {{ form.username.errors }}</p>
{{ form1.as_p }}
{{ form2.as_p }}
<input type="submit" value="Create the account">
</form>
First, you don't need #csrf_protect if you use {% csrf_token %} in template.
Second, you are probably getting student_ID required because you are trying to create a profile in signal providing just the user.
You can change your models like this:
models.py
class User(AbstractUser):
pass
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
student_ID = models.CharField(unique=True, max_length=14,
validators=[RegexValidator(regex='^.{14}$', message='The ID needs to be 14 characters long.')], null=True, blank=True, default=None)
photo = models.ImageField(upload_to='students_images', null=True, blank=True, default=None)
phone = models.CharField(max_length=15, null=True, blank=True, default=None)
def __str__(self):
return self.user.username
views.py
def student_register(request):
data = dict()
if request.method == 'POST':
form1 = UserForm(request.POST)
form2 = StudentForm(request.POST, request.FILES)
if form1.is_valid() and form2.is_valid():
cd1 = form1.cleaned_data
username = cd1["username"]
password = cd1["password"]
new_user = User.objects.create_user(username, password)
new_user.save()
cd2 = form2.cleaned_data
phone = cd2['phone']
student_ID = cd2['student_ID']
photo = cd2['photo']
Student.objects.create(user=new_user, phone=phone, student_ID=student_ID, photo=photo)
return redirect('index')
else:
form1 = UserForm()
form2 = StudentForm()
data['form1'] = form1
data['form2] = form2
return render(request, "student_signup_form.html", data)
template
<form action='' method="POST" enctype="multipart/form-data">
{% csrf_token %}
<p style="color:red"> {{ form.username.errors }}</p>
{{ form1.as_p }}
{{ form2.as_p }}
<input type="submit" value="Create the account">
</form>
You can make StudentForm class a derived class of UserForm by declaring like class StudentForm(UserForm): and just submit one form that is StudentForm
It can be done like this also,
#models.py
from django.contrib.auth.models import User
class Student(models.Model):
user = models.OneToOneField(User)
student_ID = models.CharField(unique=True, max_length=14,validators=[RegexValidator(regex='^.{14}$',message='The ID needs to be 14 characters long.')])
photo = models.ImageField(upload_to='students_images')
phone = models.CharField(max_length=15, )
User.student = property(lambda u: Student.objects.get_or_create(user=u)[0])
#forms.py
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = ('student_ID', 'photo', 'phone', )
#views.py
def student_register(request):
template_name = "student_signup_form.html"
context = {}
if request.method == 'POST':)
form = StudentForm(request.POST, instance=request.user.student)
if form.is_valid():
object = request.user.student
object.student_ID= form.cleaned_data['student_ID']
object.photo = form.cleaned_data['photo']
object.phone = form.cleaned_data['phone']
object.save()
return HttpResponseRedirect('index')
else:
form = StudentForm()
context['form'] = form
return render(request, template_name, context)

Categories