How to set a foreignkey field in views? - python

I'm trying to save the customer field on the Test model, I'm not getting any errors but it's not saving the field either, how do I fix it?
Models
class Test(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
email = models.EmailField(max_length=200, blank=False)
Forms
class TestForm(forms.Form):
email = forms.EmailField(required=True)
class Meta:
model = Test
fields = ("email")
def save(self, commit=False):
# Creating the customer object
Test.objects.create(email=self.cleaned_data['email'])
Views
def test_view(request):
customer = request.user.customer
if form.is_valid():
email = form.cleaned_data['email']
customer = customer
form.save()

You can use cleaned_data to save the ModelForm.
forms.py
class TestForm(forms.ModelForm):
class Meta:
model = Test
fields = ["email"]
Assuming, you have request method POST.
views.py
def test_view(request):
if request.method=="POST":
form=TestForm(request.POST)
customer = request.user.customer
if form.is_valid():
email = form.cleaned_data['email']
test=Test(customer=customer,email=email)
test.save()

You need to use a ModelForm, then save the object without commiting, edit the customer of the object, then commit.
class TestForm(forms.ModelForm):
class Meta:
model = Test
fields = ["email", ]
def test_view(request):
customer = request.user.customer #I'm not sure this line is right, but I can't see all your models
if form.is_valid():
test = form.save(commit=False)
test.customer = customer
test.save()

Related

How to store user details without asking the user?

I am trying to store user details with the PhoneBook and Contacts he creates so that I will be able to show the PhoneBook and Contacts that have been created by them.
I don't want the user to explicitly add the details himself. It should be handled by the backend.
I am successfully able to store the user details with the PhoneBook he created, but when I try to do the same thing with contacts, I am getting an attribute error.
models.py
class PhoneBook(models.Model):
name = models.CharField(max_length=10, blank=False)
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.name
class Contact(models.Model):
first_name = models.CharField(max_length=50, blank=False)
last_name = models.CharField(max_length=50, blank=False)
phone_number = models.CharField(max_length=13, blank=False, unique=True)
phone_book = models.ManyToManyField(PhoneBook, related_name='phone_book')
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.phone_number
views.py
#login_required
def create_phone_book(request):
form = CreatePhoneBookForm(request.POST or None)
form.instance.user = request.user
if form.is_valid():
form.save()
form = CreatePhoneBookForm()
context = {'form': form}
return render(request, 'CallCenter/create_phone_book.html', context)
#login_required
def add_to_phone_book(request):
form = AddToPhoneBookForm(request.POST or None)
form.instance.user = request.user
if form.is_valid():
form.save()
form = AddToPhoneBookForm()
context = {'form': form}
return render(request, 'CallCenter/add_to_phone_book.html', context)
forms.py
class AddToPhoneBookForm(forms.Form):
class Meta:
model = Contact
fields = ['first_name', 'last_name', 'phone_number', 'phone_book']
class CreatePhoneBookForm(forms.Form):
class Meta:
model = PhoneBook
fields = ['name']
The error I am getting is
AttributeError at /call-center/add/
'AddToPhoneBookForm' object has no attribute 'instance'
You should make use of a ModelForm, not a Form. A Form itself has no instance, so you can define:
class AddToPhoneBookForm(forms.ModelForm):
class Meta:
model = Contact
fields = ['first_name', 'last_name', 'phone_number', 'phone_book']
class CreatePhoneBookForm(forms.ModelForm):
class Meta:
model = PhoneBook
fields = ['name']
Usually when you make a successful post request, you should redirect, to implement the Post/Redirect/Get pattern [wiki].

Assign Foreign Key Value after creating ( Logged In User )

I have a createview using CBV
class StudentCreate(LoginRequiredMixin, CreateView):
login_url = '/signin/'
model = Student
fields = ['first_name', 'last_name' ]
success_url = '/dashboard/'
Respective models.py
class Class_teacher(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
standard = models.IntegerField()
division = models.CharField(max_length=1)
subject = models.CharField(max_length=200)
email = models.CharField(max_length=30)
class Student(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
classteacher = models.ForeignKey('Class_teacher', on_delete=models.SET_NULL,blank=True, null=True )
The webapp has a login feature . When the user ( classteacher ) login they can add students. What I want is classteacher field in Student(model Form ) should be automatically set as user which is the classteacher. ( Classteacher ) and should be saved in the db after creating the student. Classteacher model is updated with respective required fields .
Look here for the various methods of a CreateView that you can override.
In your case, you want to override the form_valid() method, which is called when the new Student will be saved.
from django.shortcuts import get_object_or_404
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.classteacher = get_object_or_404(Class_teacher, email=self.request.user.email)
self.object.save()
return super().form_valid(form)
You need to define your own form_valid().
I assume the Teacher as a one to one Relationship with your User model.
def form_valid(self, form):
student = form.save(commit=False)
#retrieve the current logged_in teacher, of course you have to be sure this view is only accesible for teachers (in dispatch for exemple)
self.object.classteacher = self.request.user.teacher
self.object.save()
return super(StudentCreate, self).form_vaild(form)
#bonus the dispatch
def dispatch(self, request, *args, **kwargs):
#get the loged in user
if request.user.teacher:
return super(StudentCreate, self).dispatch(request, *args, **kwargs)
else:
raise Http404

Django modelform submission with relational data

I have a django modelform that creates a new listing in my post app, I would like to associate this with a company id, which is an account type in my account app.
The account_company db table (postgresql) has a user_id field which is the pk of User. the post_listing table will have a company field which I think should be the pk of account_company.
As I am attempting to use modelforms for all forms, I am having an issue with making this association.
# models.py
class Listing(models.Model):
title = models.CharField(max_length=200)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
...
# forms.py
class newListingForm(forms.ModelForm):
class Meta:
model = Listing
fields = ('title'...)
def __init__(self, user, *args, **kwargs):
super(newListingForm, self).__init__(*args, **kwargs)
self.fields['company'].queryset = Company.objects.filter(pk__user_id=user.id)
# above i am trying to filter the AutoField to the `company pk` where `user_id` is equal to `request.user.id`
# views.py
def post(request):
if request.method == 'POST':
form = newListingForm(request.user, request.POST)
if form.is_valid():
listing = form.save(commit=False)
listing.user = request.user
listing.save()
else:
form = newListingForm(request.user)
return render(request, 'post/post.html', {'form': form})
The debug error i get is:
Unsupported lookup 'user_id' for AutoField or join on the field not permitted.
Updated
#accounts model.py
...
class Company(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
photo = models.ImageField(upload_to='images/%Y/%m/%d/', null=True)
description = models.TextField(null=True)

excluding id field in an inline formset when saving

I have two models, connected by a foreign key. One is an inline formset. For some reason, the formset ids are being identified as Primary Keys in the database, and every time the form is submitted, the table belonging to the formset is basically overwritten. When saving, how do I ignore the formset ids
models.py
class Student(models.Model):
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=40)
email = models.EmailField()
class Courses(models.Model):
student = models.ForeignKey(Student)
course_name = models.CharField(max_length=40)
start_time = models.TimeField()
forms.py
class CoursesForm(forms.ModelForm):
class Meta:
model = Courses
exclude = ("student",)
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = "__all__"
views.py
...
def post(self, request, *args, **kwargs):
sform = StudentForm(request.POST, instance=Student())
CourseSchedule = inlineformset_factory(Student, Courses, form=CoursesForm, can_delete=False, extra=0, min_num=1)
cforms = CourseSchedule(data=request.POST)
if sform.is_valid() and cforms.is_valid():
sform_obj = sform.save()
for cform in cforms.forms:
cform_obj = cform.save(commit=False)
cform_obj.student = sform_obj
cform_obj.save()
....
I figured it out.. My formset data was persisting after submission. I had to declare an empty queryset in the basemodelformset.

Extending the User Model

I want to extend the User model with custom fields, but I have a little problem
I started creating a Profiles model, with the extra fields that I want:
"models.py":
class Profiles(models.Model):
user = models.OneToOneField(User)
url = models.URLField()
avatar = models.ImageField(upload_to='profile_avatar')
def __str__(self):
return self.user.username
Then, I made a custom UserCreationForm, and I override the save function with the data that I want in the original User model:
"forms.py":
class UserForm(UserCreationForm):
first_name = forms.CharField()
last_name = forms.CharField()
email = forms.EmailField()
url = forms.URLField()
avatar = forms.ImageField()
class Meta:
model = User
fields = ("username", "first_name", "last_name", "email",)
def save(self, commit=True):
user = super(UserForm, self).save(commit=False)
user.first_name = self.cleaned_data["first_name"]
user.last_name = self.cleaned_data["last_name"]
user.email = self.cleaned_data["email"]
if commit:
user.save()
return user
Finally, I made a FormView to create the new user and save the extra data in the custom Profiles model:
"views.py":
class SignIn(FormView):
template_name = 'index/signin.html'
form_class = UserForm
success_url = reverse_lazy('signin')
def form_valid(self, form):
user = form.save()
profile = Profiles()
profile.user = user
profile.url = form.cleaned_data['url']
profile.avatar = form.cleaned_data['avatar']
profile.save()
return super(SignIn, self).form_valid(form)
The first user that I sign in with the UserForm creates correctly and the profile model is created too, but after the second sign in, Django prints this Integrity Error: '(1062, "Duplicate entry '' for key 'mail'")'; creating correctly the user, but no the profile one
Do you have any idea of what I'm doing bad?
Thank you

Categories