In Django, I would like to have an ordered many-to-many-relation. Assume I have, say, the models OrderedList and Item, and I want to be able to insert Item()s into an OrderedList() at a specific index, I want to be able to retrieve the Item()s of an OrderedList() in their order and also to change the order of Item()s on an OrderedList
I already found Define an order for ManyToManyField with django and https://github.com/gregmuellegger/django-sortedm2m
Both the github repo and the accepted answer in the SO question are working with the same architecture: They create an additional integer field, say order_index, on the junction ("Through") table which represents the position of the Item() on the OrderedList().
Honestly, I do not like that too much. If I see this correctly, having the order stored on the junction table can create inefficiency when I want to reorder Item()s: Imagine, I want to change the position of an Item() on an OrderedList() which has n Item()s. This means O(n) database updates to reorganize the order indices.
I would like to avoid this. I think of an architecture where I have an ordinary many-to-many-relation and one additional column on the OrderedList table which holds a list of Item ids, say items_order. In this architecture, I need one database update and one list operation on items_order - which should be way faster, I guess.
I believe the best way for this is to create a custom model Field. The docs state how to create a custom model Field (https://docs.djangoproject.com/en/2.1/howto/custom-model-fields/) and I can create my items_order field like this. But I did not find how to make a custom Field which, besides creating the order_list, also creates the junction table and takes care of updating the items_order whenever a new related Item() is added or removed from the relation. I think, I should subclass the ManyToMany Field (https://docs.djangoproject.com/en/2.1/_modules/django/db/models/fields/related/#ManyToManyField). But I don't know how to do this, so could you give me some guidance here?
Related
I have a model that retrieves data from a table in a database from a certain SQL query, and shows the items in a QTreeView. The characteristics are:
the data comes from a table, but has an underlying tree structure (some rows are parents that have rows below them as children)
this tree structure is shown in the QTreeView
the children are selectable in the QTreeView (not so the parents)
the table in the database gets updated continuously
in the updates, a children can be added to any existing parent
periodically (with a QTimer) the QTreeView is updated with the contents of the table
Since the children are added at any time to any parent, the first silly approach when updating the QTreeView is clearing it all, and append all the rows again, in form of parent or children, to the QTreeView. This is a 0-order approximation, and it is indeed terrible inefficient. In particular, the following problems appear:
Any existing selection is gone
Any expanded parent showing its children is collapsed (unless ExpandAll is active)
The view is reset to show the very first row.
What is the best solution to this problem? I mean, the first solution I will try will be not to clear the QTreeView, but instead parse all the returned rows from the table, and check for each of them whether the corresponding item in the QTreeView exists, and add it if not. But I wonder if there is a trickiest solution to engage a given table in a database with a QTreeView (I know this exists for a QTableView, but then the tree structure is gone).
This thread mentions a general approach, but this might get tricky quickly, but I am not sure how this would work if the underlying model is changing constantly (i.e. the QModelIndex becoming invalid).
Worst case is that you will have to write your own mechanism to remember the selection before updating and then re-applying it.
I assume you use some model/view implementation? You could enhance your model with a safe selection handling, in case the example mentioned above does not work for you.
I guess this is the case for a self-answer.
As I presumed, after a careful analysis of what data is retrieved from the database, I had to do the following "upgrades" to the retrieval code:
I retrieve, along with the fields I want to show in the view, two identifiers, one for grouping rows and one for sorting items into groups
I also retrieve the internal record ID (an increasing integer number) from the table in the database, in order to ask only for new records in the next retrieval.
In the model population code, I added the following:
I first scan the initial records that may belong to existing groups in the model
When, in the scanning, I reach the last group in the model, this implies that the rest of retrieved records belong to new groups (remember the records are retrieved sorted such that items that belong to the same group are retrieved together)
Then start creating groups and adding items to each group, until we use all the records retrieved.
Finally, it is very important:
the use beginInsertRows() and endInsertRows() before and after inserting new items in the model
capture the sorting status of the view (with sortIndicatorSection() and sortIndicatorOrder()) and re-apply this sorting status after updating the model (with sortByColumn())
Doing that the current position and selection in the QTreeView receiving the model updates are preserved, and the items in the view are added and the view updated transparently for the user.
So I have a list of unique pupils (pupil is the primary_key in an LDAP database, each with an associated teacher, which can be the same for several pupils.
There is a box in an edit form for each teacher's pupils, where a user can add/remove an pupil, and then the database is updated according using the below function. My current function is as follows. (teacher is the teacher associated with the edit page form, and updated_list is a list of the pupils' names what has been submitted and passed to this function)
def update_pupils(teacher, updated_list):
old_pupils = Pupil.objects.filter(teacher=teacher)
for pupils in old_pupils:
if pupil.name not in updated_list:
pupil.delete()
else:
updated_list.remove(pupil.name)
for pupil in updated_list:
if not Pupil.objects.filter(name=name):
new_pupil = pupil(name=name, teacher=teacher)
new_pupil.save()
As you can see the function basically finds what was the old pupil list for the teacher, looks at those and if an instance is not in our new updated_list, deletes it from the database. We then remove those deleted from the updated_list (or at least their names)...meaning the ones left are the newly created ones, which we then iterate over and save.
Now ideally, I would like to access the database as infrequently as possible if that makes sense. So can I do any of the following?
In the initial iteration, can I simply mark those pupils up for deletion and potentially do the deleting and saving together, at a later date? I know I can bulk delete items but can I somehow mark those which I want to delete, without having to access the database which I know can be expensive if the number of deletions is going to be high...and then delete a lot at once?
In the second iteration, is it possible to create the various instances and then save them all in one go? Again, I see in Django 1.4 that you can use bulk_create but then how do you save these? Plus, I'm actually using Django 1.3 :(...
I am kinda assuming that the above steps would actually help with the performance of the function?...But please let me know if that's not the case.
I have of course been reading this https://docs.djangoproject.com/en/1.3/ref/models/querysets/ So I have a list of unique items, each with an associated email address, which can be the same for several items.
First, in this line
if not Pupil.objects.filter(name=name):
It looks like the name variable is undefined no ?
Then here is a shortcut for your code I think:
def update_pupils(teacher, updated_list):
# Step 1 : delete
Pupil.objects.filter(teacher=teacher).exclude(name__in=updated_list).delete() # delete all the not updated objects for this teacher
# Step 2 : update
# either
for name in updated_list:
Pupil.objects.update_or_create(name=name, defaults={teacher:teacher}) # for updated objects, if an object of this name exists, update its teacher, else create a new object with the name from updated_list and the input teacher
# or (but I'm not sure this one will work)
Pupil.objects.update_or_create(name__in=updated_list, defaults={teacher:teacher})
Another solution, if your Pupil object only has those 2 attributes and isn't referenced by a foreign key in another relation, is to delete all the "Pupil" instances of this teacher, and then use a bulk_create.. It allows only 2 access to the DB, but it's ugly
EDIT: in first loop, pupil also is undefined
Is it possible to choose only specific items from the list in selectOneMenu?
For example. I have List Products has many fields like name, id etc. One of it is category (1,2 or 3) I want to have only one category in the selectOneMenu without making new Lists and new classes. Can you help me?
I think the easiest way is to set the value attribute of f:selectItems to a method which filters your original collection.
Otherwise you'd have to implement your own version of f:selectItems which allows filtering - as we once did in one of our projects.
Simply put, i want to create a structure that has a component MAKTX, and to have a foreign key relation with MAKT-MAKTX.
More generally i want to have a foreign key check for a field that's not part of a primary key.
I see the button "Non-key-fields/candidates", but i don't really know how to use it.
Also, i don't want to use the "key fields of a text table" relation... but i don't know if that's relevant.
Is this even a good thing that i'm trying to do? I don't see any reason why it shouldn't be possible, but you might object.
[EDIT]: I have to mention that I don't really know what I'm doing. I really just want to fill a table i created with values from another, and to make sure that those values (namely MAKTX - kind ofvalues) in my table are always values from MAKT. Suppose i do the initial filling with a SELECT statement, i want the consistency to work even if i later insert new entries manually.
So I don't know whether this makes sense or not, it just sounds to me like a good idea to have the system perform this check automatically, if possible.
Main condition for creating foreign key relation is that the field should be a primary key in your reference table. While in the table you are creating foreign key its not necessary that the field is a primary key or not. The main reason for this is that foreign key cant be null.
Refer to below link for step by step process for creating foreign key relation in abap.
http://learnabaponline.blogspot.in/2013/04/how-to-create-table-in-abap.html
First off, I agree with vwegerts's comments, what you're trying to do doesn't seem to make any sense.
Perhaps this would make more sense: create your own table without the MAKTX field. Then create a database view, joining your table and the MAKT table (and set a default language in the selection conditions if you want to). This way you'll have the descriptions joined with your data, without duplicating the actual data (which is what it looks like you're trying to do).
I'm working on a C++/Qt project. I have two business models (one is a hierarchical tree-like structure, i.e. film categories/sub-categories, and the other one is a simple vector, i.e. film titles which can belong only to a subcategory) and I want to display both in a unique tree-view, where leaf nodes can belong to both models and non-leaf nodes belong to the first model. In addition to this view, I also want to display in model specific views, a tree-view for the first model and a list view for the second one.
I've considered 3 approaches:
1) Create one QAbstractItemModel for each business model and another one to represent the mixed model. Thus, each view is associated with only one model.
2) Create only two QAbstractItemModel for each business model and implement a special view that deals with that information.
3) Use a QStandardItem model and implement subclasses of QStandardItem for both my business model elements.
Because I'm working with external data, I don't want to duplicate any information if possible.
What do you think is the best/proper approach to follow? Any implementation advices?
QDataWidgetMapper is your best bet in that one.
Make one model of your data. I would make one tree model, which is option c of your choices, but could be implementing your own tree model.
For the list view, see if you can't set the tree model on it as well, and use setRootIndex to only show the list of items you want to see. I know it works on table and tree views, so I assume it would also work on a list view.