How add values to child form by parent ID? - python

This is my model
class User(models.Model):
name = models.CharField(max_length=50)
surname = models.CharField(max_length=50)
class Phone(models.Model):
user = models.ForeignKey(Osoba, editable=False, related_name='phone', on_delete=models.CASCADE)
phone = models.CharField(max_length=50)
and i want to add phone to current User selected by ID and display it on site
i have tried that
def create_phone(request, id):
user = User.objects.get(id=id)
form = PhoneForm(request.POST or None, instance=user)
if form.is_valid():
form.save()
return redirect('list_users')
return render(request, 'index-phone.html', {'form': form})
But it doesnt work, when i click button, its not creating new Phone
My urls
urlpatterns = [
path('', list_users, name='list_users'),
path('new', create_user, name='create_user'),
path('/<int:id>/update', update_user, name='update_user'),
path('/<int:id>/delete', delete_user, name='delete_user'),
path('/<int:id>/', create_phone, name='create_phone')
]

I'm not sure about the content of your PhoneForm class, but I would guess that is a form to create and edit a Phone object. When instantiating a new PhoneForm the instance parameter should either be an existing Phone instance, or None.
You should set the user of the Phone instance another way, either by making it a field on the PhoneForm, or by manually setting the user.
This would be correct:
def create_phone(request, id):
user = User.objects.get(id=id)
form = PhoneForm(request.POST or None)
if form.is_valid():
# Setting commit to False does not save the object to the database yet.
# We do this because we still want to edit the object.
phone = form.save(commit=False)
phone.user = user
phone.save()
return redirect('list_users')
return render(request, 'index-phone.html', {'form': form})

Related

Django pass user id before form is submitted

I am working on a Django-Tenant (Multi-Tenant) application. I am writing the script to create the subdomain. I am trying to get it to where created_by is set to the current users id that is logged in. How can I get current user ID to populate the created_by field?
views.py
class CreatePortal(View):
def get(self, request):
form = CreatePortalForm()
return render(request, "registration/create_portal.html", {"form": form})
def post(self, request):
form = CreatePortalForm(request.POST)
if form.is_valid():
getDomain = form.cleaned_data.get('name')
instance = form.save(commit=False)
tenant = Client(schema_name=getDomain, name=getDomain, created_by=**[NEED USER ID HERE]**)
tenant.save()
domain = Domain()
domain.domain = (getDomain + ".example.com:8000")
domain.tenant = tenant
domain.is_primary
domain.save()
with schema_context(tenant.schema_name):
instance.save()
redirect = 'http://' + getDomain + '.example.com:8000'
return HttpResponseRedirect(redirect)
return render(request, "registraton/create_portal.html", {"form": form})
forms.py
class CreatePortalForm(forms.ModelForm):
class Meta:
model = Client
fields = ["name"]
models.py
This is the line that I am working with models.py
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
I also get an error if it is not User type and if I do not pass an actual number for id, Field 'id' expected a number but got datetime.datetime
I have tried this as well:
user = request.user.id
tenant = Client(schema_name=getDomain, name=getDomain, created_by=user)
but then get this error:
Cannot assign "1": "Client.created_by" must be a "User" instance.
I am not sure how to pass the current logged in Users ID to populate the created_by form field. Any and all help is appreciated. I am still learning Django.

Submit a form only once in Django

I am trying to make the user submit a form only once. I have a /dashboard page which is shown after submitting the /petform. But, I want the user to submit the form only once after logging in and other times it should redirect to the /dashboard directly (or show a message that "form already submitted").
models.py
class PetFormData(models.Model):
abstract = True
name = models.CharField(max_length=100)
age = models.IntegerField()
breed = models.CharField(max_length=100)
amount_spent = models.CharField(max_length=100, choices=AMOUNT_CHOICES)
pincode = models.CharField(max_length=15)
services_required = models.CharField(max_length=100, choices=SERVICE_CHOICES)
auth_user_email = models.ForeignKey(User, on_delete=models.CASCADE)
form_submitted = models.BooleanField(default=False)
views.py
#login_required
def showformdata(request):
form = PetForm(request.POST)
if request.method == 'POST':
if not PetFormData.form_submitted and user == PetFormData.auth_user_email:
PetFormData.form_submitted = True
print(PetFormData.form_submitted)
if form.is_valid():
user = request.user
nm = form.cleaned_data['name']
age = form.cleaned_data['age']
breed = form.cleaned_data['breed']
am_sp = form.cleaned_data['amount_spent']
pin = form.cleaned_data['pincode']
ser_req = ','.join(form.cleaned_data['services_required'])
model_pet_form = PetFormData(name=nm, age=age, breed=breed, amount_spent=am_sp, pincode=pin,
services_required=ser_req, auth_user_email=user)
model_pet_form.save()
print(session_data)
return redirect('/dashboard')
else:
print(PetFormData.form_submitted)
return HttpResponse('Form already submitted', content_type="text/plain")
else:
form = PetForm()
return render(request, 'petform.html', {'form': form})
Successfully submitting the form once presumably stores something in the database. A subsequent visit to that page can interrogate the database, discover it has already been done, and display the appropriate next page.
Something like this (I don't fully understand your problem)
if PetFormData.objects.filter( auth_user_email = request.user).exists() :
return redirect('/dashboard')
# OK, user hasn't submitted yet.

associate the user with the post Django and MySQL

I am trying to associate the user with the post. I have two models students is for user and sublists is for user posts with a foreign key(author). I am using MySQL database and using forms to store data into them. when my form.author execute in my HTML file it gives me a list of ids for all users in the databse but I am already logged in and i want to post as the logged in user without choosing. If remove it says my form is not valid which make sense since im not inputing for form.author.Since I'm using MySQL, I'm not using the built-in User authentication method, but instead comparing both email and password with the login form input. Spend too much time on this but hard to get around with this one. Any help would be appreciated
my views.py look like this
def addnew(request):
if request.method == 'POST':
form = Sublist(request.POST)
if form.is_valid():
try:
form.save()
messages.success(request, ' Subscirption Saved')
name = sublist.objects.get(name=name)
return render (request, 'subscrap/main.html', {'sublist': name})
except:
pass
else:
messages.success(request, 'Error')
pass
else:
form = Sublist()
return render(request, 'subscrap/addnew.html', {'form': form})
#login_required(login_url='login')
#cache_control(no_cache=True, must_revalidate=True, no_store=True)
def main(request):
return render(request, 'subscrap/main.html')
def mod(request):
student = students.objects.all()
return render(request, 'subscrap/mod.html' , {'students': student})
My Models.py
class students(models.Model):
fname = models.CharField(max_length=50)
lname = models.CharField(max_length=50)
password = models.CharField(max_length = 50 , null = True)
passwordrepeat = models.CharField(max_length = 50, null = True)
email = models.EmailField(max_length=150)
class Meta:
db_table = "students"
class sublist(models.Model):
author = models.ForeignKey(students, related_name='sublist' ,on_delete=models.CASCADE)
name = models.CharField(max_length=150)
cost = models.IntegerField(default = 0)
renewalcycle = models.IntegerField(default = 0)
class Meta:
db_table = "sublist"
Since I'm using forms here's my forms.py
lass StudentForm(forms.ModelForm):
class Meta:
model = students
fields = "__all__"
class Studentlogin(forms.Form):
email = forms.EmailField(max_length=150)
password = forms.CharField(max_length = 50, widget=forms.PasswordInput)
class Sublist(forms.ModelForm):
class Meta:
model = sublist
fields = "__all__"
Exclude the Author from the Sublist form:
class Sublist(forms.ModelForm):
class Meta:
model = sublist
exclude = ['author']
In the addnew method, you associate the .instance.author with the request.user:
#login_required(login_url='login')
def addnew(request):
if request.method == 'POST':
form = Sublist(request.POST)
if form.is_valid():
form.instance.author = request.user
form.save()
messages.success(request, ' Subscirption Saved')
return redirect('some_view')
else:
messages.error(request, 'Error')
else:
form = Sublist()
return render(request, 'subscrap/addnew.html', {'form': form})
Note: Models in Django are written in PascalCase, not snake_case,
so you might want to rename the model from sublist to Sublist.
Note: Usually a Form or a ModelForm ends with a …Form suffix,
to avoid collisions with the name of the model, and to make it clear that we are
working with a form. Therefore it might be better to use SublistForm instead of
Sublist.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the students directly. For more information you can see the referencing the User model section of the documentation.

Django ModelForm: Defining a value not passed into the template

I have a ModelForm, and I want to only pass some of the fields into the template. I would like to save one particular field to define after the POST request has been sent. Here is the ModelForm:
class CreateListingForm(ModelForm):
class Meta:
model = models.ListingModel
fields = ['name', 'image', 'description', 'price', 'category']
widgets = {
'description': Textarea()
}
And here is the Model:
class ListingModel(models.Model):
name = models.CharField(max_length=30)
image = models.ImageField(upload_to='images')
description = models.CharField(max_length=1000)
price = models.PositiveIntegerField()
category = models.CharField(max_length=15)
objects = models.Manager()
owner = models.CharField(max_length=100)
In the next code block, I am attempting to define the owner field according to the current user logged in (request.user.username):
#login_required(redirect_field_name=login_view)
def create_listing(request):
if request.method == "GET":
return render(request, "auctions/createlisting.html", {
"CreateListingForm": forms.CreateListingForm()
})
elif request.method == "POST":
form = forms.CreateListingForm(request.POST, request.FILES)
if form.is_valid():
try:
form.owner = request.user.username
print(form.owner)
form.save(commit=True)
except Exception:
return HttpResponseRedirect(reverse("create_listing_error"))
return HttpResponseRedirect(reverse("index")) #TODO
Now, when I say print(form.owner), the result is correct. However when I save the ModelForm, the owner field is left blank. Am I not defining the value of the owner field correctly?
You should not confuse the ModelForm with the instance it is wrapping. The fact that it prints something for form.owner is not that strange, you first set an attribute named .owner, an attribute that did not exists before. You should set the .owner of the .instance of the form:
#login_required(redirect_field_name=login_view)
def create_listing(request):
if request.method == 'POST':
form = forms.CreateListingForm(request.POST, request.FILES)
if form.is_valid():
form.instance.owner = request.user.username
form.save()
return redirect('name-of-some-view')
else:
form = forms.CreateListingForm()
return render(request, 'auctions/createlisting.html', {
'CreateListingForm': form
})
Where 'name-of-some-view' should be replaced by the name of some view to which you redirect in case the form was valid.
You should however consider changing the CharField of owner to a ForeignKey [Django-doc]. Imagine that later the user changes their username, then your ListingModels do no longer refer to a real user.

Django, save ModelForm

I have created a model Student which extends from the Django User and is a foreign key to another model while it has an integer field called year. What i'm trying to do is to save a form, which has 2 fields. The one is the course id and the another one is the the integer field year. When I'm clicking submit, i'm getting an error Cannot assign "u'2'": "Student.course" must be a "Course" instance.
models.py
class Student(models.Model):
user = models.OneToOneField(User)
course = models.ForeignKey(Course)
year = models.IntegerField(validators=[MinValueValidator(1),
MaxValueValidator(7)])
view.py
def step3(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
form.save()
return render_to_response("registration/complete.html", RequestContext(request))
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
forms.py
class SelectCourseYear(forms.ModelForm):
course = forms.CharField()
year = forms.IntegerField(required=True)
class Meta:
model = Student
fields = ['user', 'course', 'year']
You dont need to redefine fields in the ModelForm if you've already mentioned them in the fields attribute. So your form should look like this -
class SelectCourseYear(forms.ModelForm):
class Meta:
model = Student
fields = ['course', 'year'] # removing user. we'll handle that in view
And we can handle the form with ease in the view -
def step3(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
student = form.save(commit=False)
# commit=False tells Django that "Don't send this to database yet.
# I have more things I want to do with it."
student.user = request.user # Set the user object here
student.save() # Now you can send it to DB
return render_to_response("registration/complete.html", RequestContext(request))
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
course has to be an instance of a Course model, not just the primary key of the instance. You can still accept an id in the form as a text input, but you're going to need to retrieve the actual course instance and assign the value.
You'll need to verify that the course id is valid, so putting that code into the clean method isn't a bad idea. Notice also how the course field is excluded here? Otherwise the form will expect it to be present. You also don't need to re-define the year field, as the ModelForm will inherit that field from the Student model.
# forms.py
class SelectCourseYear(forms.ModelForm):
class Meta:
model = Student
exclude = ['user', 'course']
course_id = forms.IntegerField()
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(SelectCourseYear, self).__init__(*args, **kwargs)
def clean_course_id(self):
course_id = self.cleaned_data.get('course_id')
try:
self.course = Course.objects.get(pk=course_id)
except Course.DoesNotExist:
raise forms.ValidationError('Sorry, that course id is not valid.')
return course_id
def save(self, commit=True):
instance = super(SelectCourseYear, self).save(commit=False)
instance.course = self.course
instance.user = self.user
if commit:
instance.save()
return instance
# views.py
def step3(request):
if request.method == 'POST':
form = SelectCourseYear(request.POST or None, user=request.user)
if form.is_valid():
form.save()
return render_to_response("registration/complete.html",
RequestContext(request))
return render(request, 'registration/step3.html',)
Now, when you call .save() on the model, the course field will be assigned an instance of Course

Categories