django form with multiple choice field with potentially infinite choices - django

I have a model with a many-to-many field that will expand as the user adds more entries for the model. In the form template if I use the conventional {{ form.field }} I get a multiple choice select as is expected, but the problem that will quickly become apparent is when there are 10, 100, 1000 or more choices. What I'd like to provide in the form is a search field where the user can search through all available entries and via AJAX return entries matching their search criteria where they can then select the individual entry choices to be saved in the database.
I'm assuming I will have to manually render the multiple choice form field, but after hours of research I cannot find an example of this anywhere online. Is there an example that exists and I just haven't been able to find? How is one supposed to manually create a form with a multiple choice field in Django? Or am I going about this all wrong?

Related

django view filter ManyToMany field to guard view

I have a tag model, with ManyToMany field "parents" to tag model, to itself. There is also "allowed_users" field.
I need to guard a view in such a way, that the user won't see any tags in parents field, to which he is not allowed.
I try to modify queryset, removing the corresponding tags from parents. But when I change the instance, tag_instance.parents.set(my_new_list) it gets saved automatically so I'm altering the database and changing the real value of the instance.
So the general question is "how to guard my view in such a way, that object's ManyToMany field is filtered by custom logic".
Another question is "how to set manytomany field without altering database", as this would be a solution to the former one.
yes I use DRF
You can use the Prefetch object to filter related table when SQL queries are executed.
For instance:
Tag.objects.preftech_related(Prefetch("parents", queryset=Tag.objects.filter(allowed_users=current_user).distinct()))
This will prefetch "parents" (meaning no additionnal sql query will run when accessing my_tag.parent.all()) and filter parents to keep only those with the current user in allowed_user
Note: Tag.objects.filter(allowed_users=current_user) will duplicate tag entries for each user in allowed_user, ence the .distinct() to keep one of each

Is it better to have an explicit django model field or calculate on demand?

If I have a django model that has an field called 'order' (integer field that tracks the modifiable order of a specific model instance amongst all model instances), and I also want to track the position of the model instance based on that order ('first'/'mid'/'last'), is it better to have another model field called 'position', which I recalculate and store each time there is a change to order, or should I have a model method called 'get_position' which I call each time I need a position. I'm trying to work out which is more efficient. Whilst I won't need the position information each time I create/delete/modify a instance order, I will need that position field quite a bit within my templates.
Generally avoid creating an additional database fields if something can be calculated from data already in the db, to prevent redundancy and reduce vectors for errors.
A method may work if its relatively simple, deriving its value from an existing field within the record. If it needs to look up comparative values from other records that would be an efficiency issue.
As you mention use in templates specifically, it may be worth seeing if the template builtins can meet your requirements.
Say your recordset is already in order of the 'order' field eg,
MyRecords.objects.order_by('order')
When looping through MyRecords_context in a template using a for loop, you can test for {{if forloop.first}} or {{if forloop.last }} - you can also refer to MyRecords_context.first() and .last() to single those out. If you need the specific index of a given record in that particular recordset for you template, you can refer to {{ forloop.counter }} eg {{if forloop.counter < 10 and forloop.counter > 5}} or {{if forloop.counter == 5}}
The advantage of this approach is that if you have a filtered a subset of your records, you are still referring to the first, last or Nth records of the recordset, even though they may not be first and last overall in your absolute position field, and with no additional db calls.

Editing of django form with primary key fields

I have a django model form for which I allowed partial form save since its a long form. Now I want the user to come back and complete the form later.
There is one hindrance however that my database cannot accept duplicate entries with same primary key. So should I remove primary key in my database to solve this or is there another way to make it possible? Suggestions please.
Why not keep only one row per user for that form? Just add one boolean field to check whether the form is submitted or is a draft. Something like is_submitted=models.Boolean(default=False). Keep updating the row with the new values on each partial save (a separate button for Save or an AJAX call for auto save).
When the form is submitted, just mark the field is_submitted = True and perform whatever actions you want after that.

Django - Field by Field Restrictions on Which Users Can view Certain Fields

I'm learning Django and building a simple CRUD application. I have a model for cars, and this contains a number of fields. When a user loads a car page, I'd like some fields to be displayed and others hidden, depending on whether the user has a high enough score for the car they are viewing. So for each field (engine, wheels, headlights, etc), or for some groups of fields, there would be a corresponding visibility score. If the user's score for that particular car exceeded the visibility for a particular field, then the data for that field would be displayed in the view.
I could add a DecimalField variable for each component to denote this minimum score, the Car model would have a calc_score(user) method. In the view the current user's score would be compared against each of these, but I'm guessing there may be a better way to do this. Can anyone recommend a better approach?
Thank you.
You should just pass in the user's score as context when rendering the page from your views.py. It would look something like this:
def car_page_view(request):
current_user_score = getUserScore()
context = {
'user_score': current_user_score
}
return render(request, 'car-page.html', context)
Then, in your html, put a check like this to only show certain elements:
{% if user_score > 10 %}
<text>This text is only visible to users with scores higher than 10.</text>
{% endif %}
This is better than, say, loading all html elements and setting certain elements to "hidden". Instead, this causes the html you want hidden to never be loaded at all. So even if they use the inspect tool they won't see it :)

how to obtain two different search results from single query in django haystack with solr

I have one search box where users can search for either the movie name or actor. On the search results page I want to show the top hits for both the actor and for the movie name in separate tables. How is this done with Django Haystack over SOLR?
Thanks!
This post is old but I stumbled over it because I wanted to do the same thing. Like Mauricio Scheffler said you have to make two queries. In haystack you can specify witch model is queried:
query1 = SearchQuerySet().filter(content="something").models(Actor)
query2 = SearchQuerySet().filter(content="something").models(Movies)
If both values are in one table or the tables are related. You can place the results you want in the template.
{{ movies.object.actor }}
{{ movies.object.name }}
Don't know about haystack, but from a Solr point of view you'll have to run one query for actors and another query for movies.