Creating a nested form field or something like that - django

I'm not entirely sure about the correctness of the question. In fact, I doubt whether I can express exactly what I am looking for.
Question: How can I create additional fields based on the previous selection before submitting the form?
Let's take the number of pets and the name of the pet in our example. I want how many pet names to be entered first
class UrlForm(forms.Form):
INT_CHOICES = [(x, x) for x in range(11)]
number_of_pets = forms.ChoiceField(choices=INT_CHOICES)
and then create as many Charfield fields as the selected value based on the previous selection:
#new fields as many as the number of pets
pet1 = forms.CharField()
pet2 = forms.CharField()
Of course, the variable name issue is a separate issue.
Question 2: As an alternative approach, can I create a pet name field like a tag field? As in the image:
Image taken from here. The question is appropriate but a ReactJs topic.
You can share the topic, title, term, article, anything that I need to look at. Thanks in advance.
Edit:
The pet example is purely fictional. Influenced by the image, I used this topic.

Related

Storing answers to questionnaire in Django model

I have a django model that should store users's answers to a questionnaire. There are many types of questionnaires, but one could be simple like this (many are more complicated though):
What is your name?
What is your age?
What is your height?
What is your age?
I want to know how I could create a model to store the data that was submitted in the form. Right now, I am using a simple JSON field like this:
from django.contrib.postgres.fields import JSONField
data = JSONField(default=dict)
This gets difficult however when the questionnaire get much longer. What would be the best way to do this? If a JSON field is the best way, how should I structure the json assuming there could be different types of questions (input field, multiple choice, etc.)? Thanks!!
When dealing with JSONField in postgres, main thing to keep in mind is disk space. Since, in JSON we have to store both key and value as compared to a normal field where key is already defined and we don't have to store it in every row. So basically what you can optimize is key which I think can be an id of question number rather than complete question.
Basically, You can have question model as follow:
Question(models.Model):
content = models.CharField(max_length=100)
and you can have your JSON data as follow:
{
<question_id_1> : "Answer 1",
<question_id_2> : "Answer 2"
}
This will save a lot of space, although you will have to do a mapping after fetching data but it will be less pressure on your database and more efficient. Since, you don't have fixed type of answer type, you can just save value in JSON and later infer its sense based on question_type, for e.g. whether answer value is a id value of multi choice answer field or just a sentence as an answer. For that you can have a type field in question, that will help you with that after fetching results.
Another thing you can do is rather than storing it in JSON Field, you can have a different table where you have foreign key to question as follow:
Answer(models.Model):
question = models.ForeignKey("Question", on_delete=models.CASCADE, related_name="answers")
content = models.CharField(max_length=200)

Let user create variables (and their data-type) - Django

I am trying to write a Django app that does the following:
A user sees various articles and then codes variables against these articles.
i.e.:
Article is about Egypt.
User assigns: country = Egypt
This, so far, is easy.
What I would love to have, though, is that the user can create the variables himself, without me having to hard-code them into models.
How do I best do this?
Should I use the through-relationship on a manytomany-field or are there other, better, ways to do this?
If I use the through-relationship, how can I let the user choose what data-type the variable should be?
Should I put a field for every fieldtype into the through-model and then have the user choose it somehow?
I know, this is more than one question, but if you answer my first question I would be very happy!
I am assuming that by "user" you mean other apps that are based on the app that contains Article.
Use model inheritance:
https://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance
class Article(models.Model):
pub_date = models.DateTimeField(...)
class CountryArticle(Article):
country = SomeSuitableModel()

Multi field and computed value

I need a solution for this problem:
I would like to have MultiField widget for a "value" field. This field should allow to input two values (two input widgets), and user should choose which of these values is to be saved (two checkbox widgets). However, one of these values must be recalculated with respect to other field's value.
I've taken this approach:
a MultiValueField with 4 fields:
class PriceDetailField(MultiValueField):
use_net = BooleanField(required=False)
net_value = DecimalField(required=False, decimal_places=2)
use_gross = BooleanField(required=False)
gross_value = DecimalField(required=False, decimal_places=2)
a MultiWidget:
class PriceDetailWidget(MultiWidget):
use_net = CheckboxInput()
net_value_widget = TextInput()
use_gross = CheckboxInput()
gross_value_widget = TextInput()
and a custom Form...
class PriceModelForm(ModelForm):
value = PriceDetailField()
...which overrides default model form for a model:
class Price(models.Model):
value = models.DecimalField(
max_digits=19,
decimal_places=2,
default=Decimal(0),
)
However, this solution seems to be messed up. In the form, I need to input all subfields (the MultiValueField subfields), otherwise "Please enter value" error appears (even though those fields are marked as required=False). Also,
I must recalculate the mentioned value upon a save, having returned a tuple from the field with information which checkbox was checked and the corresponding text value, then replace the tuple with the decimal value in clean_value method of form (also, saving the checkboxes state in temporary fields....). I think such a design is very weak.
The form should work both on its own and as inline (this means, the value of the field which is used to calculate the returned value can or cannot change during save).
Is such a thing even possible?
And the root of the problem: I want to store prices of items as net prices, but I would like to allow users to input them as net or gross prices, and then recalculate gross price to net price with respect to product's VAT tax level (since VAT is assigned to product or service, not to the price). A product can have many prices, so a price is backlinked to the product by a foreign key.
Cheers,
Tomek
The feature you're looking for on a MultiValueField (allowing the sub-fields to be required or not individually) is logged as a feature request on Django.
You could probably fix this for now by subclassing MultiValueField with a rewritten clean method based on the original and following suggestions from the bug report. You're not going to have a lot of the original MultiValueField left by that point though, and if you do, you should submit your patch to Django and put a note on the bug.
Ignoring for a moment the requiredness thing, have you written a compress method on your PriceDetailField? What does it look like? This is where you should be doing the work to turn your four sub-fields into a single field to save.

Django admin many to many table name

Can I specify the name I want for the many to many table?
Yes. See Table Names for all of the exciting details.
Update: OK, then perhaps the related_name option is what you are looking for. There are some caveats covered here.
Updatex2: OK, Kelvin gets a star for answering his own question! It's been an age since I perused the Django Meta Model Options, but, in retrospect, that's where we should have started.
BTW, wandering through the django/db/ code on only half a cup of coffee is definitely a challenge.
You define the table name using the db_table option when declaring the ManyToManyField attribute. See example below:
class revision(models.Model):
revision_id = models.AutoField(primary_key=True)
issue_list = models.ManyToManyField(issue, related_name='revisions', db_table='issue_revision')
related_name is the field by which this class will be seen by issue, meaning, you will access it as my_issue.revisions(). And the table being used in the DB is named issue_revision.

Does order of declaration matter in models.py (Django / Python)?

I have something like this in models.py
class ZipCode(models.Model):
zip = models.CharField(max_length=20)
cities = City.objects.filter(zip=self).distinct()
class City(models.Model):
name = models.CharField(max_length=50)
slug = models.CharField(max_length=50)
state = models.ForeignKey(State)
zip = models.ManyToManyField(ZipCode)
When I do this I get:
NameError: name 'City' is not defined
Is this because the order of declaration matters? And if so, how can I do this, because either way I arrange this, it looks like I'm going to get a NameError.
Thanks.
Apart from order issues, this is wrong:
cities = City.objects.filter(zip=self).distinct()
It is not inside a method, so "self" will also be undefined. It is executed only once, at class-creation time (i.e. when the module is first imported), so the attribute created would be a class attribute and have the same value for all instances. What you might be looking for is this:
#property
def cities(self):
return City.objects.filter(zip=self).distinct()
Because this is inside a method, which is not executed until it's accessed, ordering issues will no longer be a problem. As ozan points out, this is a duplication of what Django reverse relations already give you for free:
a_zip_code.city_set.all()
And you can use related_name to call it what you like:
zip = models.ManyToManyField(ZipCode, related_name='cities')
...
a_zip_code.cities.all()
So I don't think the ordering issue you originally asked about is even relevant to your situation. When it is, others have already pointed out using quoted strings in ForeignKey and ManyToManyField declarations to get around it.
When you have references to classes defined after, you can use this trick:
attribute = models.ForeignKey('ClassDefinedAfterThis')
Yes order does matter as others have noted.
Though, encountering this issue is almost always going to be an indication that you're doing something wrong.
In this case your declaration:
cities = City.objects.filter(zip=self).distinct()
... is both redundant and bad practice. You can find the cities related to a zip code by referring to that zip code's city_set in your views (ie not in your model!). So if zip is an instance of ZipCode, you would do:
cities = zip.city_set.all()
If you really want to call it 'cities' rather than 'city_set' you can use the related_name parameter in your m2m declaration.
I was once worried about order... because I thought my models below could only reference models above. But then realized that you can just do a
models.ForeignKey('appName.modelName')
and all was fine.
Yes, order does matter, but your example does not look right to me. I think you should just be using a foreign key for your many-to-one relationship:
cities = models.ForeignKey(City)
This has the details on many-to-one relationships with django models.
Edit:
It was pointed out to me in the comments that cities in Europe might have several cities in the same zip code. If you are looking for a many-to-many relationship here, you should use:
cities = models.ManyToManyField(City)
This is described in Django's documentation. The point is, this is either of these examples are much more clear than what is used in the example.
Order matters in Python. This thread may be relevant to your question. Also for your uses, you may want to use a unique foreign key in the ZIP code class.