Select specific option from dropdown menu DJANGO - python

I have a page that lists all the items from a table named Stocks for each row there's a clickable ORDER button that leads users to another page where they can enter all their details as well as select what item and how much they wanna buy which would then save all of that data to a table named Orders.
This orders table is linked with the Stocks table like this:
class Order(models.Model):
name = models.CharField(max_length=50, blank=True, null=True)
quantity = models.IntegerField(default='0', blank=False, null=True)
order_item = models.ForeignKey(Stock, on_delete=models.CASCADE, blank=True)
address = models.CharField(max_length=50, blank=True, null=True)
city = models.CharField(max_length=50, blank=True, null=True)
Depending on what item they clicked the order button for I wanted to automatically select the corressponding item from the dropdown menu on the next page so that they won't have to.
def create_order(request, pk):
queryset = Stock.objects.get(id=pk)
form = CreateOrderForm(request.POST or None, initial={'order_item':queryset.item_name})
if form.is_valid():
form.save()
context = {
'form':form
}
return render(request, 'add_items.html', context)
I tried doing this by using the intitial command but for some reason it just won't change from the default blank option.
Here's my forms.py just in case
class CreateOrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ['name','quantity','order_item','address','city']

Use the Stock object as initial value, so not queryset.item_name, but queryset (although since it is not a queryset, it is better to rename this to stock):
from django.shortcuts import get_object_or_404
def create_order(request, pk):
stock = get_object_or_404(Stock, id=pk)
if request.method == 'POST':
form = CreateOrderForm(request.POST, initial={'order_item': stock})
if form.is_valid():
form.save()
else:
form = CreateOrderForm(initial={'order_item': stock})
context = {
'form':form
}
return render(request, 'add_items.html', context)
Note: It is often better to use get_object_or_404(…) [Django-doc],
then to use .get(…) [Django-doc] directly. In case the object does not exists,
for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using
.get(…) will result in a HTTP 500 Server Error.

Related

how to request and post an object to a foreignkey field

When I do this exactly as provided below, a shipping address object is created without the customer assigned in the shipping address foreignkey field, I can add it from the admin panel manually but I'm not able to make it work through code, idk what I'm doing wrong, please help!
**models.py**
class Customer(models.Model):
user = models.OneToOneField(CustomUser, on_delete=models.CASCADE, blank=True, null=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField(max_length=150)
class ShippingAddress(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, blank=True, null=True)
address_one = models.CharField(max_length=200)
address_two = models.CharField(max_length=200)
...
**views.py**
def checkout(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = Order.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
else:
items = []
order = {'get_cart_total': 0, 'get_cart_items': 0}
if request.method == 'POST':
form = ShippingForm(request.POST)
if form.is_valid():
#how do I get the customer to get added in the foreignkey field for the shipping address model
form.save()
return redirect('store:checkout_shipping')
else:
form = ShippingForm()
else:
form = ShippingForm()
context = {"items": items, "order": order, "form": form}
return render(request, 'store/checkout.html', context)
In response to your comment #how do I get the customer to get added... etc, in the case that your ShippingForm() points to your ShippingAddress model, or at least something with a customer foreign key field, you may need to do something like this:
def checkout(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = Order.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
else:
items = []
order = {'get_cart_total': 0, 'get_cart_items': 0}
if request.method == 'POST':
form = ShippingForm(request.POST)
if form.is_valid():
new_shipment = form.save(commit=False)
new_shipment.customer = customer
new_shipment.save()
return redirect('store:checkout_shipping')
else:
form = ShippingForm()
else:
form = ShippingForm()
context = {"items": items, "order": order, "form": form}
return render(request, 'store/checkout.html', context)
Using commit=False on the form.save() will allow you to subsequently modify other fields, in this case, by adding the customer relation, then saving it. More information here in the Django documentation. Salient quote:
This save() method accepts an optional commit keyword argument, which
accepts either True or False. If you call save() with commit=False,
then it will return an object that hasn’t yet been saved to the
database. In this case, it’s up to you to call save() on the resulting
model instance. This is useful if you want to do custom processing on
the object before saving it, or if you want to use one of the
specialized model saving options. commit is True by default.
"Custom processing" in this case is the creation of the foreign key relationship to the model instance (customer).

How to update only selected records in Django queryset like in admin panel actions? [duplicate]

I need to update the model according to the marked checkboxes in the django shape
How can I get only some of the table fields in a query
the "checked" line should be updated through the queryset
models.py
class moIn(models.Model):
date = models.DateTimeField(auto_now_add=True, verbose_name='')
dateUpdate = models.DateTimeField(auto_now=True)
ts = models.IntegerField(verbose_name='')
pl = models.IntegerField(verbose_name='')
rem = models.IntegerField(verbose_name='')
comment = models.TextField(max_length=200, verbose_name='', blank=True)
staffer = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name='')
checked = models.BooleanField(verbose_name='', default=False)
checkedUser = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name='', blank=True, null=True, related_name='checkedUser')
by clicking this checkbox, you will need to receive database records
forms.py
class checkForm(ModelForm):
checked = fields.BooleanField(required=False)
class Meta:
model = moIn
fields = {"id", "checked"}
views.py
def dashboard(request):
if request.user.groups.filter(name='DashBoardAccess').exists():
form = checkForm
f = tableDashFilter(request.GET, queryset=moIn.objects.all())
if request.method == 'POST':
form = checkForm(request.POST)
if form.is_valid():
tt = form.save(commit=False)
data = form.cleaned_data
field = data['checked']=True
f.qs.filter(checked=field).update(checked=True, checkedUser=request.user)
return HttpResponse('ok')
else:
context = {
'filter': f,
'form': form
}
return render(request, 'dashboard/index.html', context)
else:
raise Http404()
in a line in bold, you need to get only those lines in which the checkbox is marked
f.qs.filter(checked=field).update(checked=True, checkedUser=request.user)
You can get all the fields using ".values ()" for the queryset, and to use it with foreignKey, you need to explicitly specify the model fields:
f = tableDashFilter(request.GET, queryset=moIn.objects.values('id','date','ts','pl','rem','comment','checked','staffer__username','checkedUser__username'))
"Value" from the input, it is also going to be obtained through:
Since there can be several values (marked checkboxes), there will be a ".getlist"
checkID = request.POST.getlist('checked')
querySet filter:
f.qs.filter(id__in=checkID).update(checked=True, checkedUser=request.user)
in the html template through the loop, iterate over and insert into the input value of the model id

Django - pass a list of results when querying using filter

In my FollowingPageView function, I'm trying to filter posts based on the logged in user's list of user's he/she is following.
You'll see the Profile model has a "following" field that captures the names of users the Profile owner is following. What I'm trying to do in my view is capture these names of the users in "following" then pass them to Post.objects.filter(created_by=user_list), but I will only get the last user in that list in this case. How can I iterate over the "user_list" Queryset and pass that to Post.objects.filter in order to return the posts from each user in that list? In this case, I should have two users in the Queryset [<User: winter>, <User: daisy>].
models.py
class Profile(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
bio = models.TextField(null=True, blank=True)
website = models.CharField(max_length=225, null=True, blank=True)
follower = models.ManyToManyField(User, blank=True, related_name="followed_user") # user following this profile
following = models.ManyToManyField(User, blank=True, related_name="following_user") # profile user that follows this profile
def __str__(self):
return f"{self.user}'s' profile id is {self.id}"
def following_users(self):
for username in self.following:
return username
def get_absolute_url(self):
return reverse("network:profile-detail", args=[str(self.id)])
class Post(models.Model):
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
subject = models.CharField(max_length=50)
body = models.TextField(max_length=1000)
timestamp = models.DateTimeField(auto_now_add=True)
likes = models.ManyToManyField(User, blank=True, related_name="posts")
def __str__(self):
return f"{self.created_by} posted {self.body}"
views.py
# Following Users
def FollowingPageView(request, pk):
profile = get_object_or_404(Profile, id=pk)
user_list = []
for user in profile.following.all():
user_list.append(user)
posts = Post.objects.filter(created_by=user_list[0])
print(user_list)
paginator = Paginator(posts, 10)
page_number = request.GET.get("page")
page_obj = paginator.get_page(page_number)
try:
if request.method == "GET":
return render(request, "network/follow-posts.html", { "profile": profile, "page_obj": page_obj })
except ValueError:
return render(request, "network:index.html", {"error": ValueError})
One approach is to use an __in query. Here, because you're not using user_list for anything else, you'll probably get the best results from using an inner query:
posts = Post.objects.filter(created_by__in=profile.following.all())
But note the performance advice in the linked docs - test it on your actual setup and see.
Possibly with a distinct() call required, I can't remember exactly what triggers the possibility of duplicate records with many-to-many fields.
There are other ways to express it using field references, something like:
posts = Post.objects.filter(created_by__profile__followed_user=profile.user).distinct()
Backing databases tend to do that with a join rather than a subquery, so it can have different performance characteristics.

Show last uploaded file details on redirected page - Django

folks. In my application user uploads his/her document on upload_document page, submits the form and he/she should see details (for example, document name, document author and etc.) on redirected result page. Now I don't know where should I get document itself from POST request. Or I'm entirely in wrong way. Here are my codes.
views.py:
#login_required(login_url='sign_in')
def upload_document(request):
context = {}
form = UploadDocumentForm()
if request.method == 'POST':
form = UploadDocumentForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
return redirect('result')
context = {
'form':form
}
return render(request, 'upload_document.html', context)
#login_required(login_url='sign_in')
def result(request):
# Don't know what to do here.
return render(request, 'result.html', context)
models.py:
class OriginalDocument(models.Model):
document = models.FileField(upload_to='static/original_document', blank=False)
document_title = models.CharField(max_length=300)
student_name = models.CharField(max_length=100)
teacher_name = models.CharField(max_length=100)
document_type = models.CharField(max_length=100)
university = models.ForeignKey(University, on_delete=models.CASCADE, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add = True)
checked_by = CurrentUserField()
def __str__(self):
return self.document_title
As a user, I'm using django's built-in user.
Finding solution with the help of #k33da_lets_debug become so easy. I've changed query to this:
last_uploaded = OriginalDocument.objects.latest('id')
And that's all.

Model Choice Field - get the id

I am busy trying to get the id only in integer format preferably for the ModelChoiceField. I get the list to display but get's returned in a string format. Please helping me in retrieving the id of ModelChoiceField. I think I need to do this in the view.
forms.py
class ProjectForm(forms.ModelForm):
items = forms.ModelChoiceField(queryset=Project.objects.all())
class Meta:
model = Project
fields = ['items']
models.py
class Project(models.Model):
items = models.IntegerField(default=0, blank=True, null=True)
views.py
def ProjectView(request):
form = ProjectForm(request.POST)
if request.method == 'POST':
if form.is_valid():
save_it = form.save(commit=False)
save_it.save()
return HttpResponseRedirect('/')
else:
form = ProjectForm()
return render(request, 't.html', {'form': form })
From what I can tell, items should never be an IntegerField. Your usage has it set up to be a ForeignKey to a Project so you should just make that explicit
items = models.ForeignKey('self', null=True, blank=True)
Possibly with a better descriptive name than items.
Then, you don't need to define anything on the form, it just becomes a standard model form, with a standard model form usage.

Categories

Resources