I want to do a lookup that spans three model classes. I want to find all the PartListings that match the Specific_part in the ListItem. Say Specific part = Radio, there could be several Radios in the PartListings and I want to return the PartListing id of all of them so that I can get other attributes like quantity.
I have these models:
class SpecificPart(BaseModel):
class PartListing(BaseModel):
specific_part = models.ForeignKey(
SpecificPart, on_delete=models.CASCADE, blank=True, null=True,
related_name="part_listing")
class ListItem(BaseModel):
specific_part = models.ForeignKey(SpecificPart, on_delete=models.CASCADE,
related_name="listitem")
I'm trying to put the lookup under the ListItem class like this:
def item_match(self):
part = self.specific_part
return PartListings.filter(specific_part__specific_part=part)
I tried to set it up as a Lookup that spans relationshipsbut am getting an error that PartListing is not defined. I also suspect that I'm referencing the foreign keys incorrectly. I'm also ok with redefining the models if a One to One would be better.
I am a Django newbie so thanks so much for your help!
You can try like this using reverse relation between SpecificPart and PartListing models:
class ListItem(BaseModel):
...
def item_match(self):
return self.specific_part.part_listing.all()
Related
I am relatively new to Python / Django.
I am trying to create a relationship between food items and the category (name)
they belong:
class Category(models.Model):
options=(
('vegetable','vegetable'),
('fruit','fruit'),
('carbs','carbs'),
('fish','fish'),
('meat', 'meat'),
('sweet', 'sweet'),
('dairy', 'dairy'),
)
name=models.CharField(max_length=10,choices=options,unique=True)
def __str__(self):
return self.name
class Fooditem(models.Model):
name = models.CharField(max_length=50)
category = models.ForeignKey(Category,on_delete=models.CASCADE)
The code above throws error when running migrate:
ValueError: invalid literal for int() with base 10: 'vegetable'
I created some items in the database, is it the reason?
What is the best way to solve this problem?
Thank you,
D
It would fix it, but you may have some unexpected results.
category = models.ForeignKey(Category,on_delete=models.CASCADE)
will be an id pointing to the other model.
You can make name the primary key by changing it to the following:
name=models.CharField(max_length=10,choices=options,unique=True,primary_key=True)
Also reviewing https://docs.djangoproject.com/en/3.1/ref/models/fields/#choices more closely may help you with your options down the road. It will programming easier to define as costants and follow thier syntaxing
I would realy recommend u to do it this way. if there is something that is unclear just let me know
class Category(models.TextChoices):
vegetable='vegetable'
fruit='fruit'
carbs='carbs'
fish='fish'
meat='meat'
sweet='sweet'
dairy='dairy'
class Fooditem(models.Model):
name = models.CharField(max_length=50)
category = models.CharField(max_length=20, choices=Category.choices)```
I have a simple question but multiple google searches left me without a nice solution. Currently I am doing the following:
allowed_categories = self.allowed_view.all().difference(self.not_allowed_view.all())
users = []
for cat in allowed_categories:
for member in cat.members.all():
users.append(member)
return users
I have a ManyToManyField to Objects that also have a ManyToManyField for instances of Users. In the code above, I am trying to get all the users from all those categories and get a list of all Users.
Later I would like the same in a method allowed_to_view(self, user_instance) but that's for later.
How would I achieve this using Django ORM without using nested for-loops?
[edit]
My models are as follows:
class RestrictedView(models.Model):
allowed_view = models.ManyToManyField(Category)
not_allowed_view = models.ManyToManyField(Category)
class Category(models.Model):
name = models.CharField(max_length=30)
members = models.ManyToManyField(User)
So, I've made the following one-liner with only one query towards the database. It took me some time...
users = User.objects.filter(pk__in=self.allowed_view.all().values("users").difference(self.not_allowed_view.all().values("users")))
This gives me a nice queryset with only the users that are in the allowed_view and explicitly not in the not_allowed_view.
Without seeing you database structure / models.py file its hard to say, but you can do a search on member objects like so:
members_queryset = Member.objects.filter(
category = <allowed categories>,
...
)
users += list(members.all())
Hello folks Im new to Django(I have just the finished the tutorial) but I think i understand the basic concepts of it .Im writing here because Im trying to do something "difficult" for my current experience with django and searching the internet didnt give me a solution .What im trying to do is to create a dynamic model based on the number of entries of another model .To be more exact lets say i got the following model :
class criteria(models.Model):
criteria_text = models.CharField(max_length=200)
monotonicity = models.CharField(max_length=1,choices=(('+','ASCEDING'),('-','DESCENDING')),default='+',verbose_name='Monotonicity')
worst = models.IntegerField(default=0)
best = models.IntegerField(default=0)
What i want to do is create all the criteria models instances i want through the django admin panel and then query for all the creteria_text instances in the database and make a model with an attribute for every criteria_text instance.
So lets say I add the following criteria to the database(these are criteria_text attributes of criteria objects: Color,Weight,Price .
I want to end up with a model like this :
class Alternative(models.Model):
Color = models.IntegerField(default=0)
Weight = models.IntegerField(default=0)
Price = models.IntegerField(default=0)
The thing is that in my application this one has to happen a lot of times so i cannot make model each time someone adds an Alternative based on different criteria .
After searching i found that i can define dynamic models using the following format :
attrs = {
'name': models.CharField(max_length=32),
'__module__': 'myapp.models'
}
Animal = type("Animal", (models.Model,), attrs)
So the question is how can I define "attrs" based on a query that gets all the criteria in the database ?Can i define a relationship of this dynamic model with another model ? Also the models already created should be updated if a user adds more criteria .
Is something like this possible ?
If so please show me the path .
I don't think defining dynamic models is a good solution here (or anywhere, really). Rather, you need a relationship that can have as many items as there are criteria instances.
It might be something like this:
class Alternative(models.Model):
name = models.CharField(...)
choices = models.ManyToManyField("Criteria", through="AlternativeChoice")
class AlternativeChoice(models.Model):
alternative = models.ForeignKey('Alternative')
criteria = models.ForeignKey('Criteria')
value = models.IntegerField(default=0)
The real logic will belong in the form, where you will need to create options for each criteria entry, and validate the AlternativeChoice dependent on the related criteria.
So I'm using inheritance in django with the following classes:
class main_menu(node):
"""
main_menu(node)
Has no extra fields. All children of the root node must
be main_menu nodes
"""
# Required for tree hierarchy to work (db_column='path' for raw queries)
_path1 = models.CharField(db_column='path', max_length=Global.MAX_FILE_PATH_LENGTH, unique=True);
main_menu_blah = models.CharField(max_length=30, default='');
def __unicode__(self):
return self.main_menu_blah;
main_menu
class language(main_menu):
"""
language(main_menu)
Main menu used specifically for a main menu targetted
at a speaker of some language.
"""
# Required for tree hierarchy to work
_path2 = models.CharField(db_column='path', max_length=Global.MAX_FILE_PATH_LENGTH, unique=True);
language_blah = models.CharField(max_length=30, default='');
def __unicode__(self):
return self.language_blah;
language
class language2(language):
_path3 = models.CharField(db_column='path', max_length=Global.MAX_FILE_PATH_LENGTH, unique=True);
language_blah2 = models.CharField(max_length=30, default='');
Now, I can insert access all of these models just fine as long. I can also get them using .objects.get(...).
But if I delete a row from a parent class table (such as language which is a parent to language2), then I cannot get() the last row from the language2 table.
I execute:
subNode = language2.objects.get(_path3=);
I always get the following error:
DoesNotExist
language2 matching query does not exist.
And I've looked in the database (sqlite) and I can see that the last entry has in the column _path3.
Furthermore, I can use a raw query (using connection.cursor()) and I can get the last row. But it's only the raw data, and I need a model object. Oh and using .extra() hasn't worked either.
Why can't I get the last row? (until I reboot the server)
Thanks.
EDIT:
The different "_path*" variables are needed for something else, so an abstract base class will not help in my case, but that's another topic.
As for the db_column='path', I have it that way so that raw queries are more streamlined and I have tried removing that (so that the column is "_path1", "_path2", etc), but the issue still persists. The part that is most confusing is that a raw query works, and restarting the server fixes it (until a new row is inserted, then that last one isn't seen).
EDIT2:
So I discovered what was happening. The important thing I forgot was how each of the tables were tied together.
If I have a base class:
class A
A subclass:
class B (A)
Another subclass:
class C (B)
I have tables linked like so:
A -> B -> C
Lets say I have 2 rows in each table (each one representing a instance of the class):
row 1 A: Name="Gerald" -> B: Age="25" -> C: Gender="Male"
row 2 A: Name="Janet" -> B: Age="24" -> C: Gender="Female"
If row two in table B is deleted, there is a break in the link that points to table C.
So I basically chopped of the torso of the class. 1/3 of the data is missing. And so, django reports it as non-existent.
So, be sure you are careful when deleting entries manually. You shouldn't have this issue with django as it should keep track of all of it for you.
First thing I notice is that you have two models that are inheriting from other classes and adding their own fields, but they're using the same db_column. A cleaner way to achieve this (if you're not directly using main_menu) is with an Abstract Base Class.
Effectively, your language2 model has these fields:
_path1 = models.CharField(db_column='path', max_length=Global.MAX_FILE_PATH_LENGTH, unique=True)
_path2 = models.CharField(db_column='path', max_length=Global.MAX_FILE_PATH_LENGTH, unique=True)
_path3 = models.CharField(db_column='path', max_length=Global.MAX_FILE_PATH_LENGTH, unique=True)
main_menu_blah = models.CharField(max_length=30, default='')
language_blah = models.CharField(max_length=30, default='')
language_blah2 = models.CharField(max_length=30, default='')
Also, Python does not require a semicolon at the end of each statement.
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.