AttributeError at /orders/ 'QuerySet' object has no attribute 'orderitem - python

I am working on a django project where I want to display all the orders of a customer.
This is my models.py:
class Order(models.Model):
customer=models.ForeignKey(Customer,on_delete=models.SET_NULL,null=True,blank=True)
date_ordered=models.DateTimeField(auto_now_add=True)
complete=models.BooleanField(default=False,null=True,blank=False)
transaction_id=models.CharField(max_length=100,null=True)
class OrderItem(models.Model):
product=models.ForeignKey(Product,on_delete=models.SET_NULL,null=True)
order=models.ForeignKey(Order,on_delete=models.SET_NULL,null=True)
quantity=models.IntegerField(default=0,null=True,blank=False)
date_added=models.DateTimeField(auto_now_add=True)
And this is my views.py:
def orders(request):
customer=request.user.customer
order=Order.objects.filter(customer=customer, complete=True)
items=order.orderitem.get(order=order)
return render(request,"orders.html",{'order':order,})
When I open this template it gives me the error: query set object has no attribute orderitem. I want it to give me the orders for which complete=True and all the orderitems under that particular order so that I can iterate over them and show them in my template but that is not happening for me.
PLease help. Any help would be appreciated .

Add related_name="order_items" to the order field in OrderItem as follow.
order=models.ForeignKey(Order,on_delete=models.SET_NULL,null=True, related_name="order_items")
Now you can access the order_items of an order like this
order=Order.objects.filter(customer=customer, complete=True).first()
items = order.order_items

You can use this:
items=OrderItem.objects.all()
and in your template you can use a loop and give a if condition seeing your models like:
{% for ord in orders %}
{% for item in items %}
{% if item.order.id == ord.id %}
This is not the most efficient way as it will iterate over all items in your database but it may work for you

Related

Problem with ManyToManyField in other model's forms using Bootstrap

I would like to show possible choices from ManyToManyField (which I have in Homes model) in the Owners form. I have Owners <--Many2Many--> Homes with custom class HomesOwners. In Homes it works out of the box, I don't know how to make it work in Owners.
I am using Django 2.2.4 with Bootstrap 4 and Postgresql. I started my project based on django-bookshelf project (also just Django and Bootstrap4). I do not use any render. Comment in django-bookshelf project mentioned How to add bootstrap class to Django CreateView form fields in the template?, so I stick to that if it comed to forms.
I'm pretty new to Python (so Django too) and web technologies in general. I googled dozen of different questions/answers but I couldn't find any nice explanation of what is what and how to use it in real life. Most of them ended up with basic usage.
I did some experimentation on my own, but no success so far...
Here is the code
I have two models - Homes/models.py and Owners/models.py
Homes/models.py:
class Homes(models.Model):
id = models.AutoField(primary_key=True)
# other fields
some_owners = models.ManyToManyField(Owners, through='HomesOwners', through_fields=('id_home', 'id_owner'), related_name='some_owners')
# end of fields, some other code in the class like "class Meta" etc.
class HomesOwners(models.Model):
id = models.AutoField(primary_key=True)
id_home = models.ForeignKey(Homes, models.DO_NOTHING, db_column='id_home')
id_owner = models.ForeignKey('owners.Owners', models.DO_NOTHING, db_column='id_owner')
Owners/models.py do not have anything special, no imports from my Homes/models.py etc.
and my forms:
Homes/forms.py:
class HomesForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(HomesForm, self).__init__(*args, **kwargs)
self.fields['some_field_from_homes_model'].widget.attrs = {'class': 'form-control '}
#
# --> no need self.fields for M2M, Django does the work
#
# but I tried also and have a --> Question 2
# self.fields["some_owners"].widget = forms.widgets.CheckboxSelectMultiple()
# self.fields["some_owners"].queryset = HomesOwners.objects.all()
Without any code as "self.fields" for M2M field, Django is able to generate for me list of owners.
Question 1
I would like to get list of Homes in my OwnersForms.
I do not know what to add. I assume that I cannot add
# Owners/models.py
some_homes = models.ManyToManyField(Homes, through='HomesOwners', through_fields=('id_home', 'id_owner'), related_name='some_homes')
because of circular import, am I right?
How do I get my Homes list using self.fields?
What do I need to add to my code?
Question 2
When I've added
# Homes/forms.py
self.fields["some_owners"].widget = forms.widgets.CheckboxSelectMultiple()
self.fields["some_owners"].queryset = HomesOwners.objects.all()
I got
<!-- html page -->
HomesOwners object (1)
HomesOwners object (2)
<!-- and so on... -->
How can I just list Owners?
How to filter/order them so first they would appear Owners not connected to any Home?
Question 3
class HomesOwners(models.Model):
id = models.AutoField(primary_key=True)
id_home = models.ForeignKey(Homes, models.DO_NOTHING, db_column='id_home')
id_owner = models.ForeignKey('owners.Owners', models.DO_NOTHING, db_column='id_owner')
def __str__(self):
return pass #return something
I can't get my head around this. This class connects Homes and Owners. When I'm thinking of Homes I would like to return Owners and vice versa. So it should return different things depending on what object we are using (home or owner). I think this is connected to my 2nd question about:
HomesOwners object (1)
Also...
In homes.html I'm using my M2M like that:
{% for owner in homes.homesowners_set.all %}
{{ owner.id_owner.id }}
{% endfor %}
I would like to write something similar to my owners.html and list homes. This is connected to my previous question, I would like to have full answer if that's possible.
EDIT
With the answer given to me I was able to add Homes to OwnerUpdate view. I have views like that:
owners/views.py
# List View
class OwnersList(ListView):
model = Owners
# Detail View
class OwnersView(DetailView):
model = Owners
# Create View
class OwnersCreate(CreateView):
model = Owners
form_class = OwnersForm
# Setting returning URL
success_url = reverse_lazy('owners_list')
# Update View
class OwnersUpdate(UpdateView):
model = Owners
form_class = OwnersForm
success_url = reverse_lazy('owners_list')
# Delete View
class OwnersDelete(DeleteView):
model = Owners
success_url = reverse_lazy('owners_list')
What change do I need to make to be able to show in OwnersList Homes they own?
In Homes DetailView I am able to show Owners. I would like to do the same for Homes' DetailView and Homes ListView.
I don't really get it what you asking for,
but if I understand your question correctly,
I assume you want to add Homes list (not HomesOwners list) into your Owners form, right?
you can add extra field in your form like this:
class OwnersForm(ModelForm):
# notice the queryset is 'Homes' not 'HomesOwners'
homes = forms.ModelMultipleChoiceField(queryset=Homes.objects.all(), widget=forms.CheckboxSelectMultiple)
class Meta:
model = Owners
fields = ('homes', 'your_other_fields',)
# then you can access in init function too if you want
def __init__(self, *args, **kwargs):
super(OwnersForm, self).__init__(*args, **kwargs)
self.fields['homes'].required = False
then, since it using CheckboxSelectMultiple widget, you can iterate it in your html template like this:
{% for key, value in your_form.homes.field.choices %} <!-- notice '.field.'-->
{{ key }} = {{ value }}
{% endfor %}
you probably need to create custom save too for your form.
for your question 3, it is not about the form?
If you want to show HomesOwners, you are already doing right.
{% for owner in homes.homesowners_set.all %}
{{ owner.id_owner.id }}
{% endfor %}
but it will work if that homes is only 1 object.
if homes is a queryset, you have to iterate it first
{% for home in homes %}
{% for owner in home.homesowners_set.all %}
{{ owner.id_owner.id }}
{% endfor %}
{% endfor %}
sorry if I misunderstanding your questions,
maybe you can provide your views.py too, so I or others can help you more specific

Return the first image from the model using the tag '{{value | first}}'

I have a list of photos from which I would like to always be the first to add as a profile photo. I found the following '|first' tag in the django documentation, but I have problems to add it in my situation, every time I try to do it in this way, '{{ image_list|first.photo.url }}' i receives nothing.
Any help will be appreciated.
My models.py
class Image(models.Model):
photo = models.ImageField()
added_at = models.DateTimeField(auto_now_add=True)
masseurs = models.ForeignKey(Masseurs, on_delete=models.CASCADE)
views.py
masseur = get_object_or_404(Masseurs, pk=masseurs_id)
image_list = Image.objects.filter(masseurs_id = masseurs_id)
return render(request, 'masseur/masseur_detail.html', {'image_list':image_list})
Since image_list is a QuerySet and not a list, |first won't work. You can however use:
{{ image_list.first.photo.url }}
For reference, see : Accessing Method Calls
Most method calls attached to objects are also available from within templates. This means that templates have access to much more than just class attributes (like field names) and variables passed in from views.
Why don't you do it in the view?
image = Image.objects.filter(masseurs_id=masseurs_id).first()
But if you need to do it in the template:
{{ image_list.first.photo.url }}
This is because image_list is a queryset, so you can get the first item of the queryset with the .first() syntax

How to query in django one to many

What I want to do?
I have an app have three models:Series,Section and Episode,every one have a one-many query(by ForeignKey). just like this
series-> many Section,section-> many Episode
Now I will show a section with episodes information in series page, but it make more query.
now code
views.py
series = Series.objects.get(id=series_id)
section = Section.objects.filter(series=series)
list.html
{% for item in sections %}
...
{% for episode in item.episode_set.all %}
...
{% endfor %}
...
{%endfor%}
models.py
class Section(models.Model):
series = models.ForeignKey(Series)
....
class Episode(models.Model):
section = models.ForeignKey(Section)
What I want to get ?
an example code tell me how to query in views.py and use just little query.
you can guess, in my code, if here are many section and many episode, it will have many query.
Some idea.
I use Laravel Before, In Laravel , it has a hasMany Function, I can use it to get other models items(Define by belongsTo).
Is Django has same function?
If in template you need only episodes, you can query just them with single query
Episode.objects.filter(section__series=series_id)
But if you need all data then you can use prefetch_related Django docs.
The simplest example looks enough for your code
series = Series.objects.filter(id=series_id).prefetch_related('section_set', 'section_set__episode_set').get()
After this calls to series.section_set.all() and to section.episode_set.all() will not produce extra query.

Displaying multiple objects in a DetailView

I have been dabbling with Django CBV lately and have a question. Maybe you have better ideas than I.
Assume I have a airline booking CRM application and I intend to perform a display of a customer for various things. Assume I have a list of Models, for a Customer like Booking, Rating, Customer_Service_Calls, Favourited_Route.
Now, given a DetailView implemented by Django's CBV, I have something like this
class CustomerThreeSixtyView(DetailView):
model = 'Customer'
def get_context_data(self, **kwargs):
context = super(CustomerThreeSixtyView, self).get_context_data(**kwargs)
context['bookings'] = Booking.objects.all.filter(customer_id=request.kwargs['pk']
context['ratings'] = Ratings.objects.all.filter(customer_id=request.kwargs['pk']
context['calls'] = Customer_Service_Calls.objects.all.filter(customer_id=request.kwargs['pk'], status'Open')
context['fav_routes'] = Favourited_Route.objects.all.filter(customer_id=request.kwargs['pk'], status'Open')
return context
Something like this. My question is that, are there better ways to do this? This is the most straightforward way but I'm asking for suggestions because there seem to be bound for something.
What you have done already looks good enough. You are getting what you required in the context and then using it in the template to show the information.
Alternatively, you could directly access bookings for a particular customer in the template without specifying it in the context:
{% for booking in object.booking_set.all %} # object is the customer here
# do what you want to do with the booking here
{% endfor %}
It is even better if you use related_name while linking the customer to Booking:
class Booking(models.Model):
customer = models.ForeignKey(Customer, related_name='bookings')
# other fields
Now, you can directly use the defined related_name to access the bookings for a particular customer:
{% for booking in object.bookings.all %}
# do what you want to do with the booking here
{% endfor %}
And, you can use the same approach for other classes such as Rating, Customer_Service_Calls, Favourited_Route etc.

django: request.POST key is empty if the choicefield value is not set

I am currently beginning web development using django. In my application, I want a form with a varied number of questions and their choices to be presented.
In models.py, a table is create to store the questions
class QuizItems(models.Model):
question = models.CharField(max_length=255)
choices = SeparatedValuesField(token="$")
answer = models.IntegerField()
In form.py, I overload the __init__ method in Form class so as to pass qchoose, a list of QuizItems instances to create the form fields.
def choiceItem(question):
return [(unicode(idx), q) for idx, q in enumerate(question.choices)]
class QuizForm(forms.Form):
def __init__(self, qchoose, *args, **kwargs):
super(QuizForm, self).__init__(*args, **kwargs)
for q in qchoose:
self.fields[str(q.id)] = forms.ChoiceField(required=True,
label=q.question, widget=forms.RadioSelect(),choices=choiceItem(q))
Then in view.py
if request.method == 'POST':
idlst = request.POST.keys()
else:
# qchoose is a list of quizitems
form = QuizForm(qchoose)
In quiz.html
{% for field in form %}
<li><b> {{ field.label }} </b></li>
<ul> {{ field }} </ul>
{% endfor %}
I want to get idlst, the list of question id, that I can get the correct answers from. It works fine when all the choicefields are filled. The problem is if there is any choicefield value is empty, I won't get its key. I think since the request.POST is a dictionary, it is supposed to return all the keys even if its value is empty.
Could anyone help me what is wrong with my code or anything missing? Thank you!
You're supposed to use the form on POST as well, then call is_valid() and access the form's cleaned_data dict.

Categories