I am looking for some help in my first django app and I am new to programming. I have the below scenario:
Models:
class save_table(models.Model):
name=models.CharField(max_length=100)
UniqueuserID = models.CharField(max_length=7)
UserLocation = models.CharField(max_length=100)
UserLead = models.CharField(max_length=50)
def __str__(Self):
return self.UniqueuserID
class data_table(models.Model):
UniqueuserID = models.CharField(max_length=7)
name=models.CharField(max_length=100)
UserLocation = models.CharField(max_length=100)
UserLead = models.CharField(max_length=50)
Form:
class save_table_form(forms.ModelForm):
class Meta:
model = save_table
fields = ('UniqueuserID')
def __init__(self,*args,**kwargs):
super(save_table_form,self).__init__(*args,**kwargs)
Every user ID that the user will add to the form will have a respective data entry int he second model and I want to save that additional data along with the form. However I did not use a foreign key because I do not want the saved model data in the save_table to change based on the changes in the data_table. Can I add the additional data to the form before saving the form.
if form.is_valid():
form.save()
Please help..
Yes you can add aditional data when saving the form!
overwrite the saving methoud in class save_table_form:
like this :
class save_table_form(forms.ModelForm):
def save(self, commit=True):
user_id = self.cleaned_data['id']
user_photo = self.cleaned_data['photo']
user_password = self.cleaned_data['password1']
user = SysUser.objects.get(pk=user_id)
user.username = self.cleaned_data['username']
if user_password:
user.set_password(self.cleaned_data['password1'])
user.first_name = self.cleaned_data['first_name']
user.mobile = self.cleaned_data['mobile']
user.office_id = self.cleaned_data['office_id']
if user_photo:
user.image = user_photo
user.save()
user.user_permissions.clear()
user.user_permissions.add(*self.cleaned_data['user_permissions'])
print('data is saving')
return user
Related
I am trying to create a form where one field is a ModelChoicefield. Im trying to populate that field with objects from a different model. I have ran into a problem as i need to get the current logged user within the form to filter the queryset. Here are the 2 models
class UserExercises(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
Muscle = models.ForeignKey(Muscle, on_delete=models.CASCADE)
class Exercise(models.Model):
exercise = models.ForeignKey(UserExercises, on_delete=models.CASCADE)
weight = models.DecimalField(max_digits=6, decimal_places=3)
reps = models.PositiveIntegerField(validators=[MaxValueValidator(100)])
difficulty = models.CharField(max_length=30)
date = models.DateTimeField(default=timezone.now)
user = models.ForeignKey(User, on_delete=models.CASCADE)
And here is my form
class AddExerciseForm(forms.Form):
exercise = forms.ModelChoiceField(queryset=UserExercises.objects.filter(user=1))
class Meta:
model = Exercise
fields = ['exercise', 'weight', 'reps', 'difficulty']
As you can see i am currently hard coding a filter in the ModelChoiceField, but want to replace that with the current users Id. Is there anyway of Going about this. Im new to django so any help would be Appreciated.
My View
#login_required
def add_exercise_view(request):
if request.method == 'POST':
user_id = request.user.id
form = AddExerciseForm(user_id=user_id)
if form.is_valid():
form.save()
return redirect('myfit-home')
else:
form = AddExerciseForm()
return render(request, 'users/register.html', {'form': form})
Firstly, AddExerciseForm should extend forms.ModelForm.
To initialize form data based on some paramater, you can override __init_ method of ModelForm to update form fields (that field is exercise in this case) based on some argument/parameter (which is user_id in this case).
class AddExerciseForm(forms.ModelForm):
class Meta:
model = Exercise
fields = ['exercise', 'weight', 'reps', 'difficulty']
def __init__(self, *args, **kwargs):
user_id = kwargs.pop('user_id', None)
super(AddExerciseForm, self).__init__(*args, **kwargs)
if user_id is not None:
# update queryset for exercise field
self.fields['exercise'].queryset = UserExercises.objects.filter(user=user_id)
else:
# UserExercises.objects.none() will return an empty queryset
self.fields['exercise'].queryset = UserExercises.objects.none()
And pass the user_id while initializing the form in view:
if request.user.is_authenticated():
# get user id
user_id = request.user
form = AddExerciseForm(user_id=user_id)
override __init__ method of the Form, and pass the user as argument
def __init__(self,user,*args, **kwargs):
self.user = user
super().__init__(*args, **kwargs)
self.fields['exercise'].queryset=
UserExercises.objects.filter(user=self.user))
self.fields['exercise'].widget = forms.CheckboxSelectMultiple
class Meta:
model = Exercise
fields = ['exercise', 'weight', 'reps', 'difficulty']
I'm trying to display a form (ModelForm) with a select field filtered by currently logged in user. The select field in this case contains a list of categories. I want to display only the categories which "belong" to the currently logged in user. The category field is a foreign key to the IngredienceCategory model.
Here is what I've come up with so far but it's giving me an error (unexpected keyword queryset). Any ideas what I'm doing wrong?
# models.py
class IngredienceCategory(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
class Ingredience(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, null=True, blank=True)
category = models.ForeignKey(IngredienceCategory, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredients"
def __unicode__(self):
return self.name
class IngredienceForm(ModelForm):
class Meta:
model = Ingredience
fields = ('name', 'category')
# views.py
def home(request):
if request.user.is_authenticated():
username = request.user.username
email = request.user.email
foods = Food.objects.filter(user=request.user).order_by('name')
ingredients = Ingredience.objects.filter(user=request.user).order_by('name')
ingrcat = IngredienceCategory.objects.filter(user=request.user)
if request.method == 'POST':
form = IngredienceForm(request.POST)
if form.is_valid():
# Create an instance of Ingredience without saving to the database
ingredience = form.save(commit=False)
ingredience.user = request.user
ingredience.save()
else:
# How to display form with 'category' select list filtered by current user?
form = IngredienceForm(queryset=IngredienceCategory.objects.filter(user=request.user))
context = {}
for i in ingredients:
context[i.category.name.lower()] = context.get(i.category.name.lower(), []) + [i]
context2 = {'username': username, 'email': email, 'foods': foods, 'ingrcat': ingrcat, 'form': form,}
context = dict(context.items() + context2.items())
else:
context = {}
return render_to_response('home.html', context, context_instance=RequestContext(request))
That's happening because ModelForm does not take a queryset keyword.
You can probably achieve this by setting the queryset on the view:
form = IngredienceForm()
form.fields["category"].queryset =
IngredienceCategory.objects.filter(user=request.user)
See related question here.
Here i have another suggestion to solve the problem. You can pass request object in your form object inside view.
In view.py just pass the request object.
form = IngredienceForm(request)
In your forms.py __init__ function also add request object
from models import IngredienceCategory as IC
class IngredienceForm(ModelForm):
class Meta:
model = Ingredience
fields = ('name', 'category')
def __init__(self, request, *args, **kwargs):
super(IngredienceForm, self).__init__(*args, **kwargs)
self.fields['name'].queryset = IC.objects.filter(user=request.user)
This filter always will be applied whenever you initialize your form .
I'm trying to create a form from this model:
class A(models.Model):
u = models.OneToOneField(User)
and then create this form:
class AForm(ModelForm):
class Meta:
model = A
fields = ['u']
then i create an instance of that form in my view and send it to my template as a context I'll get a drop down list to choose from existing users but what i want to do is to have a text field to change my current user's first name or last name.
I'll be grateful if you could help me to change my form class to get the right result.
Thank you
You can add the first and last name fields to the AForm ModelForm in the following way:
class AForm(ModelForm):
first_name = forms.CharField(max_length=30, blank=True)
last_name = forms.CharField(max_length=30, blank=True)
class Meta:
Model = A
def __init__(self, *args, **kwargs):
super(AForm, self).__init__(*args, **kwargs)
self.fields['first_name'].initial = self.instance.u.first_name
self.fields['last_name'].initial = self.instance.u.last_name
def save(self, commit=True):
self.instance.u.first_name = self.cleaned_data['first_name']
self.instance.u.last_name = self.cleaned_data['last_name']
self.instance.u.save()
return super(AForm, self).save(commit=commit)
In this case you do not need a modelform of A but a modelform of User. You would need to set the form's instance appropriately in the view. For example,
a_record = A.objects.get_object_or_404(A, id=1)
form = self.UserForm(instance=a.u) # UserForm is a modelform of User
I have set up my models as shown below:
Models.py
class Customer(models.Model):
CustomerID = models.CharField(max_length=50)
Name = models.CharField(max_length=50)
Mobile = models.CharField(max_length=15)
def __unicode__(self):
return self.CustomerID
class orderHistory(models.Model):
BookingNumber = models.CharField(max_length=50)
customer = models.ForeignKey(Customer)
def __unicode__(self):
return self.BookingNumber
I have also used ModelForm to setup my forms.py:
class customerForm(ModelForm):
class Meta:
model = Customer
exclude = ['CustomerID']
The function in my views.py is something like this:
if request.method == 'POST':
form = customerForm(request.POST or None)
# check whether it's valid:
if form.is_valid():
instance = form.save()
if not instance.CustomerID:
instance.CustomerID = 'DHOBI' + instance.Mobile
instance.save()
return HttpResponseRedirect('/data/test')
else:
form = customerForm()
return render(request, "data/index.html",{'form':form})
My question is, after getting the data for the Customer model, how do I fill the data in BookingNumber in the database? I mean, if I want to set the booking number as Mobile + Today's Date and time.
How do I do that.
import datetime
bn = "%s-%s" % (instance.Mobile,str(datetime.datetime.now())
order_hist = orderHistory.objects.create(customer=instance, BookingNumber=bn)
Just note on naming of classes: give Classes Uppercase names and the attributes lowercase. You have it in reverse.
I'm trying to display a form (ModelForm) with a select field filtered by currently logged in user. The select field in this case contains a list of categories. I want to display only the categories which "belong" to the currently logged in user. The category field is a foreign key to the IngredienceCategory model.
Here is what I've come up with so far but it's giving me an error (unexpected keyword queryset). Any ideas what I'm doing wrong?
# models.py
class IngredienceCategory(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
class Ingredience(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, null=True, blank=True)
category = models.ForeignKey(IngredienceCategory, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredients"
def __unicode__(self):
return self.name
class IngredienceForm(ModelForm):
class Meta:
model = Ingredience
fields = ('name', 'category')
# views.py
def home(request):
if request.user.is_authenticated():
username = request.user.username
email = request.user.email
foods = Food.objects.filter(user=request.user).order_by('name')
ingredients = Ingredience.objects.filter(user=request.user).order_by('name')
ingrcat = IngredienceCategory.objects.filter(user=request.user)
if request.method == 'POST':
form = IngredienceForm(request.POST)
if form.is_valid():
# Create an instance of Ingredience without saving to the database
ingredience = form.save(commit=False)
ingredience.user = request.user
ingredience.save()
else:
# How to display form with 'category' select list filtered by current user?
form = IngredienceForm(queryset=IngredienceCategory.objects.filter(user=request.user))
context = {}
for i in ingredients:
context[i.category.name.lower()] = context.get(i.category.name.lower(), []) + [i]
context2 = {'username': username, 'email': email, 'foods': foods, 'ingrcat': ingrcat, 'form': form,}
context = dict(context.items() + context2.items())
else:
context = {}
return render_to_response('home.html', context, context_instance=RequestContext(request))
That's happening because ModelForm does not take a queryset keyword.
You can probably achieve this by setting the queryset on the view:
form = IngredienceForm()
form.fields["category"].queryset =
IngredienceCategory.objects.filter(user=request.user)
See related question here.
Here i have another suggestion to solve the problem. You can pass request object in your form object inside view.
In view.py just pass the request object.
form = IngredienceForm(request)
In your forms.py __init__ function also add request object
from models import IngredienceCategory as IC
class IngredienceForm(ModelForm):
class Meta:
model = Ingredience
fields = ('name', 'category')
def __init__(self, request, *args, **kwargs):
super(IngredienceForm, self).__init__(*args, **kwargs)
self.fields['name'].queryset = IC.objects.filter(user=request.user)
This filter always will be applied whenever you initialize your form .