limit choices for foreign field based on other field - django

Is it possible to do really dynamic form in AdminModel? I have following models:
class MyModel(models.Model):
firstfield=models.ForeignKey(First)
secondField= models.ForeignKey(Second, blank=True,null=True)
#some other fields
class Second(models.Model):
firstfield=models.ForeignKey(First)
#other fields
As you can see Second is optional. But I want it to limit according to current selection in First? It would require some page refreshing or some ajax work but I simply don't know how to even pass First value. Maybe I should add it to request and then use something similar to:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_foreignkey ?

You can do it through ajax request. If you don't know how it works see the below links.
How to implement two dropdowns dependent on each other using Django and jQuery
Dynamic select fields with JQuery and django

Related

When and where is `Field.blank` checked by DRF?

I have a model
class SomeModel(models.Model):
emails = ArrayField(models.EmailField(), default=list)
And let's say I have the following Serializer of the model:
class SomeModelSerializer(serializers.ModelSerializer):
class Meta:
model = SomeModel
fields = ['emails']
The email field is not blank-able, i.e: It's required to set a value for it when submitting a Form of the model, or when making changes to its Admin page.
My understanding is that DRF relies as well on Django's internal machinery to validate whether emails is missing on the Serializer data or not. But the thing is that I can't find where (and when) this happens.
I've found that DRF is not calling the Model's clean() method anymore (link). But what baffles me is that changing the blank value on the field seems to have a direct impact on the Serializer. I have switched to blank=True, and then the Serializer would allow it to be saved without that field... Then I switched back to blank=False, and the Serializer would fail if emails is not present.
So do you have any idea of when and where DRF checks for a field's blank value?
Thanks!
As far as I know, it simply doesn't. Those are only used across forms and the django admin interface.
I always specify those things on the serializer level, by setting the appropiate arguments for my fields (doc), in this case it would be allow_blank.
I am building REST APIs with django, and the only case where the blank property on the model field catches me, is when fiddling around on the admin page.
However, there appears to be a package that could be of interest to you:
django-seriously.
I haven't used it, but it appears to call full_clean() on every save().
Of course, this has the disadvantage that you will probably loose DRFs nice error messages.

Is there any possibility to add fields inside the fields of a Model

Assume I have a model named MyModel and I have a Field Named field Now I want to add three more fields inside the prescription like one field_a , field_b and field_c .
Does Django Allow that in any way or we have to make another model for this purpose and then link with Foreign Key to MyModel?
Well I think it is an idea that could lead to some really hard to maintain code and should be well thought through.
That aside If you have a look at:
https://docs.wagtail.io/en/stable/topics/streamfield.html
It's a special field meant for cms applications that uses json in the field to model dynamic fields and validations for it.
Also if you run postgres this might help. https://docs.djangoproject.com/en/3.2/ref/contrib/postgres/fields/#jsonfield

django generic view update/create: update works but create raises IntegrityError

I'm using CreateView and UpdateView directely into urls.py of my application whose name is dydict. In the file forms.py I'm using ModelForm and I'm exluding a couple of fields from being shown, some of which should be set when either creating or updating. So, as mentioned in the title, update part works but create part doesn't which is obvious because required fields that I have exluded are sent empty which is not allowed in my case. So the question here is, how should I do to fill exluded fields into the file forms.py so that I don't have to override CreateView?
Thanks in advance.
Well, you have to set your required fields somewhere. If you don't want them to be shown or editable in the form, your options are to set them in the view (by using a custom subclass of CreateView) or if appropriate to your design in the save method of the model class. Or declare an appropriate default value on the field in the model.
It would also work to allow the fields into the form, but set them to use HiddenInput widgets. That's not safe against malicious input, so I wouldn't do that for purely automated fields.
You cannot exclude fields, which are set as required in the model definition. You need to define blank=True/null=True for each of these model fields.
If this doesn't solve your issue, then please show us the model and form definitions, so we know exactly what the code looks like.

Django dynamic form & ordering of fields

I have a form for logging a 'ticket' to a department.
It is a dynamic form which has additional custom fields depending on the form category/department.
Each ticket has standard fields such as title, date, content. Some have fields called custom_acbdef which allows department to ask additional questions on their forms.
These additional fields always appear at the bottom of the form which is OK at the moment. (I add the model form then just loop trough additional fields and add them to self.fields)
Now, I want to add an additional standard field called 'PDF attachment' but I want this to always appear at the bottom of the form. The problem at the moment is all standard fields appear at the top and custom fields appear at the bottom.
class Meta:
model = Ticket
fields = ('ticket_category','ticket_branch','ticket_content', 'ticket_attachment1')
So in the above, I'd want all to insert all my custom fields inbetween ticket_content and ticket_attachment. Any ideas how I can do this? All the custom form fields have dynamic field names but always start with 'custom_'
When things start to become unmanageable inside my forms __init__, I generally take one of the following approaches:
Create a Factory
Leveraging closures, write a function to build out the fields dynamically then return that class.
def TicketForm():
fields = ['title', 'date', 'content']
for custom_field in custom_fields:
fields.append(custom_field)
fields.append('ticket_content')
fields.append('ticket_attachment1')
class _TicketForm(forms.ModelForm):
class Meta:
model = Ticket
fields = fields
return _TicketForm
Multiple forms
I'll create several different forms based on the use case, then within my view determine which one should be returned. I posted an example of this yesterday.
For further reading, check out a post by James Bennett (django core dev) regarding dynamic forms.
I know it's an old post but recently has been published a
package that fulfills this purpose.
It allows to define new fields on-the-fly and populate them in forms and database in a very simple way.
Here is the link
dinadata by undersat package

Django Two Way relationship

I am building a blog site and have models in respect of Category and Posts. Posts have a Many to Many relationship for Category.
class Post(models.Model):
categories = models.ManyToManyField(Category)
Everything is working fine aside from the fact that in the Category list in the template I only want to load categories that actually have posts.
If a category is empty I don't want to display it, I have tried to define a relationship in Category to Post to allow me to use something like {{ if category.posts }}. At the moment using another Many to Many field in Category is presently giving me an extra field in admin which I don't really want or feel that's needed.
How is best to navigate this relationship, or create one that's suitable?
Cheers
Kev
Django automatically creates a field on the related model of any ForeignKey or ManyToMany relationship. You can control the name of the field on the related model via the related_name option like that:
class Post(models.Model):
categories = models.ManyToManyField(Category,related_name='posts')
This way, your approach works without any additional fields. Btw, if you leave out the related_name argument, Django will create by default one with [field_name]_set.
You can use reverse relations on ManyToMany fields. In the reverse filter, you must use the related model name (if you did not use related_name attribute). So in your question you can use model name as the reverse name like:
{% if category.post %}
You can also use this in your filtering functions in views:
Category.objects.filter(post__isnull=False)
Reverse relation name must be lowercase.
Check the documentation here