I'm trying to build a conditional form where selecting one option will cause a new field to appear underneath, while selecting another option will display something else.
Formstack has a good example https://www.formstack.com/features/conditional-logic
I couldn't find any preexisting form packages for django with this functionality. How should I start implementing this?
Django forms (especially if you use the ModelForm library) are a direct reflection of your Django application Model. You should therefore start by refactoring your Django application Model to have fields that have optional values (i.e. they can be NULL, empty or have a default value already created).
These would be the form fields that are shown/hidden based on your conditional(s) and they may or may not have values (if they are hidden based on a conditional it is impossible to provide a value to them so the Model fields must be able to accept NULL values or use the defaults).
You would then use a client-side language such as Javascript (JS) to handle the user iteraction with your Django application. A simple to use JS framework like jQuery would be worthwhile investigating for your needs.
In addition to the exceptional Django docs on Forms, I also highly recommend you take a look at Django Crispy Forms writtten by PyDanny to see how Django forms should be done right.
Related
Currently, I am using node as backend and looking forward to shift my project to django-rest-framework. In node I used firebase-auth and MySQL and have a table called FIREBASE_USERS with email and firebase_uid fields. I was thinking of building my own custom auth for drf but can't figure out on using my FIREBASE_USERS table instead of django Users model. I read that django provides settings. AUTH_USER_MODEL to set your own custom model but the documentation uses AbstractUser class to create that and I don't want to mess with my tables since the tables are used in other projects too. Any suggestions would be appreciated.
Your custom user model needs to contain the properties as described in (1). AbstractBaseUser is a shortcut to achieve this. Override the Meta.db_table to match you table name. If this is somehow not sufficient, consider creating your own authentication backend as described in (2) and create a django user with a foreign key to your firebase user. But in order to let django function properly your user model needs to have the methods as described in (1).
Maybe (3) solves your problem?
(1) https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#django.contrib.auth.models.CustomUser
(2) https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#writing-an-authentication-backend
(3) https://github.com/fcornelius/django-firebase-auth
I am trying to add a non-model form in django admin interface and am not able to find any particular way to do it. This form would do some processing and change some data in the DB. But this is not related to a particular Model and should stand out. This form should not be available for the user to use.
One thing I can do is add the form to the general view and prohibit using permissions but I was thinking since django admin interface already exists, it would be better to add that to the django admin interface.
Is this possible to do in Django?
You can add arbitrary views that within a ModelAdmin that do whatever you want. See the documentation for ModelAdmin.get_urls. You can do the same at a higher level by defining AdminSite.get_urls.
This scenario happens way too often in my project:
someone adds a model Foo that has several ForeignKey fields, one of them to refers to model Bar
an admin is added for that model (and works OK)
the code is deployed
on production server, Bar has millions of instances
someone accesses Foo's admin page; Django tries to retrieve all Bars at once (to display them in a combo box) and the server gets overloaded
later the problem gets fixed by editing Foo's admin and adding bar to raw_id_fields.
I'd like to prevent this situation from happening in the future, preferably by somehow stating (once and for all) that Bar has many rows and it should be always treated as if the field referring to it was listed in raw_id_fields in all admin pages. Is this possible somehow?
This is an excelent point. This is a critical issue that can turn down the database and even the web server.
Considering this, I believe the default approach MUST be the raw_id_fields thing. If you know what you are doing, then you change this behavior.
Unfortunately, most of the authors of the admin interfaces libraries disagree of this thought. Not just for Python-Django, but also for other communities like Ruby-Rails.
5 years ago I got tired having the same problem, then I developed the django-smart-autoregister, that do this and also auto configure using another good patterns. Even today I face this problem, so I guess it is worth to take a look.
ps: the library was originally implemented using a modular approach, though you just call some functions that will configure the raw_id_fields for you according to the model field.
From the docs:
ForeignKey is represented by django.forms.ModelChoiceField, which is a
ChoiceField whose choices are a model QuerySet.
ModelChoiceField extends Field, and therefor has a widget property that can be abused
https://github.com/django/django/blob/master/django/forms/fields.py#L49
Add this somewhere in your project files.
from django.forms import ModelChoiceField
from django.contrib.admin.widgets import ForeignKeyRawIdWidget
ModelChoiceField.widget = ForeignKeyRawIdWidget
downside: this is also going to happen on non-admin forms
I've been searching stack overflow and google for a solution for over an hour now, and I can't seem to find something that, in my opinion, should be easy to obtain (as it's a common use case).
I've checked this thread, and a few others, but I haven't been able to find a real, easy solution:
Django modelform: is inline adding related model possible?
Anyway, say I have a model with three related entities, two foreign keys and a many-to-many related class. Now, I have a ModelForm which displays these in comboboxes and lists, but what I need is that "+" button next to these elements (as seen in the admin interface).
I want the plus to take me to a new form, for that particular entity, allow me to submit the new information, create the database entry, take me back to my original form and have the newly added entity selected in the combobox. I'm really hoping the django ModelForm Meta class has an attribute that I can't seem to find which enables exactly this.
This isn't really a django question.
This has to do with presentation of a particular widget in an html document, and that is governed by either the HTML markup, CSS, or javascript.
Django is a server side application and is primarily responsible for creating a valid http response and receiving a valid http request (of course, there is a lot that happens in the interim and that is why django is so big) but it's not a "one toolkit to kill them all" app.
I think you want to look at bootstrap: http://getbootstrap.com/
Jquery UI: http://jqueryui.com/
Or some combination of the two.
You can also just mark up the document yourself with a stock img or something.
However, if you want to do it exactly how the admin does it, just go into django.contrib.admin and examin the code to figure out how the django developers did it. I believe they are just using Jquery UI and some manual markup to accomplish that.
In django, https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships, span relationships provide an easy way in django to do a JOIN. Is there a way in the template to do this (using template tags)?
You could do that, I think, because when you write a custom template tag you can import models and run queries on them just as you can anywhere else. But it violates the separation of business logic and presentation that Django's model-view-controller (or model-view-template) design works hard to preserve. Why not do your query in a view and pass the results to a template via the template's context?
If you are asking whether Django comes with a pre-built way to do this, the answer is no. The people who created Django want you to run queries in your views.