Django: Getting category from add in view - django

I have this view, right:
def thisviewright(request,pk):
theadd = adds.objects.filter(id=pk)
theaddlist = adds.objects.filter(category=add.category)
return render_to_response..
And i'm trying to get the category so i display all other adds that have the same category.
As i'm not passing the category from a URL, i have to get it from the add, who's ID i am passing.
But i'm getting an error:
Queryset has no attribute Category
The model is as follows:
class adds(models.Model):
title = models.CharField(max_length=255)
category = models.ForeignKey('categories')
...
class categories(models.Model):
title = models.CharField(max_length=255)
So long question short, how do i get the related adds from the same category by using the category from the object i'm passing?

In the first line of the view, you're returning a queryset, not an object. While this queryset will contain only one objec, others constructed using a filter will have multiple members.
To return an object as opposed to a queryset with that line, use either of the following lines:
theadd = adds.objects.get(id=pk)
theadd = adds.objects.filter(id=pk)[0]
You should only ever use the first on unique indexed properties (i.e. id), as it will fail with an error if there is more than one object that matches the criterion.

Related

Why example with "_set" from tutorial didnt work for me?

cat = Category.objects.filter(pk=2)
prd = Product.objects.filter(pk=10)
prd.category_set.set(cat)
When I try run it I get error: object has no attribute "category_set". I want test using of argument "clear=False" from article (https://docs.djangoproject.com/en/3.1/ref/models/relations/)
So I try this and it did not work too.
prd.category_set(cat)
What is wrong? 'Product' model have 'category' field (ManyToMany with related_name='category').
Because you specified related_name='category'. The `related name is the name of the relation in reverse. It also makes not much sense that both the relation and its reverse have the same name. Normally these also should be plural.
If you thus define as models:
class Category(models.Model):
pass
class Product(models.Model):
categories = models.ManyToManyField(
Category,
related_name='products'
)
then you can set the categories of a product with:
cat = Category.objects.get(pk=2)
prd = Product.objects.get(pk=10)
prd.categories.set([cat])
Note that you need to use .get(…) [Django-doc] to retrieve a single object. A QuerySet has no managers like categories for example.
You can also pass clear=True as parameter:
cat = Category.objects.get(pk=2)
prd = Product.objects.get(pk=10)
prd.categories.set([cat], clear=True)

Getting value of a ForeignKey instead ID

I have to pass a ForeignKey object in a json response, im doing it like this:
data = {}
p = Bets.objects.create( bet_id=request.POST['team'],number=number)
data['success'] = p
return HttpResponse(json.dumps(data), content_type='application/json')
bet_id field is a ForeignKey and number is a CharField, if in data['success'] I pass p.number i can pass it with no troubles, but when I pass p.bet_id I get the id of that ForeignKey, I need to get the value, I'm trying with lookup fields with p.bet_id__name but i get the following error:
'Bets' object has no attribute 'bet_id__name'
My models:
class Teams(models.Model):
name = models.CharField(max_length=100)
class Bets(models.Model):
bet = models.ForeignKey(Teams)
number = models.CharField(max_length=255)
how can I achieve get the value instead the id?
You'll want to use:
data['success'] = p.bet.name
Note that this will create a second SQL query against your db to load the Team object tied to p.bet. To save yourself a little bit of overhead, you can change this line:
Bets.objects.create( bet_id=request.POST['team'],number=number)
To this:
Bets.objects.create( bet_id=request.POST['team'],number=number).select_related('bet')

id of object is none after save in django

I'm looping through a list of objects and saving. I need the newly generated id or pointer id right after the save but it is None.
Here is my code:
for category in category_list:
saved_category = category.save()
print saved_category.parentCategory_ptr_id
print saved_category.id
This saves my object after the routine is run, but again, does not give me the id at this line.
here is my model:
class ParentCategory(models.Model):
name = models.CharField(max_length=255)
class Category(ParentCategory):
description = models.CharField(max_length=255)
category list was created like so:
category_list = []
for row in value_list:
category = Category(description=row.description)
category_list.append(category)
return category_list
What am I doing wrong?
The problem is with:
saved_category = category.save()
It needs to be:
category = category.save()
The original saved object in the list is the object that contains the id.
Their is no need of reassign.
category.save()
When you call save() method the object is saved into database and assign id (primary key) to the object.
Saving Objects Django Official
Other same question asked on Stackoverflow and correct answer by Daniel Roseman
I don't think the object will get saved. Seems that the object you are creating lacks sufficient data to satisfy db constraints. You might have used try-catch somewhere, you would have seen the error. Try adding blank=True, null=True to name in ParentCategory or provide a name while creating the object. I hope this works...

Django - sorting object based on user defined order in template

I want the user to be able to order a list of objects in a table using javascript. Then, in a django function I would like to sort those object based on the same ordering, not on an attribute.
Is it possible? I was thinking about passing a list of pk from the template to the view and then ordering the objects according to this list, but I have not found a way to do it yet.
I don't think this is possible with queryset. Try following:
pk_list = [2, 1, 3, 4]
pk2obj = {obj.pk: obj for obj in Model.objects.all()}
objects_ordered = [pk2obj[pk] for pk in pk_list]
pkg2obj is mapping between pk and model instance object. To make a dictionary I used dictionary comprehension.
If you want to omit deleted objects:
objects_ordered = [pk2obj[pk] for pk in pk_list if pk in pk2obj]
Else if you want to replace deleted objects with default value (None in following code):
objects_ordered = [pk2obj.get(pk, None) for pk in pk_list]
I've had to solve this exact problem before.
If you want the user to be able to reorder them into a user-defined order, you can easily define a field to store this order.
As you say, initially, you could serve them in order according to id or an upload_date DateTimeField. But you could also have an PositiveIntegerField in the model, named position or order, to represent the user-defined order.
class MediaItem(models.Model):
user = models.ForeignKey(User)
upload_date = models.DateTimeField(auto_now_add = True)
position = models.PositiveIntegerField()
Whenever a user changes the order on the frontend, the JS can send the new order as an array of objects (ie. new_order = [{"pk":3, "position":1}, {"pk":1, "position":2}, {"pk":2, "position":3}]). The view can look up each instance by pk, and change the position:
for obj in new_order:
media_item = MediaItem.objects.get(pk=obj['pk'])
media_item.position = obj['position']
media_item.save()
Then always query using
objects_ordered.objects.order_by('position')
That's how we managed to do it. If you have more specific questions regarding this approach, feel free to ask in the comments.
Edit:
If the same object can be a member of many different groups or lists, and you want to store the position of the membership within that list, you can achieve this using a through model. A through model is useful when you need to store data that relates to the relationship between two objects that are related. In addition to the MediaItem class shown above, this is what your other models would look like:
class Album(models.Model):
media_items = models.ManyToManyField(MediaItem,
related_name = 'album_media_items',
through = 'Membership')
class Membership(models.Model):
album = models.ForeignKey(Album,
related_name = 'album')
media_item = models.ForeignKey(MediaItem,
related_name = 'media_item')
date = models.DateTimeField(auto_now_add = True)
position = models.PositiveIntegerField()
Then, you could query the Membership instances, instead of the MediaItem instances.
# get id of list, or album...
alb = Album.objects.get(pk=id_of_album)
media_items = Membership.objects.filter(album=alb).order_by('position')
for item in media_items:
# return the items, or do whatever...
# keep in mind they are now in the user-defined order
You can do this:
pk_list = [1,5,3,9]
foo = Foo.objects.filter(id__in=pk_list)
#Order your QuerySet in base of your pk_list using Lambda
order_foo = sorted(foo, key = lambda:x , pk_list.index(x.pk))

Django: construct a QuerySet inside a view?

I have models as follows:
class Place(models.Model):
name = models.CharField(max_length=300)
class Person(models.Model):
name = models.CharField(max_length=300)
class Manor(models.Model):
place = models.ManyToManyField(Place, related_name="place"))
lord = models.ManyToManyField(Person, related_name="lord")
overlord = models.ManyToManyField(Person, related_name="overlord")
I want to get all the Places attached with the relation 'lord' to a particular person, and then get the centre, using a GeoDjango method. This is as far as I've got:
person = get_object_or_404(Person, namesidx=namesidx)
manors = Manor.objects.filter(lord=person)
places = []
for manor in manors:
place_queryset = manor.place.all()
for place in place_queryset:
places.append(place)
if places.collect():
centre = places.collect().centroid
However, this gives me:
AttributeError at /name/208460/gamal-of-shottle/
'list' object has no attribute 'collect'
Can I either (a) do this in a more elegant way to get a QuerySet of places back directly, or (b) construct a QuerySet rather than a list in my view?
Thanks for your help!
The way you're doing this, places is a standard list, not a QuerySet, and collect is a method that only exists on GeoDjango QuerySets.
You should be able to do the whole query in one go by following the relations with the double-underscore syntax:
places = Place.objects.filter(manor__lord=person)
Note that your use of related_name="place" on the Manor.place field is very confusing - this is what sets the reverse attribute from Place back to Manor, so it should be called manors.