I want to edit an entry and it's child at the same time.
So I have a Price model which has Entry (another model) as it's foreign key.
class Price(models.Model):
price = models.ForeignKey(Entry, on_delete = models.CASCADE)
ptext = models.FloatField(blank = True, null = True)
date_added = models.DateTimeField(auto_now_add = True)
class Meta:
verbose_name_plural = 'prices'
def __str__(self):
return self.ptext[:50] + "..." `
How would I pull the price from the entry model?
I can only modify data inside the entry model, but not the price model. The instance part is giving a problem in particular. I don't know what to put for the PriceForm instance.
def edit_entry(request, entry_id):
entry = Entry.objects.get(id = entry_id)
price = entry.price_set.get.all()
topic = entry.topic
check_topic_owner(topic.owner, request.user)
if request.method != 'POST':
form = EntryForm(instance = entry)
form2 = PriceForm(instance = price)
else:
form = EntryForm(instance=entry, data = request.POST)
form2 = PriceForm(instance=price, data = request.POST)
if form.is_valid() and form2.is_valid():
form.save()
form2.save()
return HttpResponseRedirect(reverse('learning_logs:topics'))
context = {'entry': entry, 'topic': topic, 'form': form, 'form2':form2}
return render(request, 'learning_logs/edit_entry.html', context)
To get all the price objects from the entry object, you should use
price = entry.price_set.all()
instead of
price = entry.price_set.get.all()
Related
i'm buildint a warehouse management application, i have a product model and an placement for each product, every placement has a volume, once i put a product in a placement, the volume of this placement must be reduced. The problem is when the app finds a placement for the product, the placement volume stay the same
models.py
class Emplacement(models.Model):
address = models.CharField(max_length=25, blank=True)
volume = models.DecimalField(max_digits=10, decimal_places=2, null=True)
class Product(models.Model):
name = models.CharField(max_length=100)
quantity = models.PositiveIntegerField()
is_disponible = models.BooleanField(default=False)
volume = models.DecimalField(max_digits=20, decimal_places=2, null=True)
emplacement = models.ForeignKey(Emplacement, on_delete=models.CASCADE, null=True)
views.py
def product_detail(request, pk):
product = get_object_or_404(Product, id=pk)
if request.method == 'POST':
form = ValidateProductForm(request.POST, instance=product)
if form.is_valid():
product = form.save(commit=False)
product.volume = form.cleaned_data['longueur'] * form.cleaned_data['largeur'] * form.cleaned_data['hauteur']
product.is_disponible = True
all_emplacements = Emplacement.objects.all()
i=1
while i <= product.quantity:
for emplacement in all_emplacements:
if product.volume < emplacement.volume:
product.emplacement = emplacement
emplacement.volume -= product.volume
i+=1
product.save()
return redirect('print-barcode', product.id)
else:
form = ValidateProductForm(instance=product)
context = {
'product': product,
'form': form,
}
return render(request, 'dashboard/product_detail.html', context)
You're not saving the emplacement object.
Try this:
if request.method == 'POST':
form = ValidateProductForm(request.POST, instance=product)
if form.is_valid():
product = form.save(commit=False)
product.volume = form.cleaned_data['longueur'] * form.cleaned_data['largeur'] * form.cleaned_data['hauteur']
product.is_disponible = True
all_emplacements = Emplacement.objects.all()
i=1
while i <= product.quantity:
for emplacement in all_emplacements:
if product.volume < emplacement.volume:
product.emplacement = emplacement
emplacement.volume -= product.volume
emplacement.save()
i+=1
product.save()
return redirect('print-barcode', product.id)
else:
form = ValidateProductForm(instance=product)
Edit
Your Product model indicates that each Product has only ONE Emplacement, since that's where the ForeignKey is. But, a single Emplacement, can have MANY Product objects. ForeignKey is a ManyToOne relationship. When iterating through ALL Emplacements, you are using the SAME Product, and that's why they are all getting the same number in your admin. I'm guessing, but perhaps what you're after is to find the SINGLE appropriate Emplacement model that the specific Product object has, nad then update just that one. In other words, NO iterating at all.
if request.method == 'POST':
form = ValidateProductForm(request.POST, instance=product)
if form.is_valid():
product = form.save(commit=False)
product.volume = form.cleaned_data['longueur'] * form.cleaned_data['largeur'] * form.cleaned_data['hauteur']
product.is_disponible = True
# Here are my proposed changes:
product.save() # Update the product
emplacement = product.emplacement # Get the correct Emplacement
emplacement.volume -= product.volume # Adjust the volume
emplacement.save() # Save the emplacement
return redirect('print-barcode', product.id)
else:
form = ValidateProductForm(instance=product)
I have a modelform (model: Student) with a TextField where the user enters several names at once. My intention is for my view to parse this text input (getting a first name, last name, and then coming up with a nickname) and loop through the lines, saving a new student each time through the loop. However, only the last time through the loop is a student saved.
In the past I have solved this problem by using a custom save method in my model but I wanted to try doing it all in the view. I saw some posts in stackoverflow such as this one where it seemed that others were able to iterate through a loop and save objects.
models.py
class Student(models.Model):
classroom = models.ForeignKey(Classroom, on_delete=models.CASCADE)
student_first = models.CharField(default='John', max_length=30)
student_last = models.CharField(default='Smith', max_length=30)
nickname = models.CharField(default='JohnS', max_length=31)
attend = models.BooleanField(default=True)
do_not_pick = models.BooleanField(default=False)
multistudentinput = models.TextField(blank=True, default='')
def __str__(self):
return self.nickname
forms.py
class MultiStudentForm(ModelForm):
class Meta:
model = Student
fields = ('multistudentinput',)
views.py
def addmultistudent(request, classroom_id):
classblock = Classroom.objects.get(id=classroom_id)
if request.method == 'POST':
form = MultiStudentForm(request.POST)
if form.is_valid():
student = form.save(commit=False)
# save the classroom that the student belongs to
student.classroom = classblock
student_list = []
student_list = student.multistudentinput.split('\n')
for line in student_list:
line = line.strip('\r')
all_names = line.split()
num_names = len(all_names)
if num_names == 2:
last = all_names[1]
student.student_last = last
else:
last = ' '
student.student_last = ''
student.nickname = all_names[0] + last[:1]
student.student_first = all_names[0]
print(student)
student.save()
form = MultiStudentForm(None)
context = {'form': form}
return render(request, "gradebook/addmultistudent.html", context)
else:
context = {'form': form}
return render(request, "gradebook/addmultistudent.html", context)
else:
form = MultiStudentForm(None)
context = {'form': form}
return render(request, "gradebook/addmultistudent.html", context)
I everyone, I have a problem with a django's view. My goal is to change the 'execute' field into 'True' if newOrder is buy and there is some other sell order with a inferior price. And reverse for sell newOrders. I want to change the 'execute' field for the newOrder and also for the other order (in pairs). That's my code:
views.py
def order(request):
form = OrderForm()
if request.method == 'POST':
form = OrderForm(request.POST)
if form.is_valid():
new_order = form.save()
if new_order.buy is True:
sellOrder = Order.objects.filter(sell=True, execute=False,
price__lte=new_order.price).first().update(execute=True)
new_order.execute = True
sellOrder.save()
else:
buyOrder = Order.objects.filter(buy=True,
execute=False,price__gte=new_order.price).first().update(execute=True)
new_order.execute = True
buyOrder.save()
new_order.profile = request.user
new_order.save()
return redirect('home')
else:
form = OrderForm()
contex = {'form': form}
return render(request, 'app/new_order.html', contex)
models.py
class Profile(models.Model):
_id = ObjectIdField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
wallet = models.FloatField()
class Order(models.Model):
_id = ObjectIdField()
profile = models.ForeignKey(User, on_delete=models.CASCADE)
datetime = models.DateTimeField(auto_now_add=True)
buy = models.BooleanField(blank=True)
sell = models.BooleanField(blank=True)
price = models.FloatField()
quantity = models.FloatField()
execute = models.BooleanField(blank=True)
But something goes wrong. This is the error:
AttributeError at /new_order/
'NoneType' object has no attribute 'update'
sellOrder returns a count of updated rows, not the object updated
sellOrder = Order.objects.filter(sell=True, execute=False,
price__lte=new_order.price).first().update(execute=True)
instead try
sellOrder = Order.objects.filter(sell=True, execute=False,
price__lte=new_order.price).first()
new_order.execute = True
sellOrder.execute = True
sellOrder.save()
Hey guys how can i set initial value in my form field, let say the user click "BidForm" in the search form, i want the BidForm value will be the value of ProjectName in the other form...
here's my code in my search views
def search_views(request):
project_list = ProjectNameInviToBid.objects.all()
query = request.GET.get('query')
if query:
project_list = project_list.filter(ProjectName__icontains=query)
context = {
'project_list': project_list
}
return render(request, 'content/search_views.html', context)
and my other views
def project_name_details(request, sid):
majordetails = ProjectNameInviToBid.objects.get(id=sid)
if request.method == 'POST':
form = invitoBidForm(request.POST, request.FILES)
form.fields['ProjectName'].initial = majordetails
if form.is_valid():
form.save()
messages.success(request, 'File has been Uploaded')
else:
form = invitoBidForm()
args = {
'majordetails': majordetails,
'form': form
}
return render(request,'content/invitoBid/bacadmininvitoBid.html', args)
my form.py
class invitoBidForm(ModelForm):
class Meta:
model = InviToBid
fields = ('ProjectName','NameOfFile', 'Contract_No', 'Bid_Opening',
'Pre_Bid_Conference', 'Non_Refundable_Bidder_Fee',
'Delivery_Period',
'Pdf_fileinvi',)
and my models.py
class ProjectNameInviToBid(models.Model):
ProjectName = models.CharField(max_length=255, verbose_name='Project Name', null=True)
DateCreated = models.DateField(auto_now=True)
def __str__(self):
return self.ProjectName
class InviToBid(models.Model):
today = date.today()
ProjectName = models.ForeignKey('ProjectNameInviToBid', on_delete=models.CASCADE)
NameOfFile = models.CharField(max_length=255, verbose_name='Name of File')
Contract_No = models.IntegerField(verbose_name='Contract No')
def __str__(self):
return self.NameOfFile
First, I shall praise your documentation. Most people fail to provide the important code.
You can add something like this to your code here that will do what you require.
An example from my own code
if request.method == 'GET' and request.user.is_authenticated:
study = Study.objects.get(pk=studyID)
form = ContactForm(initial={'from_email': request.user.email, 'subject': "Study: " + study.name ,'message': study_message.format(request.user.get_short_name(), request.user.get_full_name())})
How you should change your code
Change your code in your other views from this:
else:
form = invitoBidForm()
to
else:
form = invitoBidForm(initial={'ProjectName': <wherever your project name comes from>})
views.py
#app.route('/new', methods = ['POST', 'GET'])
#login_required
def new():
form = StudentForm()
if request.method == 'POST':
if form.validate_on_submit():
flash('All fields are required.')
return render_template('form.html', action = 'new', form = form)
else:
student = students(
request.form['first_name'], request.form['last_name'], \
request.form['date_of_birth'], \
request.form['date_of_join'], request.form['address']
db.session.add(student)
db.session.commit()
return redirect(url_for('show_all'))
return render_template('form.html', action = url_for('new'), form = form)
#app.route('/edit/<int:id>', methods = ['POST', 'GET'])
#login_required
def edit(id):
item = students.query.get(id)
form = StudentForm(obj=item)
if request.method == 'POST':
if form.validate_on_submit():
item = students.query.get(id)
form = StudentForm(obj=item)
return render_template('form.html', action = url_for('edit',id = id), form = form)
else:
form.populate_obj(item)
db.session.add(item)
db.session.commit()
return redirect(url_for('show_all'))
return render_template('form.html', action = url_for('edit',id = id), form = form)
models.py
class students(db.Model):
__tablename__ = "students"
id = db.Column('id', db.Integer, primary_key = True)
first_name = db.Column(db.String(25))
last_name = db.Column(db.String(25))
date_of_birth = db.Column(db.Date)
date_of_join = db.Column(db.Date)
address = db.Column(db.String(200))
forms.py
class StudentForm(Form):
first_name = TextField("First Name:")
last_name = TextField("Last Name:")
date_of_birth = DateField("Date of Birth:", format='%m/%d/%Y')
date_of_join = DateField("Date of Joining:", format='%m/%d-%Y')
address = TextAreaField("Address:")
submit = SubmitField("Submit")
All other fields are added to the database while adding new item, but the date is not stored. I cant find what the problem actually is. The date field is stored during edit if i use form.validate() for form validation. And if i use form.validate_on_submit() the date field is not stored while adding or editing...