Pass Foreignkey from User Input to DB - python

I'm trying to have user input the data and store into DB and map with the other data.
Model:
class Code(models.Model):
name = models.CharField(max_length=4, default=None, blank=True, unique=True)
Within the Model, there is another class
class Pull(models.Model):
code_pull = models.ForeignKey(Code, on_delete=models.SET_NULL, null=True)
How to display to call in the Form and View, so that data is pass when user input the data in the input field.
Form
class Code_Form(forms.ModelForm):
class Meta:
model = Code
fields = ('name',)
class Pull_Form(forms.ModelForm):
class Meta:
model = Pull
fields = ('code_pull', 'data1', 'prefix',)
#Inital Value is NULL
def __init__(self, *args, **kwargs):
super(Pull_Form, self).__init__(*args, **kwargs)
self.fields['code_pull'].queryset = CODE.objects.none()
if 'code_pull' in self.data:
c = self.data.get('code_pull')
self.fields['code_pull'].queryset = CODE.objects.filter(name=c)
#print(self.fields['code_pull'].queryset)
I updated the code for the FORM, so that it initial the value from the CODE_form, Still Error, as the code field is empty
Here is the VIEW:
def InputData(request, *args, **kwargs):
form = Pull_Form(request.POST or None)
if request.method == 'POST':
if form.is_valid():
data_add = form.save(commit=False)
data_add.code = form.cleaned_data['code_pull']
data_add.save()
messages.success(request, 'Successfully')
else:
messages.error(request, form.errors)
return render(request, template_name, {'form': form })
ERROR: Not able to add the data as the field for the code is not selected when submitting the form.
ERROR CODE: code - Select a valid choice. That choice is not one of the available choices.
{{ messages }}
<form id="form1" class="post-form" role=form method="POST" action=".">{% csrf_token %}
<input id="code_pull" class="form-control" type="text" maxlength="4" required></input>
<label for="code_pull">Code</label>
<button type="submit" class="btn">Save</button>
</form>
Thank you for the help in advance.

Django forms use the name attribute in HTML controls to capture form data.
<input id="code" name="code" class="form-control" type="text" maxlength="4" required></input>
I only added name="code". this should make it work.

Related

How to Update ImageField in Django?

i am new in Django. i am having issue in updating ImageField.i have following code
in models.py
class ImageModel(models.Model):
image_name = models.CharField(max_length=50)
image_color = models.CharField(max_length=50)
image_document = models.ImageField(upload_to='product/')
-This is My forms.py
class ImageForm(forms.ModelForm):
class Meta:
model = ImageModel
fields = ['image_name', 'image_color' , 'image_document']
in Html file (editproduct.html)
<form method="POST" action="/myapp/updateimage/{{ singleimagedata.id }}">
{% csrf_token %}
<input class="form-control" type="text" name="image_name" value="{{ singleimagedata.image_name}}">
<input class="form-control" type="file" name="image_document">
<button type="submit" class="btn btn-primary">UPDATE PRODUCT</button>
</form>
-myapp is my application name. {{singleimagedata}} is a Variable Containing all fetched Data
-urls.py
urlpatterns = [
path('productlist', views.productlist, name='productlist'),
path('addproduct', views.addproduct, name='addproduct'),
path('editimage/<int:id>', views.editimage, name='editimage'),
path('updateimage/<int:id>', views.updateimage, name='updateimage'),
]
and Here is My views.py
def productlist(request):
if request.method == 'GET':
imagedata = ImageModel.objects.all()
return render(request,"product/productlist.html",{'imagedata':imagedata})
def addproduct(request):
if request.method == 'POST':
form = ImageForm(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.add_message(request, messages.SUCCESS, 'Image Uploaded')
return redirect('/myapp/productlist')
else:
imageform = ImageForm()
return render(request, "product/addproduct.html", {'imageform': imageform})
def editimage(request, id):
singleimagedata = ImageModel.objects.get(id=id)
return render(request, 'product/editproduct.html', {'singleimagedata': singleimagedata})
def updateimage(request, id): #this function is called when update data
data = ImageModel.objects.get(id=id)
form = ImageForm(request.POST,request.FILES,instance = data)
if form.is_valid():
form.save()
return redirect("/myapp/productlist")
else:
return render(request, 'demo/editproduct.html', {'singleimagedata': data})
My image Upload is working fine.i can not Update image while updating data.rest of the data are updated.i don't know how to update image and how to remove old image and put new image into directory.
I think you missed the enctype="multipart/form-data", try to change:
<form method="POST" action="/myapp/updateimage/{{ singleimagedata.id }}">
into;
<form method="POST" enctype="multipart/form-data" action="{% url 'updateimage' id=singleimagedata.id %}">
Don't miss also to add the image_color field to your html input.
Because, in your case the image_color field model is designed as required field.
To remove & update the old image file from directory;
import os
from django.conf import settings
# your imported module...
def updateimage(request, id): #this function is called when update data
old_image = ImageModel.objects.get(id=id)
form = ImageForm(request.POST, request.FILES, instance=old_image)
if form.is_valid():
# deleting old uploaded image.
image_path = old_image.image_document.path
if os.path.exists(image_path):
os.remove(image_path)
# the `form.save` will also update your newest image & path.
form.save()
return redirect("/myapp/productlist")
else:
context = {'singleimagedata': old_image, 'form': form}
return render(request, 'demo/editproduct.html', context)
I had a similar issue while updating the profile_pic of user. I solved this with the following code I think this might help:
Models.py
class Profile(models.Model):
# setting o2o field of user with User model
user_name = models.OneToOneField(User, on_delete=models.CASCADE, blank=True, null=True)
first_name = models.CharField(max_length=70, null=True, blank=True)
last_name = models.CharField(max_length=70, null=True, blank=True)
profile_pic = models.ImageField(upload_to="images", blank=True, null=True,)
def __str__(self):
return str(self.user_name)
forms.py
class ProfileEditForm(ModelForm):
class Meta:
model = Profile
fields = '__all__'
# excluding user_name as it is a one_to_one relationship with User model
exclude = ['user_name']
views.py
#login_required(login_url='login')
def edit_profile(request, id):
username = get_object_or_404(Profile, id=id)
extended_pro_edit_form = ProfileEditForm(instance=username)
if request.method == "POST":
extended_pro_edit_form = ProfileEditForm(request.POST, request.FILES, instance=username)
if extended_pro_edit_form.is_valid():
extended_pro_edit_form.save()
next_ = request.POST.get('next', '/')
return HttpResponseRedirect(next_)
context = {'extended_pro_edit_form': extended_pro_edit_form}
return render(request, 'edit_profile.html', context)
edit-profile.html
<form action="" method="post"
enctype="multipart/form-data">
{% csrf_token %}
{{ extended_pro_edit_form.as_p }}
{{ extended_pro_edit_form.errors }}
<!--To redirect user to prvious page after post req-->
<input type="hidden" name="next" value="{{ request.GET.next }}">
<button type="submit">UPDATE</button>
</form>
Answer from #binpy should solve your problem. In addition to your second answer, you could do:
def updateimage(request, id): #this function is called when update data
data = ImageModel.objects.get(id=id)
form = ImageForm(request.POST,request.FILES,instance = data)
if form.is_valid():
data.image_document.delete() # This will delete your old image
form.save()
return redirect("/myapp/productlist")
else:
return render(request, 'demo/editproduct.html', {'singleimagedata': data})
Check delete() method on django docs.
some times something like cached old image is not replaced in the front-end so you might just need to forces refresh by pressing CTRL + F5 or clear your browsing history.
the answer given by #binpy is a needed update so that the files are passed to the back-end.

How set initial values to fields on form?

enter code hereI'm having some problems to solve a problem. I have a template, which allows the user to change some of their account settings. My goal is to initialize the form, with the user's default values, and he can keep or change them (by after submit form). However, until now the page does not render these values. I'm using a class based view, CreateView, for this purpose.
My code is listed below.
Here, is my CreateView.
class DetailUserInfoView(LoginRequiredMixin ,CreateView):
model = CustomUser.CustomUser
template_name = 'users/InfoUser.html'
login_url = settings.LOGOUT_REDIRECT_URL
context_object_name = 'user'
form_class = CustomUserChangeForm
def get_object(self):
self.model = self.request.user
return self.model
def get_initial(self):
initial = super(DetailUserInfoView, self).get_initial()
initial = initial.copy()
initial[config.USERNAME] = self.request.user.username
initial[config.FIRST_NAME] = self.request.user.first_name
initial[config.LAST_NAME] = self.request.user.last_name
return initial
def get_form_kwargs(self):
kwargs = {'initial': self.get_initial()}
return kwargs
def get_context_data(self, **kwargs): #GET OBJECT ACTS AFTER THAN GET_OBJECT --> EXAMPLE OF GET_CONTEXT_DATA, I DIDN'T NEED THIS
context = super(DetailUserInfoView, self).get_context_data(**kwargs)
context['username'] = self.request.user.username
return context
Here the form.
class CustomUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = CustomUser.CustomUser
fields = ('email', 'password', 'first_name', 'last_name', 'username', 'userType')
And finally an extract of template.
<div id="infoMayOverride">
<form class="getOverridedValues" method="post">
{% csrf_token %}
<div id="usernameData">
<label>{{ form.username.label_tag }}</label> <!--MODEL ON CREATEUSERVIEW IS CUSTOMUSER, AND NOW I NEED TO USE THIS FIELDS AND INHERITED FIELDS FROM USER CLASS-->
<input type="text" id="usernameInput" value="{{ form.username }}">
</div>
<div id="firstNameData">
<label>{{ form.first_name.label_tag }}</label>
<input type="text" id="firstNameInput" value="{{ form.first_name }}">
</div>
<div id="lastNameData">
<label>{{ form.last_name.label_tag }}</label>
<input type="text" id="lastNameInput" value="{{ form.last_name }}">
</div>
<div id="divBtnChangeProfile">
<input type="submit" class="btnChangeProfile" value="Atualizar Profile">
</div>
</form>
</div>
I'd appreciate it if you could help me. I am new to the Django environment, and have tried many approaches, and I have not yet been able to solve this problem.
--------------------------- Update ------------------------------------
Now, i can get initial values. But to view them i need to write on input form: form.username.initial, and with this i can't after submit form to update user values.
Anyone knows how to solve this type of problem??
I finally got this problem solved. I will make my solution available, since it can help other people.
I had to make some changes to the code I provided behind.
Below is the code of view.
class DetailUserInfoView(LoginRequiredMixin, UpdateView):
model = CustomUser.CustomUser
template_name = 'users/InfoUser.html'
login_url = settings.LOGOUT_REDIRECT_URL
context_object_name = 'user'
form_class = CustomUserChangeForm
def get_object(self, queryset=None):
return self.request.user
def get_form_kwargs(self):
kwargs = super(DetailUserInfoView, self).get_form_kwargs()
u = self.request.user
kwargs['username_initial'] = u.username
kwargs['fName_initial'] = u.first_name
kwargs['lName_initial'] = u.last_name
return kwargs
def get_context_data(self, **kwargs): #GET OBJECT ACTS AFTER THAN GET_OBJECT --> EXAMPLE OF GET_CONTEXT_DATA, I DIDN'T NEED THIS
context = super(DetailUserInfoView, self).get_context_data(**kwargs)
form_class = self.get_form_class()
form = self.get_form(form_class)
context['form'] = form
return context
My form (with init function, to set initial values on form, and is called by def get_form_kwargs(self)).
class CustomUserChangeForm(UserChangeForm):
def __init__(self, *args, **kwargs):
username_initial = kwargs.pop('username_initial', None)
fName_initial = kwargs.pop('fName_initial', None)
lName_initial = kwargs.pop('lName_initial', None)
super(CustomUserChangeForm, self).__init__(*args, **kwargs)
self.fields['username'].initial = username_initial
self.fields['first_name'].initial = fName_initial
self.fields['last_name'].initial = lName_initial
class Meta(UserChangeForm.Meta):
model = CustomUser.CustomUser
fields = ('username', 'email', 'first_name', 'last_name')
And finnaly, in template I replace the tag input with {{ form.username }}.
I hope it can help someone who has the same problem.

Two forms in one view Django

I'm a beginner in django and I want to put two diferent registers in the same view. But also I want to make my own forms and put diferent url at the action tag. I did it in one form, but when I puy the second form, this doesn't work.
This is my models.py:
from django.db import models
class userProfile(models.Model):
usermail = models.CharField(max_length=264)
username = models.CharField(max_length=264)
userpass = models.CharField(max_length=264)
class companyProfile(models.Model):
companymail = models.CharField(max_length=264)
companyname = models.CharField(max_length=264)
companypass = models.CharField(max_length=264)
This is my forms.py:
from django import forms
from Pruebas_app.models import companyProfile, userProfile
class registerCompany(forms.Form):
companypassconf = forms.CharField()
class Meta():
model = companyProfile
fields = ['companymail','companyname', 'companypass']
labels = {'companymail': '', 'companyname': '', }
widgets = { 'companypass': forms.PasswordInput(),}
class registerUser(forms.Form):
userpassconf = forms.CharField()
class Meta():
model = companyProfile
fields = ['usermail','username', 'userpass']
labels = {'usermail': '', 'username': '', }
widgets = {'userpass': forms.PasswordInput(),}
And this is my template:
<form action="{ url 'user_register'}" method="post">
<input type="text" name="username">
<input type="email" name="usermail">
<input type="password" name="userpass">
<input type="password" name="userpassconf">
<input type="submit" value="Register">
</form>
<form action="{ url 'company_register'}" method="post">
<input type="text" name="companyname">
<input type="email" name="companymail">
<input type="password" name="companypass">
<input type="password" name="companypassconf">
<input type="submit" value="Register">
</form>
And this is my views.py:
from django.shortcuts import render
from Pruebas import forms
from Pruebas.forms import registerCompany, registerUser
from django.http import HttpResponse
def user_register(request):
form = forms.registerUser()
regd = False
passmatch = True
if request.method == "POST":
form = registerUser(request.POST)
if form.is_valid():
form_data = form.cleaned_data
print (form_data.get("userpass"))
if form_data.get("userpass") == form_data.get("userpassconf"):
passmatch = True
form.save()
regd = True
print("saved")
else:
passmatch = False
else:
print("error")
red = 'Pruebas/register.html'
regd = False
return render(request, 'Pruebas/register.html', {'registered': regd, "matchPass": passmatch})
I tried to send the data from my forms to one unique view, but I only can recive the data from the user register. I don't know what I was doing wrong or what I have to do to make this works, please help!
In your forms, don't define meta class and just display the fields like you're doing with the userpassconf. You can even combine the forms into a single form, and then just handle the data in your view like you're already doing, but create two instances. Something like:
if request.method == "POST":
form = registerUser(request.POST)
if form.is_valid():
form_data = form.cleaned_data
if form_data.get("userpass") == form_data.get("userpassconf"):
passmatch = True
new_user = userProfile()
new_user.usermail = form_data.get("usermail")
new_user.username = form_data.get("username")
new_user.save()
So basically you're just creating an instance of whatever model you want to save to, and assigning the form data to it, and then saving it. And don't forget to import your models into the views file.

Blank Result When Filtering ForeignKey values in Django ModelchoiceField

I have three models and they serve as 'Foreignkey' to each other.
Hotel models
class Hotel(model.Models):
user= models.ForeignKey(User)
name= models.CharField(max_length=100, verbose_name='hotel_name')
address= models.CharField(max_length=100, verbose_name='hotel_address')
#more fields
Rooms models
class HotelRooms(models.Model):
hotel= models.ForeignKey(Hotel, related_name='myhotels')
slug=models.SlugField(max_length=100, unique=True)
room_name=models.CharField(max_length=100, verbose_name='Room Name')
#other fields
HotelCalendar models
class HotelCalendar(models.Model):
user=models.ForeignKey(User)
hotel=models.ForeignKey(Hotel)
hotelrooms=models.ForeignKey(HotelRooms)
#other fields
Now, I want to display all rooms that belongs to a hotel in HotelCalender form in order for the owner to select the room he/she wants to update and save.
HotelCalendar form
class HotelCalendarForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(HotelCalendarForm, self).__init__(*args, **kwargs)
self.fields['hotelrooms'].queryset= HotelRooms.objects.filter(hotel=self.instance.hotel_id)
Template
<form id="post_form" method="post" action=""
enctype="multipart/form-data">
{% csrf_token %}
{{ HotelCalendarForm.as_p }}
<input type="submit" name="submit" value="Submit" />
</form>
Views
def hotel_calendar_view(request, hotel_id):
if request.method=="POST":
form=HotelCalendarForm(request.POST)
if form.is_valid():
data=form.cleaned_data
newbookdate=HotelCalendar(
user=request.user,
hotel=Hotel.objects.get(id=hotel_id),
hotelrooms=data['hotelrooms'],)
newbookdate.save()
return render(request, 'notice.html')
#other code here
When I load the form, it won't return any value, The modelchoicefield is just blank.
What am I missing?
It seems you are trying to populate the hotelrooms field with the filtered results by the hotel when the form is loaded on a GET request. If that's the case the field wont load any data as the instance variable will be None.
For the initial data you need to pass the hotel id to the form when it is being initialized on the GET request and in the form, load the data using the hotel id and not instance.hotel_id. For example:
views.py
#login_required
def hotel_calendar_view(request, hotel_id):
if request.method=="POST":
## code to post the form data
else:
context = {
'HotelCalendarForm’: HotelCalendarForm(hotel_id=hotel_id),
'hotel': Hotel.objects.get(id=hotel_id)
}
return render(request, 'hotels/hotel_calendar.html', context)
# return default response
and then in your forms:
forms.py
class HotelCalendarForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
hotel_id = kwargs.pop(“hotel_id”, None)
super(HotelCalendarForm, self).__init__(*args, **kwargs)
if hotel_id:
self.fields['hotelrooms'].queryset=HotelRooms.objects.filter(hotel=hotel_id)
You should modify the line
self.fields['hotelrooms'].queryset = HotelRooms.objects.filter(hotel=self.instance.hotel_id)
to
self.fields['hotelrooms'].queryset = HotelRooms.objects.filter(hotel=self.instance.hotel)
When you are filtering on foreign key it expects a model instance. If you would want to filter on foreign key you would have to do it like this:
HotelRooms.objects.filter(hotel_id=self.instance.hotel_id)
If you want to know more read https://docs.djangoproject.com/ja/1.9/topics/db/queries/#field-lookups

Boolean field not saving in Django form

I have a form with radio buttons and text fields. When I submit the form, the boolean field does not get created in the record. The boolean field is supposed to be updated via the radio buttons. What could be the issue here?
Here is the relevant part of my forms.py file:
CHOICES = (
(1,'yes'),
(0,'no')
)
class ServiceForm(forms.ModelForm):
one_time_service = forms.ChoiceField(required = True, choices = CHOICES, widget=forms.RadioSelect())
class Meta:
model = Service
fields = ('one_time_service')
This is my models.py one_time_service field
one_time_service = models.BooleanField(default=False)
This is my views.py:
def create(request):
if request.POST:
form= ServiceForm(request.POST)
if form.is_valid():
service_obj = form.save(commit=False)
service_obj.user_id = request.user.id
service_obj.save()
return render_to_response('services/service_created.html',
{'service': Service.objects.get(id=service_obj.id)})
else:
form = ServiceForm()
args= {}
args.update(csrf(request))
args['form'] = form
return render_to_response('services/create_service.html', args )
Edit: Here is my create_service.html
<form action="/services/create" method="post" enctype="multipart/form-data">{% csrf_token %}
<ul>
{{form.as_p}}
</ul>
<input type="submit" name="submit" value="Create Service">
</form>
I have no idea if this is the problem, but the line:
fields = ('one_time_service')
is wrong. That's not a single element tuple, that's a string with parens around it. Add a comma to make it a tuple:
fields = ('one_time_service',)
Edit: also, form.save() does not update any database records -- it creates a new one! That may be your problem.

Categories